in bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/ScanAndCompareGarbageCollector.java [115:216]
public void gc(GarbageCleaner garbageCleaner) {
if (null == ledgerManager) {
// if ledger manager is null, the bookie is not started to connect to metadata store.
// so skip garbage collection
return;
}
try {
// Get a set of all ledgers on the bookie
NavigableSet<Long> bkActiveLedgers = Sets.newTreeSet(ledgerStorage.getActiveLedgersInRange(0,
Long.MAX_VALUE));
this.activeLedgerCounter = bkActiveLedgers.size();
long curTime = System.currentTimeMillis();
boolean checkOverreplicatedLedgers = (enableGcOverReplicatedLedger && curTime
- lastOverReplicatedLedgerGcTimeMillis > gcOverReplicatedLedgerIntervalMillis);
if (checkOverreplicatedLedgers) {
LOG.info("Start removing over-replicated ledgers. activeLedgerCounter={}", activeLedgerCounter);
// remove all the overreplicated ledgers from the local bookie
Set<Long> overReplicatedLedgers = removeOverReplicatedledgers(bkActiveLedgers, garbageCleaner);
if (overReplicatedLedgers.isEmpty()) {
LOG.info("No over-replicated ledgers found.");
} else {
LOG.info("Removed over-replicated ledgers: {}", overReplicatedLedgers);
}
lastOverReplicatedLedgerGcTimeMillis = System.currentTimeMillis();
}
// Iterate over all the ledger on the metadata store
long zkOpTimeoutMs = this.conf.getZkTimeout() * 2;
LedgerRangeIterator ledgerRangeIterator = ledgerManager
.getLedgerRanges(zkOpTimeoutMs);
Set<Long> ledgersInMetadata = null;
long start;
long end = -1;
boolean done = false;
AtomicBoolean isBookieInEnsembles = new AtomicBoolean(false);
Versioned<LedgerMetadata> metadata = null;
while (!done) {
start = end + 1;
if (ledgerRangeIterator.hasNext()) {
LedgerRange lRange = ledgerRangeIterator.next();
ledgersInMetadata = lRange.getLedgers();
end = lRange.end();
} else {
ledgersInMetadata = new TreeSet<>();
end = Long.MAX_VALUE;
done = true;
}
Iterable<Long> subBkActiveLedgers = bkActiveLedgers.subSet(start, true, end, true);
if (LOG.isDebugEnabled()) {
LOG.debug("Active in metadata {}, Active in bookie {}", ledgersInMetadata, subBkActiveLedgers);
}
for (Long bkLid : subBkActiveLedgers) {
if (!ledgersInMetadata.contains(bkLid)) {
if (verifyMetadataOnGc) {
isBookieInEnsembles.set(false);
metadata = null;
int rc = BKException.Code.OK;
try {
metadata = result(ledgerManager.readLedgerMetadata(bkLid), zkOpTimeoutMs,
TimeUnit.MILLISECONDS);
} catch (BKException | TimeoutException e) {
if (e instanceof BKException) {
rc = ((BKException) e).getCode();
} else {
LOG.warn("Time-out while fetching metadata for Ledger {} : {}.", bkLid,
e.getMessage());
continue;
}
}
// check bookie should be part of ensembles in one
// of the segment else ledger should be deleted from
// local storage
if (metadata != null && metadata.getValue() != null) {
metadata.getValue().getAllEnsembles().forEach((entryId, ensembles) -> {
if (ensembles != null && ensembles.contains(selfBookieAddress)) {
isBookieInEnsembles.set(true);
}
});
if (isBookieInEnsembles.get()) {
continue;
}
} else if (rc != BKException.Code.NoSuchLedgerExistsOnMetadataServerException) {
LOG.warn("Ledger {} Missing in metadata list, but ledgerManager returned rc: {}.",
bkLid, rc);
continue;
}
}
garbageCleaner.clean(bkLid);
}
}
}
} catch (Throwable t) {
// ignore exception, collecting garbage next time
LOG.warn("Exception when iterating over the metadata", t);
}
}