/** * Aborts a temp block. * * @param sessionId the id of session * @param blockId the id of block * @throws BlockDoesNotExistException if block id can not be found in temporary blocks * @throws BlockAlreadyExistsException if block id already exists in committed blocks * @throws InvalidWorkerStateException if block id is not owned by session id * @throws IOException if I/O errors occur when deleting the block file */ private void abortBlockInternal(long sessionId, long blockId) throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException, IOException { long lockId = mLockManager.lockBlock(sessionId, blockId, BlockLockType.WRITE); try { String path; TempBlockMeta tempBlockMeta; mMetadataReadLock.lock(); try { checkTempBlockOwnedBySession(sessionId, blockId); tempBlockMeta = mMetaManager.getTempBlockMeta(blockId); path = tempBlockMeta.getPath(); } finally { mMetadataReadLock.unlock(); } // Heavy IO is guarded by block lock but not metadata lock. This may throw IOException. Files.delete(Paths.get(path)); mMetadataWriteLock.lock(); try { mMetaManager.abortTempBlockMeta(tempBlockMeta); } catch (BlockDoesNotExistException e) { throw Throwables.propagate(e); // We shall never reach here } finally { mMetadataWriteLock.unlock(); } } finally { mLockManager.unlockBlock(lockId); } }
@Override public BlockWriter getBlockWriter(long sessionId, long blockId) throws BlockDoesNotExistException, IOException { // NOTE: a temp block is supposed to only be visible by its own writer, unnecessary to acquire // block lock here since no sharing // TODO(bin): Handle the case where multiple writers compete for the same block. mMetadataReadLock.lock(); try { TempBlockMeta tempBlockMeta = mMetaManager.getTempBlockMeta(blockId); return new LocalFileBlockWriter(tempBlockMeta.getPath()); } finally { mMetadataReadLock.unlock(); } }
/** * Commits a temp block. * * @param sessionId the id of session * @param blockId the id of block * @return destination location to move the block * @throws BlockDoesNotExistException if block id can not be found in temporary blocks * @throws BlockAlreadyExistsException if block id already exists in committed blocks * @throws InvalidWorkerStateException if block id is not owned by session id * @throws IOException if I/O errors occur when deleting the block file */ private BlockStoreLocation commitBlockInternal(long sessionId, long blockId) throws BlockAlreadyExistsException, InvalidWorkerStateException, BlockDoesNotExistException, IOException { long lockId = mLockManager.lockBlock(sessionId, blockId, BlockLockType.WRITE); try { // When committing TempBlockMeta, the final BlockMeta calculates the block size according to // the actual file size of this TempBlockMeta. Therefore, commitTempBlockMeta must happen // after moving actual block file to its committed path. BlockStoreLocation loc; String srcPath; String dstPath; TempBlockMeta tempBlockMeta; mMetadataReadLock.lock(); try { checkTempBlockOwnedBySession(sessionId, blockId); tempBlockMeta = mMetaManager.getTempBlockMeta(blockId); srcPath = tempBlockMeta.getPath(); dstPath = tempBlockMeta.getCommitPath(); loc = tempBlockMeta.getBlockLocation(); } finally { mMetadataReadLock.unlock(); } // Heavy IO is guarded by block lock but not metadata lock. This may throw IOException. FileUtils.move(srcPath, dstPath); mMetadataWriteLock.lock(); try { mMetaManager.commitTempBlockMeta(tempBlockMeta); } catch (BlockAlreadyExistsException e) { throw Throwables.propagate(e); // we shall never reach here } catch (BlockDoesNotExistException e) { throw Throwables.propagate(e); // we shall never reach here } catch (WorkerOutOfSpaceException e) { throw Throwables.propagate(e); // we shall never reach here } finally { mMetadataWriteLock.unlock(); } return loc; } finally { mLockManager.unlockBlock(lockId); } }