View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.regionserver;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  import org.apache.hadoop.classification.InterfaceAudience;
24  import org.apache.hadoop.fs.Path;
25  import org.apache.hadoop.hbase.*;
26  import org.apache.hadoop.hbase.exceptions.FailedLogCloseException;
27  import org.apache.hadoop.hbase.regionserver.wal.HLog;
28  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
29  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
30  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
31  import org.apache.hadoop.hbase.util.Bytes;
32  import org.apache.hadoop.hbase.util.HasThread;
33  
34  import java.io.IOException;
35  import java.util.concurrent.atomic.AtomicBoolean;
36  import java.util.concurrent.locks.ReentrantLock;
37  
38  /**
39   * Runs periodically to determine if the HLog should be rolled.
40   *
41   * NOTE: This class extends Thread rather than Chore because the sleep time
42   * can be interrupted when there is something to do, rather than the Chore
43   * sleep time which is invariant.
44   */
45  @InterfaceAudience.Private
46  class LogRoller extends HasThread implements WALActionsListener {
47    static final Log LOG = LogFactory.getLog(LogRoller.class);
48    private final ReentrantLock rollLock = new ReentrantLock();
49    private final AtomicBoolean rollLog = new AtomicBoolean(false);
50    private final Server server;
51    protected final RegionServerServices services;
52    private volatile long lastrolltime = System.currentTimeMillis();
53    // Period to roll log.
54    private final long rollperiod;
55    private final int threadWakeFrequency;
56  
57    /** @param server */
58    public LogRoller(final Server server, final RegionServerServices services) {
59      super();
60      this.server = server;
61      this.services = services;
62      this.rollperiod = this.server.getConfiguration().
63        getLong("hbase.regionserver.logroll.period", 3600000);
64      this.threadWakeFrequency = this.server.getConfiguration().
65        getInt(HConstants.THREAD_WAKE_FREQUENCY, 10 * 1000);
66    }
67  
68    @Override
69    public void run() {
70      while (!server.isStopped()) {
71        long now = System.currentTimeMillis();
72        boolean periodic = false;
73        if (!rollLog.get()) {
74          periodic = (now - this.lastrolltime) > this.rollperiod;
75          if (!periodic) {
76            synchronized (rollLog) {
77              try {
78                rollLog.wait(this.threadWakeFrequency);
79              } catch (InterruptedException e) {
80                // Fall through
81              }
82            }
83            continue;
84          }
85          // Time for periodic roll
86          if (LOG.isDebugEnabled()) {
87            LOG.debug("Hlog roll period " + this.rollperiod + "ms elapsed");
88          }
89        } else if (LOG.isDebugEnabled()) {
90          LOG.debug("HLog roll requested");
91        }
92        rollLock.lock(); // FindBugs UL_UNRELEASED_LOCK_EXCEPTION_PATH
93        try {
94          this.lastrolltime = now;
95          // This is array of actual region names.
96          byte [][] regionsToFlush = getWAL().rollWriter(rollLog.get());
97          if (regionsToFlush != null) {
98            for (byte [] r: regionsToFlush) scheduleFlush(r);
99          }
100       } catch (FailedLogCloseException e) {
101         server.abort("Failed log close in log roller", e);
102       } catch (java.net.ConnectException e) {
103         server.abort("Failed log close in log roller", e);
104       } catch (IOException ex) {
105         // Abort if we get here.  We probably won't recover an IOE. HBASE-1132
106         server.abort("IOE in log roller",
107           RemoteExceptionHandler.checkIOException(ex));
108       } catch (Exception ex) {
109         LOG.error("Log rolling failed", ex);
110         server.abort("Log rolling failed", ex);
111       } finally {
112         try {
113           rollLog.set(false);
114         } finally {
115           rollLock.unlock();
116         }
117       }
118     }
119     LOG.info("LogRoller exiting.");
120   }
121 
122   /**
123    * @param encodedRegionName Encoded name of region to flush.
124    */
125   private void scheduleFlush(final byte [] encodedRegionName) {
126     boolean scheduled = false;
127     HRegion r = this.services.getFromOnlineRegions(Bytes.toString(encodedRegionName));
128     FlushRequester requester = null;
129     if (r != null) {
130       requester = this.services.getFlushRequester();
131       if (requester != null) {
132         requester.requestFlush(r);
133         scheduled = true;
134       }
135     }
136     if (!scheduled) {
137       LOG.warn("Failed to schedule flush of " +
138         Bytes.toString(encodedRegionName) + ", region=" + r + ", requester=" +
139         requester);
140     }
141   }
142 
143   public void logRollRequested() {
144     synchronized (rollLog) {
145       rollLog.set(true);
146       rollLog.notifyAll();
147     }
148   }
149 
150   /**
151    * Called by region server to wake up this thread if it sleeping.
152    * It is sleeping if rollLock is not held.
153    */
154   public void interruptIfNecessary() {
155     try {
156       rollLock.lock();
157       this.interrupt();
158     } finally {
159       rollLock.unlock();
160     }
161   }
162 
163   protected HLog getWAL() throws IOException {
164     return this.services.getWAL(null);
165   }
166 
167   @Override
168   public void preLogRoll(Path oldPath, Path newPath) throws IOException {
169     // Not interested
170   }
171 
172   @Override
173   public void postLogRoll(Path oldPath, Path newPath) throws IOException {
174     // Not interested
175   }
176 
177   @Override
178   public void preLogArchive(Path oldPath, Path newPath) throws IOException {
179     // Not interested
180   }
181 
182   @Override
183   public void postLogArchive(Path oldPath, Path newPath) throws IOException {
184     // Not interested
185   }
186 
187   @Override
188   public void visitLogEntryBeforeWrite(HRegionInfo info, HLogKey logKey,
189       WALEdit logEdit) {
190     // Not interested.
191   }
192 
193   @Override
194   public void visitLogEntryBeforeWrite(HTableDescriptor htd, HLogKey logKey,
195                                        WALEdit logEdit) {
196     //Not interested
197   }
198 
199   @Override
200   public void logCloseRequested() {
201     // not interested
202   }
203 }