Пример #1
0
  void readJournal() throws IOException, BookieException {
    long startTs = MathUtils.now();
    journal.replay(
        new JournalScanner() {
          @Override
          public void process(int journalVersion, long offset, ByteBuffer recBuff)
              throws IOException {
            long ledgerId = recBuff.getLong();
            long entryId = recBuff.getLong();
            try {
              LOG.debug("Replay journal - ledger id : {}, entry id : {}.", ledgerId, entryId);
              if (entryId == METAENTRY_ID_LEDGER_KEY) {
                if (journalVersion >= JournalChannel.V3) {
                  int masterKeyLen = recBuff.getInt();
                  byte[] masterKey = new byte[masterKeyLen];

                  recBuff.get(masterKey);
                  masterKeyCache.put(ledgerId, masterKey);
                } else {
                  throw new IOException(
                      "Invalid journal. Contains journalKey "
                          + " but layout version ("
                          + journalVersion
                          + ") is too old to hold this");
                }
              } else if (entryId == METAENTRY_ID_FENCE_KEY) {
                if (journalVersion >= JournalChannel.V4) {
                  byte[] key = masterKeyCache.get(ledgerId);
                  if (key == null) {
                    key = ledgerStorage.readMasterKey(ledgerId);
                  }
                  LedgerDescriptor handle = handles.getHandle(ledgerId, key);
                  handle.setFenced();
                } else {
                  throw new IOException(
                      "Invalid journal. Contains fenceKey "
                          + " but layout version ("
                          + journalVersion
                          + ") is too old to hold this");
                }
              } else {
                byte[] key = masterKeyCache.get(ledgerId);
                if (key == null) {
                  key = ledgerStorage.readMasterKey(ledgerId);
                }
                LedgerDescriptor handle = handles.getHandle(ledgerId, key);

                recBuff.rewind();
                handle.addEntry(recBuff);
              }
            } catch (NoLedgerException nsle) {
              LOG.debug("Skip replaying entries of ledger {} since it was deleted.", ledgerId);
            } catch (BookieException be) {
              throw new IOException(be);
            }
          }
        });
    long elapsedTs = MathUtils.now() - startTs;
    LOG.info("Finished replaying journal in {} ms.", elapsedTs);
  }
Пример #2
0
  /**
   * Fences a ledger. From this point on, clients will be unable to write to this ledger. Only
   * recoveryAddEntry will be able to add entries to the ledger. This method is idempotent. Once a
   * ledger is fenced, it can never be unfenced. Fencing a fenced ledger has no effect.
   */
  public SettableFuture<Boolean> fenceLedger(long ledgerId, byte[] masterKey)
      throws IOException, BookieException {
    LedgerDescriptor handle = handles.getHandle(ledgerId, masterKey);
    boolean success;
    synchronized (handle) {
      success = handle.setFenced();
    }
    if (success) {
      // fenced first time, we should add the key to journal ensure we can rebuild
      ByteBuffer bb = ByteBuffer.allocate(8 + 8);
      bb.putLong(ledgerId);
      bb.putLong(METAENTRY_ID_FENCE_KEY);
      bb.flip();

      FutureWriteCallback fwc = new FutureWriteCallback();
      LOG.debug("record fenced state for ledger {} in journal.", ledgerId);
      journal.logAddEntry(bb, fwc, null);
      return fwc.getResult();
    } else {
      // already fenced
      SettableFuture<Boolean> successFuture = SettableFuture.create();
      successFuture.set(true);
      return successFuture;
    }
  }
Пример #3
0
  /** Add an entry to a ledger as specified by handle. */
  private void addEntryInternal(
      LedgerDescriptor handle, ByteBuffer entry, WriteCallback cb, Object ctx)
      throws IOException, BookieException {
    long ledgerId = handle.getLedgerId();
    entry.rewind();
    long entryId = handle.addEntry(entry);

    entry.rewind();
    LOG.trace("Adding {}@{}", entryId, ledgerId);
    journal.logAddEntry(entry, cb, ctx);
  }
Пример #4
0
 @Override
 public void run() {
   // bookie thread wait for journal thread
   try {
     // start journal
     journal.start();
     // wait until journal quits
     journal.join();
     LOG.info("Journal thread quits.");
   } catch (InterruptedException ie) {
     LOG.warn("Interrupted on running journal thread : ", ie);
   }
   // if the journal thread quits due to shutting down, it is ok
   if (!shuttingdown) {
     // some error found in journal thread and it quits
     // following add operations to it would hang unit client timeout
     // so we should let bookie server exists
     LOG.error("Journal manager quits unexpectedly.");
     triggerBookieShutdown(ExitCode.BOOKIE_EXCEPTION);
   }
 }
Пример #5
0
  // internal shutdown method to let shutdown bookie gracefully
  // when encountering exception
  synchronized int shutdown(int exitCode) {
    try {
      if (running) { // avoid shutdown twice
        // the exitCode only set when first shutdown usually due to exception found
        this.exitCode = exitCode;
        // mark bookie as in shutting down progress
        shuttingdown = true;

        // Shutdown Sync thread
        syncThread.shutdown();

        // Shutdown disk checker
        ledgerDirsManager.shutdown();
        if (indexDirsManager != ledgerDirsManager) {
          indexDirsManager.shutdown();
        }

        // Shutdown journal
        journal.shutdown();
        this.join();

        // Shutdown the EntryLogger which has the GarbageCollector Thread running
        ledgerStorage.shutdown();

        // close Ledger Manager
        try {
          activeLedgerManager.close();
          activeLedgerManagerFactory.uninitialize();
        } catch (IOException ie) {
          LOG.error("Failed to close active ledger manager : ", ie);
        }

        // Shutdown the ZK client
        if (zk != null) zk.close();

        // Shutdown State Service
        stateService.shutdown();

        // setting running to false here, so watch thread in bookie server know it only after bookie
        // shut down
        running = false;
      }
    } catch (InterruptedException ie) {
      LOG.error("Interrupted during shutting down bookie : ", ie);
    }
    return this.exitCode;
  }
Пример #6
0
  /**
   * Retrieve the ledger descriptor for the ledger which entry should be added to. The
   * LedgerDescriptor returned from this method should be eventually freed with #putHandle().
   *
   * @throws BookieException if masterKey does not match the master key of the ledger
   */
  private LedgerDescriptor getLedgerForEntry(ByteBuffer entry, byte[] masterKey)
      throws IOException, BookieException {
    long ledgerId = entry.getLong();
    LedgerDescriptor l = handles.getHandle(ledgerId, masterKey);
    if (!masterKeyCache.containsKey(ledgerId)) {
      // new handle, we should add the key to journal ensure we can rebuild
      ByteBuffer bb = ByteBuffer.allocate(8 + 8 + 4 + masterKey.length);
      bb.putLong(ledgerId);
      bb.putLong(METAENTRY_ID_LEDGER_KEY);
      bb.putInt(masterKey.length);
      bb.put(masterKey);
      bb.flip();

      if (null == masterKeyCache.putIfAbsent(ledgerId, masterKey)) {
        journal.logAddEntry(bb, new NopWriteCallback(), null);
      }
    }
    return l;
  }