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.fs.Path;
25  import org.apache.hadoop.hbase.*;
26  import org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException;
27  import org.apache.hadoop.hbase.regionserver.wal.HLogKey;
28  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
29  import org.apache.hadoop.hbase.regionserver.wal.WALActionsListener;
30  import org.apache.hadoop.hbase.util.Bytes;
31  import org.apache.hadoop.hbase.util.HasThread;
32  
33  import java.io.IOException;
34  import java.util.concurrent.atomic.AtomicBoolean;
35  import java.util.concurrent.locks.ReentrantLock;
36  
37  /**
38   * Runs periodically to determine if the HLog should be rolled.
39   *
40   * NOTE: This class extends Thread rather than Chore because the sleep time
41   * can be interrupted when there is something to do, rather than the Chore
42   * sleep time which is invariant.
43   */
44  class LogRoller extends HasThread implements WALActionsListener {
45    static final Log LOG = LogFactory.getLog(LogRoller.class);
46    private final ReentrantLock rollLock = new ReentrantLock();
47    private final AtomicBoolean rollLog = new AtomicBoolean(false);
48    private final Server server;
49    private final RegionServerServices services;
50    private volatile long lastrolltime = System.currentTimeMillis();
51    // Period to roll log.
52    private final long rollperiod;
53    private final int threadWakeFrequency;
54  
55    /** @param server */
56    public LogRoller(final Server server, final RegionServerServices services) {
57      super();
58      this.server = server;
59      this.services = services;
60      this.rollperiod = this.server.getConfiguration().
61        getLong("hbase.regionserver.logroll.period", 3600000);
62      this.threadWakeFrequency = this.server.getConfiguration().
63        getInt(HConstants.THREAD_WAKE_FREQUENCY, 10 * 1000);
64    }
65  
66    @Override
67    public void run() {
68      while (!server.isStopped()) {
69        long now = System.currentTimeMillis();
70        boolean periodic = false;
71        if (!rollLog.get()) {
72          periodic = (now - this.lastrolltime) > this.rollperiod;
73          if (!periodic) {
74            synchronized (rollLog) {
75              try {
76                rollLog.wait(this.threadWakeFrequency);
77              } catch (InterruptedException e) {
78                // Fall through
79              }
80            }
81            continue;
82          }
83          // Time for periodic roll
84          if (LOG.isDebugEnabled()) {
85            LOG.debug("Hlog roll period " + this.rollperiod + "ms elapsed");
86          }
87        } else if (LOG.isDebugEnabled()) {
88          LOG.debug("HLog roll requested");
89        }
90        rollLock.lock(); // FindBugs UL_UNRELEASED_LOCK_EXCEPTION_PATH
91        try {
92          this.lastrolltime = now;
93          // This is array of actual region names.
94          byte [][] regionsToFlush = this.services.getWAL().rollWriter(rollLog.get());
95          if (regionsToFlush != null) {
96            for (byte [] r: regionsToFlush) scheduleFlush(r);
97          }
98        } catch (FailedLogCloseException e) {
99          server.abort("Failed log close in log roller", e);
100       } catch (java.net.ConnectException e) {
101         server.abort("Failed log close in log roller", e);
102       } catch (IOException ex) {
103         // Abort if we get here.  We probably won't recover an IOE. HBASE-1132
104         server.abort("IOE in log roller",
105           RemoteExceptionHandler.checkIOException(ex));
106       } catch (Exception ex) {
107         LOG.error("Log rolling failed", ex);
108         server.abort("Log rolling failed", ex);
109       } finally {
110         rollLog.set(false);
111         rollLock.unlock();
112       }
113     }
114     LOG.info("LogRoller exiting.");
115   }
116 
117   /**
118    * @param encodedRegionName Encoded name of region to flush.
119    */
120   private void scheduleFlush(final byte [] encodedRegionName) {
121     boolean scheduled = false;
122     HRegion r = this.services.getFromOnlineRegions(Bytes.toString(encodedRegionName));
123     FlushRequester requester = null;
124     if (r != null) {
125       requester = this.services.getFlushRequester();
126       if (requester != null) {
127         requester.requestFlush(r);
128         scheduled = true;
129       }
130     }
131     if (!scheduled) {
132       LOG.warn("Failed to schedule flush of " +
133         Bytes.toString(encodedRegionName) + ", region=" + r + ", requester=" +
134         requester);
135     }
136   }
137 
138   public void logRollRequested() {
139     synchronized (rollLog) {
140       rollLog.set(true);
141       rollLog.notifyAll();
142     }
143   }
144 
145   /**
146    * Called by region server to wake up this thread if it sleeping.
147    * It is sleeping if rollLock is not held.
148    */
149   public void interruptIfNecessary() {
150     try {
151       rollLock.lock();
152       this.interrupt();
153     } finally {
154       rollLock.unlock();
155     }
156   }
157 
158   @Override
159   public void preLogRoll(Path oldPath, Path newPath) throws IOException {
160     // Not interested
161   }
162 
163   @Override
164   public void postLogRoll(Path oldPath, Path newPath) throws IOException {
165     // Not interested
166   }
167 
168   @Override
169   public void preLogArchive(Path oldPath, Path newPath) throws IOException {
170     // Not interested
171   }
172 
173   @Override
174   public void postLogArchive(Path oldPath, Path newPath) throws IOException {
175     // Not interested
176   }
177 
178   @Override
179   public void visitLogEntryBeforeWrite(HRegionInfo info, HLogKey logKey,
180       WALEdit logEdit) {
181     // Not interested.
182   }
183 
184   @Override
185   public void visitLogEntryBeforeWrite(HTableDescriptor htd, HLogKey logKey,
186                                        WALEdit logEdit) {
187     //Not interested
188   }
189 
190   @Override
191   public void logCloseRequested() {
192     // not interested
193   }
194 }