private void openWithMetadata()

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);

        }
    }