@Override public void removeBlock(long sessionId, long blockId, BlockStoreLocation location) throws InvalidWorkerStateException, BlockDoesNotExistException, IOException { removeBlockInternal(sessionId, blockId, location); synchronized (mBlockStoreEventListeners) { for (BlockStoreEventListener listener : mBlockStoreEventListeners) { listener.onRemoveBlockByClient(sessionId, blockId); } } }
@Override public void abortBlock(long sessionId, long blockId) throws BlockAlreadyExistsException, BlockDoesNotExistException, InvalidWorkerStateException, IOException { abortBlockInternal(sessionId, blockId); synchronized (mBlockStoreEventListeners) { for (BlockStoreEventListener listener : mBlockStoreEventListeners) { listener.onAbortBlock(sessionId, blockId); } } }
@Override public void accessBlock(long sessionId, long blockId) throws BlockDoesNotExistException { mMetadataReadLock.lock(); boolean hasBlock = mMetaManager.hasBlockMeta(blockId); mMetadataReadLock.unlock(); if (!hasBlock) { throw new BlockDoesNotExistException(ExceptionMessage.NO_BLOCK_ID_FOUND, blockId); } synchronized (mBlockStoreEventListeners) { for (BlockStoreEventListener listener : mBlockStoreEventListeners) { listener.onAccessBlock(sessionId, blockId); } } }
@Override public void moveBlock( long sessionId, long blockId, BlockStoreLocation oldLocation, BlockStoreLocation newLocation) throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException, WorkerOutOfSpaceException, IOException { for (int i = 0; i < MAX_RETRIES + 1; i++) { MoveBlockResult moveResult = moveBlockInternal(sessionId, blockId, oldLocation, newLocation); if (moveResult.getSuccess()) { synchronized (mBlockStoreEventListeners) { for (BlockStoreEventListener listener : mBlockStoreEventListeners) { listener.onMoveBlockByClient( sessionId, blockId, moveResult.getSrcLocation(), moveResult.getDstLocation()); } } return; } if (i < MAX_RETRIES) { freeSpaceInternal(sessionId, moveResult.getBlockSize(), newLocation); } } throw new WorkerOutOfSpaceException( ExceptionMessage.NO_SPACE_FOR_BLOCK_MOVE, newLocation, blockId, MAX_RETRIES); }
/** * 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; mMetadataReadLock.lock(); try { 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); } } finally { mMetadataReadLock.unlock(); } // 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<String, Set<BlockTransferInfo>>(); 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<BlockTransferInfo>(); } 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); } } } } } }