Index: src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogRolling.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogRolling.java (revision 1173921) +++ src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestLogRolling.java (working copy) @@ -416,13 +416,22 @@ server = TEST_UTIL.getRSForFirstRegionInTable(Bytes.toBytes(tableName)); this.log = server.getWAL(); final List paths = new ArrayList(); + final List preLogRolledCalled = new ArrayList(); paths.add(log.computeFilename()); log.registerWALActionsListener(new WALActionsListener() { @Override - public void logRolled(Path newFile) { + public void preLogRoll(Path oldFile, Path newFile) { + preLogRolledCalled.add(new Integer(1)); + } + @Override + public void postLogRoll(Path oldFile, Path newFile) { paths.add(newFile); } @Override + public void preLogArchive(Path oldFile, Path newFile) {} + @Override + public void postLogArchive(Path oldFile, Path newFile) {} + @Override public void logRollRequested() {} @Override public void logCloseRequested() {} @@ -478,6 +487,7 @@ // force a log roll to read back and verify previously written logs log.rollWriter(true); + assertTrue(preLogRolledCalled.size() == 1); // read back the data written Set loggedRows = new HashSet(); Index: src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java (revision 1173921) +++ src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestHLog.java (working copy) @@ -709,12 +709,26 @@ } @Override - public void logRolled(Path newFile) { + public void preLogRoll(Path oldFile, Path newFile) { // TODO Auto-generated method stub - } @Override + public void postLogRoll(Path oldFile, Path newFile) { + // TODO Auto-generated method stub + } + + @Override + public void preLogArchive(Path oldFile, Path newFile) { + // TODO Auto-generated method stub + } + + @Override + public void postLogArchive(Path oldFile, Path newFile) { + // TODO Auto-generated method stub + } + + @Override public void logRollRequested() { // TODO Auto-generated method stub Index: src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestWALActionsListener.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestWALActionsListener.java (revision 1173921) +++ src/test/java/org/apache/hadoop/hbase/regionserver/wal/TestWALActionsListener.java (working copy) @@ -108,8 +108,10 @@ hlog.close(); hlog.closeAndDelete(); - assertEquals(11, observer.logRollCounter); - assertEquals(5, laterobserver.logRollCounter); + assertEquals(11, observer.preLogRollCounter); + assertEquals(11, observer.postLogRollCounter); + assertEquals(5, laterobserver.preLogRollCounter); + assertEquals(5, laterobserver.postLogRollCounter); assertEquals(2, observer.closedCount); } @@ -118,15 +120,31 @@ * Just counts when methods are called */ static class DummyWALActionsListener implements WALActionsListener { - public int logRollCounter = 0; + public int preLogRollCounter = 0; + public int postLogRollCounter = 0; public int closedCount = 0; @Override - public void logRolled(Path newFile) { - logRollCounter++; + public void preLogRoll(Path oldFile, Path newFile) { + preLogRollCounter++; } @Override + public void postLogRoll(Path oldFile, Path newFile) { + postLogRollCounter++; + } + + @Override + public void preLogArchive(Path oldFile, Path newFile) { + // Not interested + } + + @Override + public void postLogArchive(Path oldFile, Path newFile) { + // Not interested + } + + @Override public void logRollRequested() { // Not interested } Index: src/main/java/org/apache/hadoop/hbase/regionserver/LogRoller.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/LogRoller.java (revision 1173921) +++ src/main/java/org/apache/hadoop/hbase/regionserver/LogRoller.java (working copy) @@ -154,11 +154,26 @@ } @Override - public void logRolled(Path newFile) { + public void preLogRoll(Path oldPath, Path newPath) throws IOException { // Not interested } @Override + public void postLogRoll(Path oldPath, Path newPath) throws IOException { + // Not interested + } + + @Override + public void preLogArchive(Path oldPath, Path newPath) throws IOException { + // Not interested + } + + @Override + public void postLogArchive(Path oldPath, Path newPath) throws IOException { + // Not interested + } + + @Override public void visitLogEntryBeforeWrite(HRegionInfo info, HLogKey logKey, WALEdit logEdit) { // Not interested. Index: src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java (revision 1173921) +++ src/main/java/org/apache/hadoop/hbase/regionserver/wal/HLog.java (working copy) @@ -548,11 +548,22 @@ // Do all the preparation outside of the updateLock to block // as less as possible the incoming writes long currentFilenum = this.filenum; + Path oldPath = null; + if (currentFilenum > 0) { + oldPath = computeFilename(currentFilenum); + } this.filenum = System.currentTimeMillis(); Path newPath = computeFilename(); if (LOG.isDebugEnabled()) { LOG.debug("Enabling new writer for "+FSUtils.getPath(newPath)); } + + // Tell our listeners that a new log is about to be created + if (!this.listeners.isEmpty()) { + for (WALActionsListener i : this.listeners) { + i.preLogRoll(oldPath, newPath); + } + } HLog.Writer nextWriter = this.createWriterInstance(fs, newPath, conf); // Can we get at the dfsclient outputstream? If an instance of // SFLW, it'll have done the necessary reflection to get at the @@ -564,7 +575,7 @@ // Tell our listeners that a new log was created if (!this.listeners.isEmpty()) { for (WALActionsListener i : this.listeners) { - i.logRolled(newPath); + i.postLogRoll(oldPath, newPath); } } @@ -814,9 +825,22 @@ LOG.info("moving old hlog file " + FSUtils.getPath(p) + " whose highest sequenceid is " + seqno + " to " + FSUtils.getPath(newPath)); + + // Tell our listeners that a log is going to be archived. + if (!this.listeners.isEmpty()) { + for (WALActionsListener i : this.listeners) { + i.preLogArchive(p, newPath); + } + } if (!this.fs.rename(p, newPath)) { throw new IOException("Unable to rename " + p + " to " + newPath); } + // Tell our listeners that a log has been archived. + if (!this.listeners.isEmpty()) { + for (WALActionsListener i : this.listeners) { + i.postLogArchive(p, newPath); + } + } } /** @@ -851,10 +875,24 @@ if (!fs.exists(this.dir)) return; FileStatus[] files = fs.listStatus(this.dir); for(FileStatus file : files) { + Path p = getHLogArchivePath(this.oldLogDir, file.getPath()); + // Tell our listeners that a log is going to be archived. + if (!this.listeners.isEmpty()) { + for (WALActionsListener i : this.listeners) { + i.preLogArchive(file.getPath(), p); + } + } + if (!fs.rename(file.getPath(),p)) { throw new IOException("Unable to rename " + file.getPath() + " to " + p); } + // Tell our listeners that a log was archived. + if (!this.listeners.isEmpty()) { + for (WALActionsListener i : this.listeners) { + i.postLogArchive(file.getPath(), p); + } + } } LOG.debug("Moved " + files.length + " log files to " + FSUtils.getPath(this.oldLogDir)); Index: src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALActionsListener.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALActionsListener.java (revision 1173921) +++ src/main/java/org/apache/hadoop/hbase/regionserver/wal/WALActionsListener.java (working copy) @@ -19,6 +19,7 @@ */ package org.apache.hadoop.hbase.regionserver.wal; +import java.io.IOException; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; @@ -28,13 +29,38 @@ * so make sure your implementation is fast else you'll slow hbase. */ public interface WALActionsListener { + /** - * The WAL was rolled. - * @param newFile the path to the new hlog + * The WAL is going to be rolled. The oldPath can be null if this is + * the first log file from the regionserver. + * @param oldPath the path to the old hlog + * @param newPath the path to the new hlog */ - public void logRolled(Path newFile); + public void preLogRoll(Path oldPath, Path newPath) throws IOException; /** + * The WAL has been rolled. The oldPath can be null if this is + * the first log file from the regionserver. + * @param oldPath the path to the old hlog + * @param newPath the path to the new hlog + */ + public void postLogRoll(Path oldPath, Path newPath) throws IOException; + + /** + * The WAL is going to be archived. + * @param oldPath the path to the old hlog + * @param newPath the path to the new hlog + */ + public void preLogArchive(Path oldPath, Path newPath) throws IOException; + + /** + * The WAL has been archived. + * @param oldPath the path to the old hlog + * @param newPath the path to the new hlog + */ + public void postLogArchive(Path oldPath, Path newPath) throws IOException; + + /** * A request was made that the WAL be rolled. */ public void logRollRequested(); Index: src/main/java/org/apache/hadoop/hbase/replication/regionserver/Replication.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/replication/regionserver/Replication.java (revision 1173921) +++ src/main/java/org/apache/hadoop/hbase/replication/regionserver/Replication.java (working copy) @@ -156,10 +156,25 @@ } @Override - public void logRolled(Path p) { - getReplicationManager().logRolled(p); + public void preLogRoll(Path oldPath, Path newPath) throws IOException { + // Not interested } + @Override + public void postLogRoll(Path oldPath, Path newPath) { + getReplicationManager().logRolled(newPath); + } + + @Override + public void preLogArchive(Path oldPath, Path newPath) throws IOException { + // Not interested + } + + @Override + public void postLogArchive(Path oldPath, Path newPath) throws IOException { + // Not interested + } + /** * This method modifies the master's configuration in order to inject * replication-related features