use of alluxio.exception.WorkerOutOfSpaceException in project alluxio by Alluxio.
the class UnderFileSystemBlockReader method updateBlockWriter.
/**
* Updates the block writer given an offset to read. If the offset is beyond the current
* position of the block writer, the block writer will be aborted.
*
* @param offset the read offset
*/
private void updateBlockWriter(long offset) throws IOException {
try {
if (mBlockWriter != null && offset > mBlockWriter.getPosition()) {
mBlockWriter.close();
mBlockWriter = null;
mLocalBlockStore.abortBlock(mBlockMeta.getSessionId(), mBlockMeta.getBlockId());
}
} catch (BlockDoesNotExistException e) {
// This can only happen when the session is expired.
LOG.warn("Block {} does not exist when being aborted.", mBlockMeta.getBlockId());
} catch (BlockAlreadyExistsException | InvalidWorkerStateException | IOException e) {
// reader does not commit the block if it fails to abort the block.
throw CommonUtils.castToIOException(e);
}
try {
if (mBlockWriter == null && offset == 0 && !mNoCache) {
BlockStoreLocation loc = BlockStoreLocation.anyDirInTier(mStorageTierAssoc.getAlias(0));
String blockPath = mLocalBlockStore.createBlock(mBlockMeta.getSessionId(), mBlockMeta.getBlockId(), loc, mInitialBlockSize).getPath();
mBlockWriter = new LocalFileBlockWriter(blockPath);
}
} catch (IOException | BlockAlreadyExistsException | WorkerOutOfSpaceException e) {
// This can happen when there are concurrent UFS readers who are all trying to cache to block.
LOG.debug("Failed to update block writer for UFS block [blockId: {}, ufsPath: {}, offset: {}]", mBlockMeta.getBlockId(), mBlockMeta.getUnderFileSystemPath(), offset, e);
mBlockWriter = null;
}
}
use of alluxio.exception.WorkerOutOfSpaceException 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 location location to create the block
* @param initialBlockSize initial block size in bytes
* @param newBlock true if this temp block is created for a new block
* @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, BlockStoreLocation location, long initialBlockSize, boolean newBlock) throws BlockAlreadyExistsException {
// block lock here since no sharing
try (LockResource r = new LockResource(mMetadataWriteLock)) {
if (newBlock) {
checkTempBlockIdAvailable(blockId);
}
StorageDirView dirView = mAllocator.allocateBlockWithView(sessionId, initialBlockSize, location, getUpdatedView());
if (dirView == null) {
// Allocator fails to find a proper place for this new block.
return null;
}
// TODO(carson): Add tempBlock to corresponding storageDir and remove the use of
// StorageDirView.createTempBlockMeta.
TempBlockMeta tempBlock = dirView.createTempBlockMeta(sessionId, blockId, initialBlockSize);
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", initialBlockSize, location);
throw Throwables.propagate(e);
}
return tempBlock;
}
}
use of alluxio.exception.WorkerOutOfSpaceException in project alluxio by Alluxio.
the class TieredBlockStore method freeSpaceInternal.
/**
* Tries to get an eviction plan to free a certain amount of space in the given location, and
* carries out this plan with the best effort.
*
* @param sessionId the session Id
* @param availableBytes amount of space in bytes to free
* @param location location of space
* @throws WorkerOutOfSpaceException if it is impossible to achieve the free requirement
* @throws IOException if I/O errors occur when removing or moving block files
*/
private void freeSpaceInternal(long sessionId, long availableBytes, BlockStoreLocation location) throws WorkerOutOfSpaceException, IOException {
EvictionPlan plan;
try (LockResource r = new LockResource(mMetadataReadLock)) {
plan = mEvictor.freeSpaceWithView(availableBytes, location, getUpdatedView());
// Absent plan means failed to evict enough space.
if (plan == null) {
throw new WorkerOutOfSpaceException(ExceptionMessage.NO_EVICTION_PLAN_TO_FREE_SPACE);
}
}
// 1. remove blocks to make room.
for (Pair<Long, BlockStoreLocation> blockInfo : plan.toEvict()) {
try {
removeBlockInternal(sessionId, blockInfo.getFirst(), blockInfo.getSecond());
} catch (InvalidWorkerStateException e) {
// Evictor is not working properly
LOG.error("Failed to evict blockId {}, this is temp block", blockInfo.getFirst());
continue;
} catch (BlockDoesNotExistException e) {
LOG.info("Failed to evict blockId {}, it could be already deleted", blockInfo.getFirst());
continue;
}
synchronized (mBlockStoreEventListeners) {
for (BlockStoreEventListener listener : mBlockStoreEventListeners) {
listener.onRemoveBlockByWorker(sessionId, blockInfo.getFirst());
}
}
}
// 2. transfer blocks among tiers.
// 2.1. group blocks move plan by the destination tier.
Map<String, Set<BlockTransferInfo>> blocksGroupedByDestTier = new HashMap<>();
for (BlockTransferInfo entry : plan.toMove()) {
String alias = entry.getDstLocation().tierAlias();
if (!blocksGroupedByDestTier.containsKey(alias)) {
blocksGroupedByDestTier.put(alias, new HashSet<BlockTransferInfo>());
}
blocksGroupedByDestTier.get(alias).add(entry);
}
// 2.2. move blocks in the order of their dst tiers, from bottom to top
for (int tierOrdinal = mStorageTierAssoc.size() - 1; tierOrdinal >= 0; --tierOrdinal) {
Set<BlockTransferInfo> toMove = blocksGroupedByDestTier.get(mStorageTierAssoc.getAlias(tierOrdinal));
if (toMove == null) {
toMove = new HashSet<>();
}
for (BlockTransferInfo entry : toMove) {
long blockId = entry.getBlockId();
BlockStoreLocation oldLocation = entry.getSrcLocation();
BlockStoreLocation newLocation = entry.getDstLocation();
MoveBlockResult moveResult;
try {
moveResult = moveBlockInternal(sessionId, blockId, oldLocation, newLocation);
} catch (InvalidWorkerStateException e) {
// Evictor is not working properly
LOG.error("Failed to evict blockId {}, this is temp block", blockId);
continue;
} catch (BlockAlreadyExistsException e) {
continue;
} catch (BlockDoesNotExistException e) {
LOG.info("Failed to move blockId {}, it could be already deleted", blockId);
continue;
}
if (moveResult.getSuccess()) {
synchronized (mBlockStoreEventListeners) {
for (BlockStoreEventListener listener : mBlockStoreEventListeners) {
listener.onMoveBlockByWorker(sessionId, blockId, moveResult.getSrcLocation(), newLocation);
}
}
}
}
}
}
use of alluxio.exception.WorkerOutOfSpaceException in project alluxio by Alluxio.
the class TieredBlockStore method commitBlockInternal.
/**
* 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;
try (LockResource r = new LockResource(mMetadataReadLock)) {
checkTempBlockOwnedBySession(sessionId, blockId);
tempBlockMeta = mMetaManager.getTempBlockMeta(blockId);
srcPath = tempBlockMeta.getPath();
dstPath = tempBlockMeta.getCommitPath();
loc = tempBlockMeta.getBlockLocation();
}
// Heavy IO is guarded by block lock but not metadata lock. This may throw IOException.
FileUtils.move(srcPath, dstPath);
try (LockResource r = new LockResource(mMetadataWriteLock)) {
mMetaManager.commitTempBlockMeta(tempBlockMeta);
} catch (BlockAlreadyExistsException | BlockDoesNotExistException | WorkerOutOfSpaceException e) {
// we shall never reach here
throw Throwables.propagate(e);
}
return loc;
} finally {
mLockManager.unlockBlock(lockId);
}
}
use of alluxio.exception.WorkerOutOfSpaceException 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);
}
}
Aggregations