in bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerOpenOp.java [136:248]
private void openWithMetadata(Versioned<LedgerMetadata> versionedMetadata) {
LedgerMetadata metadata = versionedMetadata.getValue();
final byte[] passwd;
// we should use digest type from metadata *ONLY* when:
// 1) digest type is stored in metadata
// 2) `autodetection` is enabled
DigestType digestType;
if (enableDigestAutodetection && metadata.hasPassword()) {
digestType = fromApiDigestType(metadata.getDigestType());
} else {
digestType = suggestedDigestType;
}
/* For an administrative open, the default passwords
* are read from the configuration, but if the metadata
* already contains passwords, use these instead. */
if (administrativeOpen && metadata.hasPassword()) {
passwd = metadata.getPassword();
digestType = fromApiDigestType(metadata.getDigestType());
} else {
passwd = this.passwd;
if (metadata.hasPassword()) {
if (!Arrays.equals(passwd, metadata.getPassword())) {
LOG.error("Provided passwd does not match that in metadata");
openComplete(BKException.Code.UnauthorizedAccessException, null);
return;
}
// if `digest auto detection` is enabled, ignore the suggested digest type, this allows digest type
// changes. e.g. moving from `crc32` to `crc32c`.
if (suggestedDigestType != fromApiDigestType(metadata.getDigestType()) && !enableDigestAutodetection) {
LOG.error("Provided digest does not match that in metadata");
openComplete(BKException.Code.DigestMatchException, null);
return;
}
}
}
// get the ledger metadata back
try {
lh = new ReadOnlyLedgerHandle(bk.getClientCtx(), ledgerId, versionedMetadata, digestType,
passwd, !doRecovery);
} catch (GeneralSecurityException e) {
LOG.error("Security exception while opening ledger: " + ledgerId, e);
openComplete(BKException.Code.DigestNotInitializedException, null);
return;
} catch (NumberFormatException e) {
LOG.error("Incorrectly entered parameter throttle: " + bk.getConf().getThrottleValue(), e);
openComplete(BKException.Code.IncorrectParameterException, null);
return;
}
if (metadata.isClosed()) {
// Ledger was closed properly
openComplete(BKException.Code.OK, lh);
return;
}
if (doRecovery) {
lh.recover(new OrderedGenericCallback<Void>(bk.getMainWorkerPool(), ledgerId) {
@Override
public void safeOperationComplete(int rc, Void result) {
if (rc == BKException.Code.OK) {
openComplete(BKException.Code.OK, lh);
} else {
closeLedgerHandleAsync().whenComplete((ignore, ex) -> {
if (ex != null) {
LOG.error("Ledger {} close failed", ledgerId, ex);
}
if (rc == BKException.Code.UnauthorizedAccessException
|| rc == BKException.Code.TimeoutException) {
openComplete(bk.getReturnRc(rc), null);
} else {
openComplete(bk.getReturnRc(BKException.Code.LedgerRecoveryException), null);
}
});
}
}
@Override
public String toString() {
return String.format("Recover(%d)", ledgerId);
}
});
} else {
lh.asyncReadLastConfirmed(new ReadLastConfirmedCallback() {
@Override
public void readLastConfirmedComplete(int rc,
long lastConfirmed, Object ctx) {
if (rc == BKException.Code.TimeoutException) {
closeLedgerHandleAsync().whenComplete((r, ex) -> {
if (ex != null) {
LOG.error("Ledger {} close failed", ledgerId, ex);
}
openComplete(bk.getReturnRc(rc), null);
});
} else if (rc != BKException.Code.OK) {
closeLedgerHandleAsync().whenComplete((r, ex) -> {
if (ex != null) {
LOG.error("Ledger {} close failed", ledgerId, ex);
}
openComplete(bk.getReturnRc(BKException.Code.ReadException), null);
});
} else {
lh.lastAddConfirmed = lh.lastAddPushed = lastConfirmed;
openComplete(BKException.Code.OK, lh);
}
}
}, null);
}
}