Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add diskUnderWarnThreshold check event to prevent gcThread suspended forever #4018

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ public void diskAlmostFull(File disk) {
}
}

@Override
public void diskUnderWarnThreshold(File disk) {
if (gcThread.isForceGCAllowWhenNoSpace()) {
gcThread.disableForceGC();
} else {
gcThread.resumeMajorGC();
}
}

@Override
public void diskFull(File disk) {
if (gcThread.isForceGCAllowWhenNoSpace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public class LedgerDirsManager {
private static final Logger LOG = LoggerFactory.getLogger(LedgerDirsManager.class);

private volatile List<File> filledDirs;
private volatile List<File> warnDirs;
private final List<File> ledgerDirectories;
private volatile List<File> writableLedgerDirectories;
private final List<LedgerDirsListener> listeners;
Expand All @@ -71,6 +72,7 @@ public LedgerDirsManager(ServerConfiguration conf, File[] dirs, DiskChecker disk
}
this.writableLedgerDirectories = new ArrayList<File>(ledgerDirectories);
this.filledDirs = new ArrayList<File>();
this.warnDirs = new ArrayList<File>();
this.listeners = new ArrayList<LedgerDirsListener>();
this.entryLogSize = conf.getEntryLogSizeLimit();
this.minUsableSizeForIndexFileCreation = conf.getMinUsableSizeForIndexFileCreation();
Expand Down Expand Up @@ -233,6 +235,13 @@ public List<File> getFullFilledLedgerDirs() {
return filledDirs;
}

/**
* @return warn threshold ledger dirs.
*/
public List<File> getWarnLedgerDirs() {
gaozhangmin marked this conversation as resolved.
Show resolved Hide resolved
return warnDirs;
}

/**
* Get dirs, which are full more than threshold.
*/
Expand Down Expand Up @@ -290,6 +299,39 @@ public void addToWritableDirs(File dir, boolean underWarnThreshold) {
}
}

/**
* Add the dir to warn dirs list.
*/
@VisibleForTesting
public void addToWarnDirs(File dir) {
if (!warnDirs.contains(dir)) {
LOG.warn(dir + " usages is above warn threshold. Adding it to warn dirs list");
List<File> updatedFilledDirs = new ArrayList<File>(warnDirs);
gaozhangmin marked this conversation as resolved.
Show resolved Hide resolved
updatedFilledDirs.add(dir);
warnDirs = updatedFilledDirs;
for (LedgerDirsListener listener : listeners) {
listener.diskAlmostFull(dir);
}
}
}


/**
* Remove warn dirs list.
*/
@VisibleForTesting
public void removeFromWarnDirs(File dir) {
if (warnDirs.contains(dir)) {
LOG.warn(dir + " usages is under warn threshold. Remove from warn dirs list");
List<File> newDirs = new ArrayList<File>(warnDirs);
newDirs.remove(dir);
warnDirs = newDirs;
for (LedgerDirsListener listener : listeners) {
listener.diskUnderWarnThreshold(dir);
}
}
}

/**
* Returns one of the ledger dir from writable dirs list randomly.
*/
Expand Down Expand Up @@ -402,6 +444,12 @@ default void diskFailed(File disk) {}
*/
default void diskAlmostFull(File disk) {}

/**
* Notified when the disk usage is under warn threshold.
* @param disk
*/
default void diskUnderWarnThreshold(File disk) {}

/**
* This will be notified on disk detected as full.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@ private void check(final LedgerDirsManager ldm) {
}
return e.getUsage();
});
for (LedgerDirsListener listener : ldm.getListeners()) {
listener.diskAlmostFull(dir);
}
ldm.addToWarnDirs(dir);
} catch (DiskOutOfSpaceException e) {
diskUsages.compute(dir, (d, prevUsage) -> {
if (null == prevUsage || e.getUsage() != prevUsage) {
Expand Down Expand Up @@ -124,6 +122,25 @@ private void check(final LedgerDirsManager ldm) {
}
}

// - Update warnThresholdDirs disk usage.
List<File> warnDirs = new ArrayList<File>(ldm.getWarnLedgerDirs());
for (File dir : warnDirs) {
try {
diskUsages.put(dir, diskChecker.checkDir(dir));
ldm.removeFromWarnDirs(dir);
} catch (DiskErrorException e) {
// Notify disk failure to all the listeners
for (LedgerDirsListener listener : ldm.getListeners()) {
listener.diskFailed(dir);
}
} catch (DiskWarnThresholdException e) {
diskUsages.put(dir, e.getUsage());
} catch (DiskOutOfSpaceException e) {
diskUsages.put(dir, e.getUsage());
ldm.addToFilledDirs(dir);
}
}

List<File> fullfilledDirs = new ArrayList<File>(ldm.getFullFilledLedgerDirs());
boolean makeWritable = ldm.hasWritableLedgerDirs();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,15 @@ public void diskAlmostFull(File disk) {
}
}

@Override
public void diskUnderWarnThreshold(File disk) {
if (gcThread.isForceGCAllowWhenNoSpace()) {
gcThread.disableForceGC();
} else {
gcThread.resumeMajorGC();
}
}

@Override
public void diskFull(File disk) {
if (gcThread.isForceGCAllowWhenNoSpace()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.bookkeeper.bookie.LedgerDirsManager.LedgerDirsListener;
Expand Down Expand Up @@ -280,6 +281,22 @@ public void testAnyLedgerFullTransitToReadOnly(boolean isReadOnlyModeOnAnyDiskFu
dirsManager.addLedgerDirsListener(mockLedgerDirsListener);
ledgerMonitor.start();

final CountDownLatch diskAlmostFull = new CountDownLatch(1);
final CountDownLatch diskUnderWarnThreshold = new CountDownLatch(1);
dirsManager.addLedgerDirsListener(new LedgerDirsListener() {

@Override
public void diskAlmostFull(File disk) {
diskAlmostFull.countDown();
}

@Override
public void diskUnderWarnThreshold(File disk) {
diskUnderWarnThreshold.countDown();
}

});

Thread.sleep((diskCheckInterval * 2) + 100);
assertFalse(mockLedgerDirsListener.readOnly);

Expand All @@ -294,6 +311,14 @@ public void testAnyLedgerFullTransitToReadOnly(boolean isReadOnlyModeOnAnyDiskFu
mockLedgerDirsListener, true);
setUsageAndThenVerify(curDir1, nospace - 0.20f, curDir2, nospace - 0.20f, mockDiskChecker,
mockLedgerDirsListener, false);
assertTrue("Disk Almost Full should have been triggered", diskAlmostFull.getCount() == 0);
// curDirs1's usage was above warn threshold 0.5 before, now it is below warn threshold 0.5.
setUsageAndThenVerify(curDir1, nospace - 0.50f, curDir2,
nospace - 0.20f, mockDiskChecker, mockLedgerDirsListener, false);
assertTrue("Disk diskUnderWarnThreshold event should have been triggered",
diskUnderWarnThreshold.getCount() == 0);
assertFalse(dirsManager.getWarnLedgerDirs().contains(curDir1));
assertTrue(dirsManager.getWarnLedgerDirs().contains(curDir2));
} else {
setUsageAndThenVerify(curDir1, 0.1f, curDir2, 0.1f, mockDiskChecker,
mockLedgerDirsListener, false);
Expand Down