/** @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; } }
/** @return a new block container id */ @Override public long getNewContainerId() { synchronized (mBlockContainerIdGenerator) { long containerId = mBlockContainerIdGenerator.getNewContainerId(); writeJournalEntry(mBlockContainerIdGenerator.toJournalEntry()); flushJournal(); return containerId; } }