You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by st...@apache.org on 2008/12/07 08:23:25 UTC
svn commit: r724098 - in /hadoop/hbase/trunk: CHANGES.txt
src/java/org/apache/hadoop/hbase/regionserver/HLog.java
src/java/org/apache/hadoop/hbase/regionserver/LogFlusher.java
src/java/org/apache/hadoop/hbase/regionserver/LogRoller.java
Author: stack
Date: Sat Dec 6 23:23:25 2008
New Revision: 724098
URL: http://svn.apache.org/viewvc?rev=724098&view=rev
Log:
HBASE-1048 HLog: Found 0 logs to remove out of total 1450; oldest outstanding seqnum is 162297053 fr om region -ROOT-,,0
Modified:
hadoop/hbase/trunk/CHANGES.txt
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HLog.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogFlusher.java
hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogRoller.java
Modified: hadoop/hbase/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/CHANGES.txt?rev=724098&r1=724097&r2=724098&view=diff
==============================================================================
--- hadoop/hbase/trunk/CHANGES.txt (original)
+++ hadoop/hbase/trunk/CHANGES.txt Sat Dec 6 23:23:25 2008
@@ -164,6 +164,8 @@
HBASE-1030 Bit of polish on HBASE-1018
HBASE-847 new API: HTable.getRow with numVersion specified
(DoÄacan Güney via Stack)
+ HBASE-1048 HLog: Found 0 logs to remove out of total 1450; oldest
+ outstanding seqnum is 162297053 fr om region -ROOT-,,0
NEW FEATURES
HBASE-875 Use MurmurHash instead of JenkinsHash [in bloomfilters]
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HLog.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HLog.java?rev=724098&r1=724097&r2=724098&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HLog.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/HLog.java Sat Dec 6 23:23:25 2008
@@ -137,6 +137,13 @@
// We synchronize on updateLock to prevent updates and to prevent a log roll
// during an update
private final Integer updateLock = new Integer(0);
+
+ /*
+ * If more than this many logs, force flush of oldest region to oldest edit
+ * goes to disk. If too many and we crash, then will take forever replaying.
+ * Keep the number of logs tidy.
+ */
+ private final int maxLogs;
/**
* Create an edit log at the given <code>dir</code> location.
@@ -152,10 +159,9 @@
* @throws IOException
*/
public HLog(final FileSystem fs, final Path dir, final Configuration conf,
- final LogRollListener listener) throws IOException {
-
+ final LogRollListener listener)
+ throws IOException {
super();
-
this.fs = fs;
this.dir = dir;
this.conf = conf;
@@ -172,6 +178,7 @@
throw new IOException("Target HLog directory already exists: " + dir);
}
fs.mkdirs(dir);
+ this.maxLogs = conf.getInt("hbase.regionserver.maxlogs", 64);
rollWriter();
}
@@ -234,14 +241,17 @@
* cacheFlushLock and then completeCacheFlush could be called which would wait
* for the lock on this and consequently never release the cacheFlushLock
*
+ * @return If lots of logs, flush the returned region so next time through
+ * we can clean logs. Returns null if nothing to flush.
* @throws FailedLogCloseException
* @throws IOException
*/
- public void rollWriter() throws FailedLogCloseException, IOException {
+ public byte [] rollWriter() throws FailedLogCloseException, IOException {
+ byte [] regionToFlush = null;
this.cacheFlushLock.lock();
try {
if (closed) {
- return;
+ return regionToFlush;
}
synchronized (updateLock) {
// Clean up current writer.
@@ -268,7 +278,7 @@
}
this.outputfiles.clear();
} else {
- cleanOldLogs();
+ regionToFlush = cleanOldLogs();
}
}
this.numEntries = 0;
@@ -277,32 +287,28 @@
} finally {
this.cacheFlushLock.unlock();
}
+ return regionToFlush;
}
/*
* Clean up old commit logs.
+ * @return If lots of logs, flush the returned region so next time through
+ * we can clean logs. Returns null if nothing to flush.
* @throws IOException
*/
- private void cleanOldLogs() throws IOException {
- // Get oldest edit/sequence id. If logs are older than this id,
- // then safe to remove.
- Long oldestOutstandingSeqNum =
- Collections.min(this.lastSeqWritten.values());
+ private byte [] cleanOldLogs() throws IOException {
+ byte [] regionToFlush = null;
+ Long oldestOutstandingSeqNum = getOldestOutstandingSeqNum();
// Get the set of all log files whose final ID is older than or
// equal to the oldest pending region operation
TreeSet<Long> sequenceNumbers =
new TreeSet<Long>(this.outputfiles.headMap(
(Long.valueOf(oldestOutstandingSeqNum.longValue() + 1L))).keySet());
// Now remove old log files (if any)
+ byte [] oldestRegion = null;
if (LOG.isDebugEnabled()) {
// Find region associated with oldest key -- helps debugging.
- byte [] oldestRegion = null;
- for (Map.Entry<byte [], Long> e: this.lastSeqWritten.entrySet()) {
- if (e.getValue().longValue() == oldestOutstandingSeqNum.longValue()) {
- oldestRegion = e.getKey();
- break;
- }
- }
+ oldestRegion = getOldestRegion(oldestOutstandingSeqNum);
LOG.debug("Found " + sequenceNumbers.size() + " logs to remove " +
" out of total " + this.outputfiles.size() + "; " +
"oldest outstanding seqnum is " + oldestOutstandingSeqNum +
@@ -313,6 +319,33 @@
deleteLogFile(this.outputfiles.remove(seq), seq);
}
}
+ int countOfLogs = this.outputfiles.size() - sequenceNumbers.size();
+ if (countOfLogs > this.maxLogs) {
+ regionToFlush = oldestRegion != null?
+ oldestRegion: getOldestRegion(oldestOutstandingSeqNum);
+ LOG.info("Too many logs: logs=" + countOfLogs + ", maxlogs=" +
+ this.maxLogs + "; forcing flush of region with oldest edits: " +
+ Bytes.toString(regionToFlush));
+ }
+ return regionToFlush;
+ }
+
+ /*
+ * @return Logs older than this id are safe to remove.
+ */
+ private Long getOldestOutstandingSeqNum() {
+ return Collections.min(this.lastSeqWritten.values());
+ }
+
+ private byte [] getOldestRegion(final Long oldestOutstandingSeqNum) {
+ byte [] oldestRegion = null;
+ for (Map.Entry<byte [], Long> e: this.lastSeqWritten.entrySet()) {
+ if (e.getValue().longValue() == oldestOutstandingSeqNum.longValue()) {
+ oldestRegion = e.getKey();
+ break;
+ }
+ }
+ return oldestRegion;
}
/*
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogFlusher.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogFlusher.java?rev=724098&r1=724097&r2=724098&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogFlusher.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogFlusher.java Sat Dec 6 23:23:25 2008
@@ -48,7 +48,6 @@
}
}
- @Override
protected void chore() {
synchronized (log) {
HLog hlog = log.get();
@@ -57,4 +56,4 @@
}
}
}
-}
+}
\ No newline at end of file
Modified: hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogRoller.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogRoller.java?rev=724098&r1=724097&r2=724098&view=diff
==============================================================================
--- hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogRoller.java (original)
+++ hadoop/hbase/trunk/src/java/org/apache/hadoop/hbase/regionserver/LogRoller.java Sat Dec 6 23:23:25 2008
@@ -26,9 +26,10 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.RemoteExceptionHandler;
+import org.apache.hadoop.hbase.util.Bytes;
/**
- * Runs periodically to determine if the HLog should be rolled
+ * Runs periodically to determine if the HLog should be rolled.
*
* NOTE: This class extends Thread rather than Chore because the sleep time
* can be interrupted when there is something to do, rather than the Chore
@@ -61,7 +62,10 @@
}
rollLock.lock(); // Don't interrupt us. We're working
try {
- server.getLog().rollWriter();
+ byte [] regionToFlush = server.getLog().rollWriter();
+ if (regionToFlush != null) {
+ scheduleFlush(regionToFlush);
+ }
} catch (FailedLogCloseException e) {
LOG.fatal("Forcing server shutdown", e);
server.abort();
@@ -79,6 +83,23 @@
}
LOG.info("LogRoller exiting.");
}
+
+ private void scheduleFlush(final byte [] region) {
+ boolean scheduled = false;
+ HRegion r = this.server.getOnlineRegion(region);
+ FlushRequester requester = null;
+ if (r != null) {
+ requester = this.server.getFlushRequester();
+ if (requester != null) {
+ requester.request(r);
+ scheduled = true;
+ }
+ }
+ if (!scheduled) {
+ LOG.warn("Failed to schedule flush of " +
+ Bytes.toString(region) + "r=" + r + ", requester=" + requester);
+ }
+ }
public void logRollRequested() {
synchronized (rollLog) {