public SortedMap<Long, LedgerMetadata> getLedgersContainBookies(Set<BookieSocketAddress> bookies)
     throws InterruptedException, BKException {
   final SyncObject sync = new SyncObject();
   final AtomicReference<SortedMap<Long, LedgerMetadata>> resultHolder =
       new AtomicReference<SortedMap<Long, LedgerMetadata>>(null);
   asyncGetLedgersContainBookies(
       bookies,
       new GenericCallback<SortedMap<Long, LedgerMetadata>>() {
         @Override
         public void operationComplete(int rc, SortedMap<Long, LedgerMetadata> result) {
           LOG.info("GetLedgersContainBookies completed with rc : {}", rc);
           synchronized (sync) {
             sync.rc = rc;
             sync.value = true;
             resultHolder.set(result);
             sync.notify();
           }
         }
       });
   synchronized (sync) {
     while (sync.value == false) {
       sync.wait();
     }
   }
   if (sync.rc != BKException.Code.OK) {
     throw BKException.create(sync.rc);
   }
   return resultHolder.get();
 }
  public void recoverBookieData(
      final Set<BookieSocketAddress> bookiesSrc, boolean dryrun, boolean skipOpenLedgers)
      throws InterruptedException, BKException {
    SyncObject sync = new SyncObject();
    // Call the async method to recover bookie data.
    asyncRecoverBookieData(
        bookiesSrc,
        dryrun,
        skipOpenLedgers,
        new RecoverCallback() {
          @Override
          public void recoverComplete(int rc, Object ctx) {
            LOG.info("Recover bookie operation completed with rc: " + rc);
            SyncObject syncObj = (SyncObject) ctx;
            synchronized (syncObj) {
              syncObj.rc = rc;
              syncObj.value = true;
              syncObj.notify();
            }
          }
        },
        sync);

    // Wait for the async method to complete.
    synchronized (sync) {
      while (sync.value == false) {
        sync.wait();
      }
    }
    if (sync.rc != BKException.Code.OK) {
      throw BKException.create(sync.rc);
    }
  }
  /**
   * Open a ledger as an administrator without recovering the ledger. This means that no digest
   * password checks are done. Otherwise, the call is identical to BookKeeper#openLedgerNoRecovery
   *
   * @param lId ledger identifier
   * @see BookKeeper#openLedgerNoRecovery
   */
  public LedgerHandle openLedgerNoRecovery(final long lId)
      throws InterruptedException, BKException {
    SyncCounter counter = new SyncCounter();
    counter.inc();
    new LedgerOpenOp(bkc, lId, new SyncOpenCallback(), counter).initiateWithoutRecovery();
    /*
     * Wait
     */
    counter.block(0);
    if (counter.getrc() != BKException.Code.OK) {
      throw BKException.create(counter.getrc());
    }

    return counter.getLh();
  }
 private void replicateLedgerFragment(
     LedgerHandle lh,
     final LedgerFragment ledgerFragment,
     final Map<Integer, BookieSocketAddress> targetBookieAddresses)
     throws InterruptedException, BKException {
   SyncCounter syncCounter = new SyncCounter();
   ResultCallBack resultCallBack = new ResultCallBack(syncCounter);
   SingleFragmentCallback cb =
       new SingleFragmentCallback(
           resultCallBack,
           lh,
           ledgerFragment.getFirstEntryId(),
           getReplacedBookiesMap(ledgerFragment, targetBookieAddresses));
   syncCounter.inc();
   Set<BookieSocketAddress> targetBookieSet = new HashSet<BookieSocketAddress>();
   targetBookieSet.addAll(targetBookieAddresses.values());
   asyncRecoverLedgerFragment(lh, ledgerFragment, cb, targetBookieSet);
   syncCounter.block(0);
   if (syncCounter.getrc() != BKException.Code.OK) {
     throw BKException.create(bkc.getReturnRc(syncCounter.getrc()));
   }
 }