View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.regionserver;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.hbase.RemoteExceptionHandler;
25  import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
26  import org.apache.hadoop.hbase.regionserver.wal.LogRollListener;
27  import org.apache.hadoop.hbase.util.Bytes;
28  
29  import java.io.IOException;
30  import java.util.concurrent.atomic.AtomicBoolean;
31  import java.util.concurrent.locks.ReentrantLock;
32  
33  /**
34   * Runs periodically to determine if the HLog should be rolled.
35   *
36   * NOTE: This class extends Thread rather than Chore because the sleep time
37   * can be interrupted when there is something to do, rather than the Chore
38   * sleep time which is invariant.
39   */
40  class LogRoller extends Thread implements LogRollListener {
41    static final Log LOG = LogFactory.getLog(LogRoller.class);
42    private final ReentrantLock rollLock = new ReentrantLock();
43    private final AtomicBoolean rollLog = new AtomicBoolean(false);
44    private final HRegionServer server;
45    private volatile long lastrolltime = System.currentTimeMillis();
46    // Period to roll log.
47    private final long rollperiod;
48  
49    /** @param server */
50    public LogRoller(final HRegionServer server) {
51      super();
52      this.server = server;
53      this.rollperiod =
54        this.server.conf.getLong("hbase.regionserver.logroll.period", 3600000);
55    }
56  
57    @Override
58    public void run() {
59      while (!server.isStopRequested()) {
60        long now = System.currentTimeMillis();
61        boolean periodic = false;
62        if (!rollLog.get()) {
63          periodic = (now - this.lastrolltime) > this.rollperiod;
64          if (!periodic) {
65            synchronized (rollLog) {
66              try {
67                rollLog.wait(server.threadWakeFrequency);
68              } catch (InterruptedException e) {
69                // Fall through
70              }
71            }
72            continue;
73          }
74          // Time for periodic roll
75          if (LOG.isDebugEnabled()) {
76            LOG.debug("Hlog roll period " + this.rollperiod + "ms elapsed");
77          }
78        }
79        rollLock.lock(); // FindBugs UL_UNRELEASED_LOCK_EXCEPTION_PATH
80        try {
81          this.lastrolltime = now;
82          byte [][] regionsToFlush = server.getLog().rollWriter();
83          if (regionsToFlush != null) {
84            for (byte [] r: regionsToFlush) scheduleFlush(r);
85          }
86        } catch (FailedLogCloseException e) {
87          LOG.fatal("Forcing server shutdown", e);
88          server.checkFileSystem();
89          server.abort("Failed log close in log roller", e);
90        } catch (java.net.ConnectException e) {
91          LOG.fatal("Forcing server shutdown", e);
92          server.checkFileSystem();
93          server.abort("Failed connect in log roller", e);
94        } catch (IOException ex) {
95          LOG.fatal("Log rolling failed with ioe: ",
96            RemoteExceptionHandler.checkIOException(ex));
97          server.checkFileSystem();
98          // Abort if we get here.  We probably won't recover an IOE. HBASE-1132
99          server.abort("IOE in log roller", ex);
100       } catch (Exception ex) {
101         LOG.error("Log rolling failed", ex);
102         server.checkFileSystem();
103         server.abort("Log rolling failed", ex);
104       } finally {
105         rollLog.set(false);
106         rollLock.unlock();
107       }
108     }
109     LOG.info("LogRoller exiting.");
110   }
111 
112   private void scheduleFlush(final byte [] region) {
113     boolean scheduled = false;
114     HRegion r = this.server.getOnlineRegion(region);
115     FlushRequester requester = null;
116     if (r != null) {
117       requester = this.server.getFlushRequester();
118       if (requester != null) {
119         requester.request(r);
120         scheduled = true;
121       }
122     }
123     if (!scheduled) {
124     LOG.warn("Failed to schedule flush of " +
125       Bytes.toString(region) + "r=" + r + ", requester=" + requester);
126     }
127   }
128 
129   public void logRollRequested() {
130     synchronized (rollLog) {
131       rollLog.set(true);
132       rollLog.notifyAll();
133     }
134   }
135 
136   /**
137    * Called by region server to wake up this thread if it sleeping.
138    * It is sleeping if rollLock is not held.
139    */
140   public void interruptIfNecessary() {
141     try {
142       rollLock.lock();
143       this.interrupt();
144     } finally {
145       rollLock.unlock();
146     }
147   }
148 }