use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.
the class TieredBlockStore method moveBlockInternal.
/**
* Moves a block to new location only if allocator finds available space in newLocation. This
* method will not trigger any eviction. Returns {@link MoveBlockResult}.
*
* @param sessionId session Id
* @param blockId block Id
* @param oldLocation the source location of the block
* @param newLocation new location to move this block
* @return the resulting information about the move operation
* @throws BlockDoesNotExistException if block is not found
* @throws BlockAlreadyExistsException if a block with same Id already exists in new location
* @throws InvalidWorkerStateException if the block to move is a temp block
* @throws IOException if I/O errors occur when moving block file
*/
private MoveBlockResult moveBlockInternal(long sessionId, long blockId, BlockStoreLocation oldLocation, BlockStoreLocation newLocation) throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException, IOException {
long lockId = mLockManager.lockBlock(sessionId, blockId, BlockLockType.WRITE);
try {
long blockSize;
String srcFilePath;
String dstFilePath;
BlockMeta srcBlockMeta;
BlockStoreLocation srcLocation;
BlockStoreLocation dstLocation;
try (LockResource r = new LockResource(mMetadataReadLock)) {
if (mMetaManager.hasTempBlockMeta(blockId)) {
throw new InvalidWorkerStateException(ExceptionMessage.MOVE_UNCOMMITTED_BLOCK, blockId);
}
srcBlockMeta = mMetaManager.getBlockMeta(blockId);
srcLocation = srcBlockMeta.getBlockLocation();
srcFilePath = srcBlockMeta.getPath();
blockSize = srcBlockMeta.getBlockSize();
}
if (!srcLocation.belongsTo(oldLocation)) {
throw new BlockDoesNotExistException(ExceptionMessage.BLOCK_NOT_FOUND_AT_LOCATION, blockId, oldLocation);
}
TempBlockMeta dstTempBlock = createBlockMetaInternal(sessionId, blockId, newLocation, blockSize, false);
if (dstTempBlock == null) {
return new MoveBlockResult(false, blockSize, null, null);
}
// When `newLocation` is some specific location, the `newLocation` and the `dstLocation` are
// just the same; while for `newLocation` with a wildcard significance, the `dstLocation`
// is a specific one with specific tier and dir which belongs to newLocation.
dstLocation = dstTempBlock.getBlockLocation();
// internally from the newLocation and return success with specific block location.
if (dstLocation.belongsTo(srcLocation)) {
mMetaManager.abortTempBlockMeta(dstTempBlock);
return new MoveBlockResult(true, blockSize, srcLocation, dstLocation);
}
dstFilePath = dstTempBlock.getCommitPath();
// Heavy IO is guarded by block lock but not metadata lock. This may throw IOException.
FileUtils.move(srcFilePath, dstFilePath);
try (LockResource r = new LockResource(mMetadataWriteLock)) {
// If this metadata update fails, we panic for now.
// TODO(bin): Implement rollback scheme to recover from IO failures.
mMetaManager.moveBlockMeta(srcBlockMeta, dstTempBlock);
} catch (BlockAlreadyExistsException | BlockDoesNotExistException | WorkerOutOfSpaceException e) {
// we shall never reach here
throw Throwables.propagate(e);
}
return new MoveBlockResult(true, blockSize, srcLocation, dstLocation);
} finally {
mLockManager.unlockBlock(lockId);
}
}
use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.
the class BlockWorkerTest method commitBlockOnRetry.
/**
* Tests that commitBlock doesn't throw an exception when {@link BlockAlreadyExistsException} gets
* thrown by the block store.
*/
@Test
public void commitBlockOnRetry() throws Exception {
long blockId = mRandom.nextLong();
long length = mRandom.nextLong();
long lockId = mRandom.nextLong();
long sessionId = mRandom.nextLong();
long usedBytes = mRandom.nextLong();
String tierAlias = "MEM";
HashMap<String, Long> usedBytesOnTiers = new HashMap<>();
usedBytesOnTiers.put(tierAlias, usedBytes);
BlockMeta blockMeta = PowerMockito.mock(BlockMeta.class);
BlockStoreLocation blockStoreLocation = PowerMockito.mock(BlockStoreLocation.class);
BlockStoreMeta blockStoreMeta = PowerMockito.mock(BlockStoreMeta.class);
when(mBlockStore.lockBlock(sessionId, blockId)).thenReturn(lockId);
when(mBlockStore.getBlockMeta(sessionId, blockId, lockId)).thenReturn(blockMeta);
when(mBlockStore.getBlockStoreMeta()).thenReturn(blockStoreMeta);
when(blockMeta.getBlockLocation()).thenReturn(blockStoreLocation);
when(blockStoreLocation.tierAlias()).thenReturn(tierAlias);
when(blockMeta.getBlockSize()).thenReturn(length);
when(blockStoreMeta.getUsedBytesOnTiers()).thenReturn(usedBytesOnTiers);
doThrow(new BlockAlreadyExistsException("")).when(mBlockStore).commitBlock(sessionId, blockId);
mBlockWorker.commitBlock(sessionId, blockId);
}
use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.
the class BlockWorkerDataWriter method create.
/**
* Creates an instance of {@link BlockWorkerDataWriter}.
*
* @param context the file system context
* @param blockId the block ID
* @param blockSize the block size in bytes
* @param options the output stream options
* @return the {@link BlockWorkerDataWriter} created
*/
public static BlockWorkerDataWriter create(final FileSystemContext context, long blockId, long blockSize, OutStreamOptions options) throws IOException {
AlluxioConfiguration conf = context.getClusterConf();
int chunkSize = (int) conf.getBytes(PropertyKey.USER_LOCAL_WRITER_CHUNK_SIZE_BYTES);
long reservedBytes = Math.min(blockSize, conf.getBytes(PropertyKey.USER_FILE_RESERVED_BYTES));
BlockWorker blockWorker = context.getProcessLocalWorker();
Preconditions.checkNotNull(blockWorker, "blockWorker");
long sessionId = SessionIdUtils.createSessionId();
try {
blockWorker.createBlock(sessionId, blockId, options.getWriteTier(), options.getMediumType(), reservedBytes);
BlockWriter blockWriter = blockWorker.createBlockWriter(sessionId, blockId);
return new BlockWorkerDataWriter(sessionId, blockId, options, blockWriter, blockWorker, chunkSize, reservedBytes, conf);
} catch (BlockAlreadyExistsException | WorkerOutOfSpaceException | BlockDoesNotExistException | InvalidWorkerStateException e) {
throw new IOException(e);
}
}
use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.
the class TieredBlockStore method createBlockMetaInternal.
/**
* Creates a temp block meta only if allocator finds available space. This method will not trigger
* any eviction.
*
* @param sessionId session id
* @param blockId block id
* @param newBlock true if this temp block is created for a new block
* @param options block allocation options
* @return a temp block created if successful, or null if allocation failed (instead of throwing
* {@link WorkerOutOfSpaceException} because allocation failure could be an expected case)
* @throws BlockAlreadyExistsException if there is already a block with the same block id
*/
private TempBlockMeta createBlockMetaInternal(long sessionId, long blockId, boolean newBlock, AllocateOptions options) throws BlockAlreadyExistsException, WorkerOutOfSpaceException, IOException {
try (LockResource r = new LockResource(mMetadataWriteLock)) {
// unnecessary to acquire block lock here since no sharing.
if (newBlock) {
checkTempBlockIdAvailable(blockId);
}
// Allocate space.
StorageDirView dirView = allocateSpace(sessionId, options);
// TODO(carson): Add tempBlock to corresponding storageDir and remove the use of
// StorageDirView.createTempBlockMeta.
TempBlockMeta tempBlock = dirView.createTempBlockMeta(sessionId, blockId, options.getSize());
try {
// Add allocated temp block to metadata manager. This should never fail if allocator
// correctly assigns a StorageDir.
mMetaManager.addTempBlockMeta(tempBlock);
} catch (WorkerOutOfSpaceException | BlockAlreadyExistsException e) {
// If we reach here, allocator is not working properly
LOG.error("Unexpected failure: {} bytes allocated at {} by allocator, " + "but addTempBlockMeta failed", options.getSize(), options.getLocation());
throw Throwables.propagate(e);
}
return tempBlock;
}
}
use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.
the class CacheRequestManager method cacheBlockFromRemoteWorker.
/**
* Caches the block at best effort from a remote worker (possibly from UFS indirectly).
*
* @param blockId block ID
* @param blockSize block size
* @param sourceAddress the source to read the block previously by client
* @param openUfsBlockOptions options to open the UFS file
* @return if the block is cached
*/
private boolean cacheBlockFromRemoteWorker(long blockId, long blockSize, InetSocketAddress sourceAddress, Protocol.OpenUfsBlockOptions openUfsBlockOptions) throws IOException, AlluxioException {
try {
mBlockWorker.createBlock(Sessions.CACHE_WORKER_SESSION_ID, blockId, 0, "", blockSize);
} catch (BlockAlreadyExistsException e) {
// It is already cached
LOG.debug("block already cached: {}", blockId);
return true;
}
try (BlockReader reader = getRemoteBlockReader(blockId, blockSize, sourceAddress, openUfsBlockOptions);
BlockWriter writer = mBlockWorker.createBlockWriter(Sessions.CACHE_WORKER_SESSION_ID, blockId)) {
BufferUtils.transfer(reader.getChannel(), writer.getChannel());
mBlockWorker.commitBlock(Sessions.CACHE_WORKER_SESSION_ID, blockId, false);
return true;
} catch (AlluxioException | IOException e) {
LOG.warn("Failed to async cache block {} from remote worker ({}) on copying the block: {}", blockId, sourceAddress, e.toString());
try {
mBlockWorker.abortBlock(Sessions.CACHE_WORKER_SESSION_ID, blockId);
} catch (AlluxioException | IOException ee) {
LOG.warn("Failed to abort block {}: {}", blockId, ee.toString());
}
throw e;
}
}
Aggregations