use of alluxio.exception.BlockDoesNotExistException 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.BlockDoesNotExistException in project alluxio by Alluxio.
the class AbstractEvictor method cascadingEvict.
/**
* A recursive implementation of cascading eviction.
*
* This method uses a specific eviction strategy to find blocks to evict in the requested
* location. After eviction, one {@link alluxio.worker.block.meta.StorageDir} in the location has
* the specific amount of free space. It then uses an allocation strategy to allocate space in the
* next tier to move each evicted blocks. If the next tier fails to allocate space for the evicted
* blocks, the next tier will continue to evict its blocks to free space.
*
* This method is only used in
* {@link #freeSpaceWithView(long, BlockStoreLocation, BlockMetadataManagerView)}.
*
* @param bytesToBeAvailable bytes to be available after eviction
* @param location target location to evict blocks from
* @param plan the plan to be recursively updated, is empty when first called in
* {@link #freeSpaceWithView(long, BlockStoreLocation, BlockMetadataManagerView)}
* @return the first {@link StorageDirView} in the range of location to evict/move bytes from, or
* null if there is no plan
*/
protected StorageDirView cascadingEvict(long bytesToBeAvailable, BlockStoreLocation location, EvictionPlan plan) {
location = updateBlockStoreLocation(bytesToBeAvailable, location);
// 1. If bytesToBeAvailable can already be satisfied without eviction, return the eligible
// StoargeDirView
StorageDirView candidateDirView = EvictorUtils.selectDirWithRequestedSpace(bytesToBeAvailable, location, mManagerView);
if (candidateDirView != null) {
return candidateDirView;
}
// 2. Iterate over blocks in order until we find a StorageDirView that is in the range of
// location and can satisfy bytesToBeAvailable after evicting its blocks iterated so far
EvictionDirCandidates dirCandidates = new EvictionDirCandidates();
Iterator<Long> it = getBlockIterator();
while (it.hasNext() && dirCandidates.candidateSize() < bytesToBeAvailable) {
long blockId = it.next();
try {
BlockMeta block = mManagerView.getBlockMeta(blockId);
if (block != null) {
// might not present in this view
if (block.getBlockLocation().belongsTo(location)) {
String tierAlias = block.getParentDir().getParentTier().getTierAlias();
int dirIndex = block.getParentDir().getDirIndex();
dirCandidates.add(mManagerView.getTierView(tierAlias).getDirView(dirIndex), blockId, block.getBlockSize());
}
}
} catch (BlockDoesNotExistException e) {
LOG.warn("Remove block {} from evictor cache because {}", blockId, e);
it.remove();
onRemoveBlockFromIterator(blockId);
}
}
// 3. If there is no eligible StorageDirView, return null
if (dirCandidates.candidateSize() < bytesToBeAvailable) {
return null;
}
// 4. cascading eviction: try to allocate space in the next tier to move candidate blocks
// there. If allocation fails, the next tier will continue to evict its blocks to free space.
// Blocks are only evicted from the last tier or it can not be moved to the next tier.
candidateDirView = dirCandidates.candidateDir();
List<Long> candidateBlocks = dirCandidates.candidateBlocks();
StorageTierView nextTierView = mManagerView.getNextTier(candidateDirView.getParentTierView());
if (nextTierView == null) {
// This is the last tier, evict all the blocks.
for (Long blockId : candidateBlocks) {
try {
BlockMeta block = mManagerView.getBlockMeta(blockId);
if (block != null) {
candidateDirView.markBlockMoveOut(blockId, block.getBlockSize());
plan.toEvict().add(new Pair<>(blockId, candidateDirView.toBlockStoreLocation()));
}
} catch (BlockDoesNotExistException e) {
continue;
}
}
} else {
for (Long blockId : candidateBlocks) {
try {
BlockMeta block = mManagerView.getBlockMeta(blockId);
if (block == null) {
continue;
}
StorageDirView nextDirView = mAllocator.allocateBlockWithView(Sessions.MIGRATE_DATA_SESSION_ID, block.getBlockSize(), BlockStoreLocation.anyDirInTier(nextTierView.getTierViewAlias()), mManagerView);
if (nextDirView == null) {
nextDirView = cascadingEvict(block.getBlockSize(), BlockStoreLocation.anyDirInTier(nextTierView.getTierViewAlias()), plan);
}
if (nextDirView == null) {
// If we failed to find a dir in the next tier to move this block, evict it and
// continue. Normally this should not happen.
plan.toEvict().add(new Pair<>(blockId, block.getBlockLocation()));
candidateDirView.markBlockMoveOut(blockId, block.getBlockSize());
continue;
}
plan.toMove().add(new BlockTransferInfo(blockId, block.getBlockLocation(), nextDirView.toBlockStoreLocation()));
candidateDirView.markBlockMoveOut(blockId, block.getBlockSize());
nextDirView.markBlockMoveIn(blockId, block.getBlockSize());
} catch (BlockDoesNotExistException e) {
continue;
}
}
}
return candidateDirView;
}
use of alluxio.exception.BlockDoesNotExistException in project alluxio by Alluxio.
the class WebInterfaceWorkerBlockInfoServlet method doGet.
/**
* Populates attributes before redirecting to a jsp.
*
* @param request the {@link HttpServletRequest} object
* @param response the {@link HttpServletResponse} object
* @throws ServletException if the target resource throws this exception
* @throws IOException if the target resource throws this exception
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("fatalError", "");
String filePath = request.getParameter("path");
if (!(filePath == null || filePath.isEmpty())) {
// Display file block info
try {
UIFileInfo uiFileInfo = getUiFileInfo(new AlluxioURI(filePath));
List<ImmutablePair<String, List<UIFileBlockInfo>>> fileBlocksOnTier = new ArrayList<>();
for (Entry<String, List<UIFileBlockInfo>> e : uiFileInfo.getBlocksOnTier().entrySet()) {
fileBlocksOnTier.add(new ImmutablePair<>(e.getKey(), e.getValue()));
}
request.setAttribute("fileBlocksOnTier", fileBlocksOnTier);
request.setAttribute("blockSizeBytes", uiFileInfo.getBlockSizeBytes());
request.setAttribute("path", filePath);
getServletContext().getRequestDispatcher("/worker/viewFileBlocks.jsp").forward(request, response);
return;
} catch (FileDoesNotExistException e) {
request.setAttribute("fatalError", "Error: Invalid Path " + e.getMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
} catch (IOException e) {
request.setAttribute("invalidPathError", "Error: File " + filePath + " is not available " + e.getMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
} catch (BlockDoesNotExistException e) {
request.setAttribute("fatalError", "Error: block not found. " + e.getMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
} catch (AlluxioException e) {
request.setAttribute("fatalError", "Error: alluxio exception. " + e.getMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
}
}
List<Long> fileIds = getSortedFileIds();
request.setAttribute("nTotalFile", fileIds.size());
request.setAttribute("orderedTierAliases", new WorkerStorageTierAssoc().getOrderedStorageAliases());
// URL can not determine offset and limit, let javascript in jsp determine and redirect
if (request.getParameter("offset") == null && request.getParameter("limit") == null) {
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
}
try {
int offset = Integer.parseInt(request.getParameter("offset"));
int limit = Integer.parseInt(request.getParameter("limit"));
List<Long> subFileIds = fileIds.subList(offset, offset + limit);
List<UIFileInfo> uiFileInfos = new ArrayList<>(subFileIds.size());
for (long fileId : subFileIds) {
try {
uiFileInfos.add(getUiFileInfo(fileId));
} catch (IOException e) {
// The file might have been deleted, log a warning and ignore this file.
LOG.warn("Unable to get file info for fileId {}. {}", fileId, e.getMessage());
}
}
request.setAttribute("fileInfos", uiFileInfos);
} catch (FileDoesNotExistException e) {
request.setAttribute("fatalError", "Error: Invalid FileId " + e.getMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
} catch (NumberFormatException e) {
request.setAttribute("fatalError", "Error: offset or limit parse error, " + e.getLocalizedMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
} catch (IndexOutOfBoundsException e) {
request.setAttribute("fatalError", "Error: offset or offset + limit is out of bound, " + e.getLocalizedMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
} catch (IllegalArgumentException | AlluxioException e) {
request.setAttribute("fatalError", e.getLocalizedMessage());
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
return;
}
getServletContext().getRequestDispatcher("/worker/blockInfo.jsp").forward(request, response);
}
use of alluxio.exception.BlockDoesNotExistException in project alluxio by Alluxio.
the class BlockDataServerHandler method handleUnderFileSystemBlockReadRequest.
/**
* Handles a {@link RPCUnderFileSystemBlockReadRequest} by reading the data through a
* {@link BlockReader} provided by the block worker. This method assumes the data is available
* in the UFS returns an error status if the data is not available.
*
* @param ctx The context of this request which handles the result of this operation
* @param req The initiating {@link RPCBlockReadRequest}
* @throws IOException if an I/O error occurs when reading the data requested
*/
public void handleUnderFileSystemBlockReadRequest(final ChannelHandlerContext ctx, final RPCUnderFileSystemBlockReadRequest req) throws IOException {
final long blockId = req.getBlockId();
final long offset = req.getOffset();
final long len = req.getLength();
final long sessionId = req.getSessionId();
final boolean noCache = req.getNoCache();
try {
DataBuffer buffer = null;
req.validate();
BlockReader reader = mWorker.readUfsBlock(sessionId, blockId, offset, noCache);
ByteBuffer data = reader.read(offset, len);
if (data != null && data.remaining() > 0) {
buffer = new DataByteBuffer(data, data.remaining());
Metrics.BYTES_READ_UFS.inc(buffer.getLength());
}
RPCBlockReadResponse resp = new RPCBlockReadResponse(blockId, offset, data.remaining(), buffer, RPCResponse.Status.SUCCESS);
ChannelFuture future = ctx.writeAndFlush(resp);
if (buffer != null) {
future.addListener(new ReleasableResourceChannelListener(buffer));
}
LOG.debug("Preparation for responding to remote block request for: {} done.", blockId);
} catch (Exception e) {
LOG.error("Exception reading block {}", blockId, e);
RPCBlockReadResponse resp;
if (e instanceof BlockDoesNotExistException) {
resp = RPCBlockReadResponse.createErrorResponse(req, RPCResponse.Status.FILE_DNE);
} else {
resp = RPCBlockReadResponse.createErrorResponse(req, RPCResponse.Status.UFS_READ_FAILED);
}
ChannelFuture future = ctx.writeAndFlush(resp);
future.addListener(ChannelFutureListener.CLOSE);
}
}
use of alluxio.exception.BlockDoesNotExistException in project alluxio by Alluxio.
the class FileDataManager method lockBlocks.
/**
* Locks all the blocks of a given file Id.
*
* @param fileId the id of the file
* @param blockIds the ids of the file's blocks
* @throws IOException when an I/O exception occurs
*/
public void lockBlocks(long fileId, List<Long> blockIds) throws IOException {
Map<Long, Long> blockIdToLockId = new HashMap<>();
List<Throwable> errors = new ArrayList<>();
synchronized (mLock) {
if (mPersistingInProgressFiles.containsKey(fileId)) {
throw new IOException("the file " + fileId + " is already being persisted");
}
}
try {
// lock all the blocks to prevent any eviction
for (long blockId : blockIds) {
long lockId = mBlockWorker.lockBlock(Sessions.CHECKPOINT_SESSION_ID, blockId);
blockIdToLockId.put(blockId, lockId);
}
} catch (BlockDoesNotExistException e) {
errors.add(e);
// make sure all the locks are released
for (long lockId : blockIdToLockId.values()) {
try {
mBlockWorker.unlockBlock(lockId);
} catch (BlockDoesNotExistException bdnee) {
errors.add(bdnee);
}
}
if (!errors.isEmpty()) {
StringBuilder errorStr = new StringBuilder();
errorStr.append("failed to lock all blocks of file ").append(fileId).append("\n");
for (Throwable error : errors) {
errorStr.append(error).append('\n');
}
throw new IOException(errorStr.toString());
}
}
synchronized (mLock) {
mPersistingInProgressFiles.put(fileId, blockIdToLockId);
}
}
Aggregations