You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by si...@apache.org on 2017/01/30 22:25:06 UTC
bookkeeper git commit: BOOKKEEPER-949: Allow entryLog creation for
compaction
Repository: bookkeeper
Updated Branches:
refs/heads/master ca7e5fd80 -> ba5dadcb3
BOOKKEEPER-949: Allow entryLog creation for compaction
Allow entryLog creation even when bookie
is in RO mode for compaction
Signed-off-by: Venkateswararao Jujjuri (JV) <vjujjurisalesforce.com>
Reviewed-by: Andrey Yegorov <ayegorovsalesforce.com>
Reviewed-by: Charan Reddy Guttapalem <cguttapalemsalesforce.com>
Author: JV <vj...@salesforce.com>
Reviewers: Sijie Guo <si...@apache.org>
Closes #99 from reddycharan/entrylogcreationforcompaction
Project: http://git-wip-us.apache.org/repos/asf/bookkeeper/repo
Commit: http://git-wip-us.apache.org/repos/asf/bookkeeper/commit/ba5dadcb
Tree: http://git-wip-us.apache.org/repos/asf/bookkeeper/tree/ba5dadcb
Diff: http://git-wip-us.apache.org/repos/asf/bookkeeper/diff/ba5dadcb
Branch: refs/heads/master
Commit: ba5dadcb3e1fa942f2f1a17178fd368c4bd0f0c4
Parents: ca7e5fd
Author: JV <vj...@salesforce.com>
Authored: Mon Jan 30 14:25:01 2017 -0800
Committer: Sijie Guo <si...@apache.org>
Committed: Mon Jan 30 14:25:01 2017 -0800
----------------------------------------------------------------------
.../apache/bookkeeper/bookie/BookieShell.java | 8 +++-
.../apache/bookkeeper/bookie/EntryLogger.java | 2 +-
.../bookie/GarbageCollectorThread.java | 2 +-
.../bookkeeper/bookie/LedgerDirsManager.java | 44 ++++++++++++++++++++
.../bookkeeper/bookie/CreateNewLogTest.java | 32 +++++++++++++-
.../bookie/TestLedgerDirsManager.java | 30 +++++++++++++
6 files changed, 113 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/ba5dadcb/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
----------------------------------------------------------------------
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
index 1092001..b4030f1 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieShell.java
@@ -23,6 +23,7 @@ import static com.google.common.base.Charsets.UTF_8;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -1818,8 +1819,11 @@ public class BookieShell implements Tool {
Collections.sort(completeFilesList, new FilesTimeComparator());
return completeFilesList;
}
-
- private static class FilesTimeComparator implements Comparator<File> {
+
+ private static class FilesTimeComparator implements Comparator<File>, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
@Override
public int compare(File file1, File file2) {
Path file1Path = Paths.get(file1.getAbsolutePath());
http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/ba5dadcb/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
----------------------------------------------------------------------
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
index ecd0e0a..08ad1be 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
@@ -549,7 +549,7 @@ public class EntryLogger {
* Allocate a new log file.
*/
BufferedLogChannel allocateNewLog() throws IOException {
- List<File> list = ledgerDirsManager.getWritableLedgerDirs();
+ List<File> list = ledgerDirsManager.getWritableLedgerDirsForNewLog();
Collections.shuffle(list);
// It would better not to overwrite existing entry log files
File newLogFile = null;
http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/ba5dadcb/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
----------------------------------------------------------------------
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
index 36b7349..aa42475 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
@@ -504,7 +504,7 @@ public class GarbageCollectorThread extends BookieThread {
// closed and corrupted.
if (!compacting.compareAndSet(false, true)) {
// set compacting flag failed, means compacting is true now
- // indicates another thread wants to interrupt gc thread to exit
+ // indicates that compaction is in progress for this EntryLogId.
return;
}
http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/ba5dadcb/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerDirsManager.java
----------------------------------------------------------------------
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerDirsManager.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerDirsManager.java
index 7c95b85..52836f7 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerDirsManager.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LedgerDirsManager.java
@@ -60,6 +60,8 @@ public class LedgerDirsManager {
private final Random rand = new Random();
private final ConcurrentMap<File, Float> diskUsages =
new ConcurrentHashMap<File, Float>();
+ private final long entryLogSize;
+ private boolean forceGCAllowWhenNoSpace;
public LedgerDirsManager(ServerConfiguration conf, File[] dirs) {
this(conf, dirs, NullStatsLogger.INSTANCE);
@@ -78,6 +80,8 @@ public class LedgerDirsManager {
this.listeners = new ArrayList<LedgerDirsListener>();
this.diskChecker = diskChecker;
this.monitor = new LedgerDirsMonitor(conf.getDiskCheckInterval());
+ this.forceGCAllowWhenNoSpace = conf.getIsForceGCAllowWhenNoSpace();
+ this.entryLogSize = conf.getEntryLogSizeLimit();
for (File dir : dirs) {
diskUsages.put(dir, 0f);
String statName = "dir_" + dir.getPath().replace('/', '_') + "_usage";
@@ -129,6 +133,46 @@ public class LedgerDirsManager {
return writableLedgerDirectories;
}
+ public List<File> getWritableLedgerDirsForNewLog()
+ throws NoWritableLedgerDirException {
+
+ if (!writableLedgerDirectories.isEmpty()) {
+ return writableLedgerDirectories;
+ }
+
+ // If Force GC is not allowed under no space
+ if (!forceGCAllowWhenNoSpace) {
+ String errMsg = "All ledger directories are non writable and force GC is not enabled.";
+ NoWritableLedgerDirException e = new NoWritableLedgerDirException(errMsg);
+ LOG.error(errMsg, e);
+ throw e;
+ }
+
+ // We don't have writable Ledger Dirs.
+ // That means we must have turned readonly but the compaction
+ // must have started running and it needs to allocate
+ // a new log file to move forward with the compaction.
+ List<File> fullLedgerDirsToAccomodateNewEntryLog = new ArrayList<File>();
+ for (File dir: this.ledgerDirectories) {
+ // Pick dirs which can accommodate little more than an entry log.
+ if (dir.getUsableSpace() > (this.entryLogSize * 1.2) ) {
+ fullLedgerDirsToAccomodateNewEntryLog.add(dir);
+ }
+ }
+
+ if (!fullLedgerDirsToAccomodateNewEntryLog.isEmpty()) {
+ LOG.info("No writable ledger dirs. Trying to go beyond to accomodate compaction."
+ + "Dirs that can accomodate new entryLog are: {}", fullLedgerDirsToAccomodateNewEntryLog);
+ return fullLedgerDirsToAccomodateNewEntryLog;
+ }
+
+ // We will reach here when we have no option of creating a new log file for compaction
+ String errMsg = "All ledger directories are non writable and no reserved space left for creating entry log file.";
+ NoWritableLedgerDirException e = new NoWritableLedgerDirException(errMsg);
+ LOG.error(errMsg, e);
+ throw e;
+ }
+
/**
* @return full-filled ledger dirs.
*/
http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/ba5dadcb/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java
----------------------------------------------------------------------
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java
index e2d2e63..42167a3 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/CreateNewLogTest.java
@@ -19,9 +19,9 @@
package org.apache.bookkeeper.bookie;
import java.io.File;
+import java.util.List;
import org.junit.Assert;
-
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.bookkeeper.conf.TestBKConfiguration;
import org.junit.After;
@@ -99,4 +99,34 @@ public class CreateNewLogTest {
Assert.assertTrue("Wrong log id", el.getCurrentLogId() > 1);
}
+ @Test(timeout=60000)
+ public void testCreateNewLogWithNoWritableLedgerDirs() throws Exception {
+ ServerConfiguration conf = TestBKConfiguration.newServerConfiguration();
+
+ // Creating a new configuration with a number of ledger directories.
+ conf.setLedgerDirNames(ledgerDirs);
+ conf.setIsForceGCAllowWhenNoSpace(true);
+ LedgerDirsManager ledgerDirsManager = new LedgerDirsManager(conf, conf.getLedgerDirs());
+ EntryLogger el = new EntryLogger(conf, ledgerDirsManager);
+
+ // Extracted from createNewLog()
+ String logFileName = Long.toHexString(1) + ".log";
+ File dir = ledgerDirsManager.pickRandomWritableDir();
+ LOG.info("Picked this directory: " + dir);
+ File newLogFile = new File(dir, logFileName);
+ newLogFile.createNewFile();
+
+ // Now let us move all dirs to filled dirs
+ List<File> wDirs = ledgerDirsManager.getWritableLedgerDirs();
+ for (File tdir: wDirs) {
+ ledgerDirsManager.addToFilledDirs(tdir);
+ }
+
+ // Calls createNewLog, and with the number of directories we
+ // are using, if it picks one at random it will fail.
+ el.createNewLog();
+ LOG.info("This is the current log id: " + el.getCurrentLogId());
+ Assert.assertTrue("Wrong log id", el.getCurrentLogId() > 1);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/bookkeeper/blob/ba5dadcb/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/TestLedgerDirsManager.java
----------------------------------------------------------------------
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/TestLedgerDirsManager.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/TestLedgerDirsManager.java
index 4d8d547..b72cfc7 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/TestLedgerDirsManager.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/TestLedgerDirsManager.java
@@ -72,6 +72,7 @@ public class TestLedgerDirsManager {
ServerConfiguration conf = TestBKConfiguration.newServerConfiguration();
conf.setLedgerDirNames(new String[] { tmpDir.toString() });
conf.setDiskCheckInterval(diskCheckInterval);
+ conf.setIsForceGCAllowWhenNoSpace(true);
mockDiskChecker = new MockDiskChecker(threshold, warnThreshold);
dirsManager = new LedgerDirsManager(conf, conf.getLedgerDirs(), NullStatsLogger.INSTANCE, mockDiskChecker);
@@ -88,6 +89,16 @@ public class TestLedgerDirsManager {
}
@Test(timeout=60000)
+ public void testGetWritableDir() throws Exception {
+ try {
+ List<File> writeDirs = dirsManager.getWritableLedgerDirs();
+ assertTrue("Must have a writable ledgerDir", writeDirs.size() > 0);
+ } catch (NoWritableLedgerDirException nwlde) {
+ fail("We should have a writeble ledgerDir");
+ }
+ }
+
+ @Test(timeout=60000)
public void testPickWritableDirExclusive() throws Exception {
try {
dirsManager.pickRandomWritableDir(curDir);
@@ -112,6 +123,25 @@ public class TestLedgerDirsManager {
}
@Test(timeout=60000)
+ public void testGetWritableDirForLog() throws Exception {
+ List<File> writeDirs;
+ try {
+ dirsManager.addToFilledDirs(curDir);
+ writeDirs = dirsManager.getWritableLedgerDirs();
+ fail("Should not reach here due to there is no writable ledger dir.");
+ } catch (NoWritableLedgerDirException nwlde) {
+ // expected to fail with no writable ledger dir
+ // Now make sure we can get one for log
+ try {
+ writeDirs = dirsManager.getWritableLedgerDirsForNewLog();
+ assertTrue("Must have a writable ledgerDir", writeDirs.size() > 0);
+ } catch (NoWritableLedgerDirException e) {
+ fail("We should have a writeble ledgerDir");
+ }
+ }
+ }
+
+ @Test(timeout=60000)
public void testLedgerDirsMonitorDuringTransition() throws Exception {
MockLedgerDirsListener mockLedgerDirsListener = new MockLedgerDirsListener();