Example #1
0
 /** @return a new block container id */
 @Override
 public long getNewContainerId() {
   synchronized (mBlockContainerIdGenerator) {
     long containerId = mBlockContainerIdGenerator.getNewContainerId();
     writeJournalEntry(mBlockContainerIdGenerator.toJournalEntry());
     flushJournal();
     return containerId;
   }
 }
Example #2
0
  /** @return a new block container id */
  @Override
  public long getNewContainerId() {
    synchronized (mBlockContainerIdGenerator) {
      long containerId = mBlockContainerIdGenerator.getNewContainerId();
      if (containerId < mJournaledNextContainerId) {
        // This container id is within the reserved container ids, so it is safe to return the id
        // without having to write anything to the journal.
        return containerId;
      }
      // This container id is not safe with respect to the last journaled container id.
      // Therefore, journal the new state of the container id. This implies that when a master
      // crashes, the container ids within the reservation which have not been used yet will
      // never be used. This is a tradeoff between fully utilizing the container id space, vs.
      // improving master scalability.
      // TODO(gpang): investigate if dynamic reservation sizes could be effective

      // Set the next id to journal with a reservation of container ids, to avoid having to write
      // to the journal for ids within the reservation.
      mJournaledNextContainerId = containerId + CONTAINER_ID_RESERVATION_SIZE;
      long counter = appendJournalEntry(getContainerIdJournalEntry());
      // This must be flushed while holding the lock on mBlockContainerIdGenerator, in order to
      // prevent subsequent calls to return container ids that have not been journaled and flushed.
      waitForJournalFlush(counter);
      return containerId;
    }
  }
Example #3
0
 @Override
 public void streamToJournalCheckpoint(JournalOutputStream outputStream) throws IOException {
   outputStream.writeEntry(mBlockContainerIdGenerator.toJournalEntry());
   for (MasterBlockInfo blockInfo : mBlocks.values()) {
     BlockInfoEntry blockInfoEntry =
         BlockInfoEntry.newBuilder()
             .setBlockId(blockInfo.getBlockId())
             .setLength(blockInfo.getLength())
             .build();
     outputStream.writeEntry(JournalEntry.newBuilder().setBlockInfo(blockInfoEntry).build());
   }
 }
Example #4
0
 @Override
 public void processJournalEntry(JournalEntry entry) throws IOException {
   Message innerEntry = JournalProtoUtils.unwrap(entry);
   // TODO(gene): A better way to process entries besides a huge switch?
   if (innerEntry instanceof BlockContainerIdGeneratorEntry) {
     mBlockContainerIdGenerator.setNextContainerId(
         ((BlockContainerIdGeneratorEntry) innerEntry).getNextContainerId());
   } else if (innerEntry instanceof BlockInfoEntry) {
     BlockInfoEntry blockInfoEntry = (BlockInfoEntry) innerEntry;
     mBlocks.put(
         blockInfoEntry.getBlockId(),
         new MasterBlockInfo(blockInfoEntry.getBlockId(), blockInfoEntry.getLength()));
   } else {
     throw new IOException(ExceptionMessage.UNEXPECTED_JOURNAL_ENTRY.getMessage(entry));
   }
 }