/*
   * (non-Javadoc)
   *
   * @see
   * org.apache.bookkeeper.mledger.impl.MetaStore.UpdateLedgersIdsCallback
   * #updateLedgersIdsComplete
   * (org.apache.bookkeeper.mledger.ManagedLedgerException.MetaStoreException)
   */
  public synchronized void updateLedgersIdsComplete(Version version) {
    state = State.LedgerOpened;
    ledgersVersion = version;

    // Process all the pending addEntry requests
    while (!pendingAddEntries.isEmpty()) {
      OpAddEntry op = pendingAddEntries.poll();

      op.setLedger(currentLedger);
      ++currentLedgerEntries;
      currentLedgerSize += op.data.length;

      if (currentLedgerIsFull()) {
        state = State.ClosingLedger;
        op.setCloseWhenDone(true);
        op.initiate();
        log.debug(
            "[{}] Stop writing into ledger {} queue={}",
            va(name, currentLedger.getId(), pendingAddEntries.size()));
        break;
      } else {
        op.initiate();
      }
    }
  }
  @Override
  public synchronized void asyncAddEntry(
      final byte[] data, final AddEntryCallback callback, final Object ctx) {
    checkArgument(state != State.None);
    log.debug("[{}] asyncAddEntry size={} state={}", va(name, data.length, state));
    if (state == State.Fenced) {
      callback.addComplete(new ManagedLedgerFencedException(), null, ctx);
      return;
    }

    OpAddEntry addOperation = new OpAddEntry(this, data, callback, ctx);

    if (state == State.ClosingLedger || state == State.CreatingLedger) {
      // We don't have a ready ledger to write into
      // We are waiting for a new ledger to be created
      log.debug("[{}] Queue addEntry request", name);
      pendingAddEntries.add(addOperation);
    } else if (state == State.ClosedLedger) {
      // No ledger and no pending operations. Create a new one
      pendingAddEntries.add(addOperation);
      log.debug("[{}] Creating a new ledger", name);
      state = State.CreatingLedger;
      bookKeeper.asyncCreateLedger(
          config.getEnsembleSize(),
          config.getQuorumSize(),
          config.getDigestType(),
          config.getPassword(),
          this,
          ctx);
    } else {
      checkArgument(state == State.LedgerOpened);
      checkArgument(!currentLedgerIsFull());

      // Write into lastLedger
      log.debug("[{}] Write into current ledger lh={}", name, currentLedger.getId());
      addOperation.setLedger(currentLedger);

      ++currentLedgerEntries;
      currentLedgerSize += data.length;
      if (currentLedgerIsFull()) {
        // This entry will be the last added to current ledger
        addOperation.setCloseWhenDone(true);
        state = State.ClosingLedger;
      }

      addOperation.initiate();
    }
  }