/** * Adds the metadata of a new block into this storage dir or throws IOException. * * @param tempBlockMeta the meta data of a temp block to add * @throws IOException if blockId already exists or not enough space */ public void addTempBlockMeta(TempBlockMeta tempBlockMeta) throws IOException { Preconditions.checkNotNull(tempBlockMeta); long userId = tempBlockMeta.getUserId(); long blockId = tempBlockMeta.getBlockId(); long blockSize = tempBlockMeta.getBlockSize(); if (getAvailableBytes() < blockSize) { throw new IOException( "Failed to add TempBlockMeta: blockId " + blockId + " is " + blockSize + " bytes, but only " + getAvailableBytes() + " bytes available"); } if (hasTempBlockMeta(blockId)) { throw new IOException("Failed to add TempBlockMeta: blockId " + blockId + " exists"); } mBlockIdToTempBlockMap.put(blockId, tempBlockMeta); Set<Long> userTempBlocks = mUserIdToTempBlockIdsMap.get(userId); if (userTempBlocks == null) { mUserIdToTempBlockIdsMap.put(userId, Sets.newHashSet(blockId)); } else { userTempBlocks.add(blockId); } reserveSpace(blockSize, false); }
/** * Removes a temp block from this storage dir or throws IOException. * * @param tempBlockMeta the meta data of the temp block to remove * @throws IOException if no temp block is found */ public void removeTempBlockMeta(TempBlockMeta tempBlockMeta) throws IOException { Preconditions.checkNotNull(tempBlockMeta); final long blockId = tempBlockMeta.getBlockId(); final long userId = tempBlockMeta.getUserId(); TempBlockMeta deletedTempBlockMeta = mBlockIdToTempBlockMap.remove(blockId); if (deletedTempBlockMeta == null) { throw new IOException("Failed to remove TempBlockMeta: blockId " + blockId + " not found"); } Set<Long> userBlocks = mUserIdToTempBlockIdsMap.get(userId); if (userBlocks == null) { throw new IOException( "Failed to remove TempBlockMeta: blockId " + blockId + " has userId " + userId + " not found"); } if (!userBlocks.contains(blockId)) { throw new IOException( "Failed to remove TempBlockMeta: blockId " + blockId + " not " + "associated with userId " + userId); } Preconditions.checkState(userBlocks.remove(blockId)); if (userBlocks.isEmpty()) { mUserIdToTempBlockIdsMap.remove(userId); } reclaimSpace(tempBlockMeta.getBlockSize(), false); }
/** * Cleans up the temp block meta data for each block id passed in * * @param userId the ID of the client associated with the temporary blocks * @param tempBlockIds the list of temporary blocks to clean up, non temporary blocks or * nonexistent blocks will be ignored */ public void cleanupUserTempBlocks(long userId, List<Long> tempBlockIds) { Set<Long> userTempBlocks = mUserIdToTempBlockIdsMap.get(userId); // The user's temporary blocks have already been removed. if (userTempBlocks == null) { return; } for (Long tempBlockId : tempBlockIds) { if (!mBlockIdToTempBlockMap.containsKey(tempBlockId)) { // This temp block does not exist in this dir, this is expected for some blocks since the // input list is across all dirs continue; } userTempBlocks.remove(tempBlockId); TempBlockMeta tempBlockMeta = mBlockIdToTempBlockMap.remove(tempBlockId); if (tempBlockMeta != null) { reclaimSpace(tempBlockMeta.getBlockSize(), false); } else { LOG.error("Cannot find blockId {} when cleanup userId {}", tempBlockId, userId); } } if (userTempBlocks.isEmpty()) { mUserIdToTempBlockIdsMap.remove(userId); } else { // This may happen if the client comes back during clean up and creates more blocks or some // temporary blocks failed to be deleted LOG.warn("Blocks still owned by user " + userId + " after cleanup."); } }
/** * Changes the size of a temp block or throws IOException. * * @param tempBlockMeta the meta data of the temp block to resize * @param newSize the new size after change in bytes * @throws IOException */ public void resizeTempBlockMeta(TempBlockMeta tempBlockMeta, long newSize) throws IOException { long oldSize = tempBlockMeta.getBlockSize(); tempBlockMeta.setBlockSize(newSize); if (newSize > oldSize) { reserveSpace(newSize - oldSize, false); } else if (newSize < oldSize) { throw new IOException("Shrinking block, not supported!"); } }
/** * Cleans up the temp block meta data of a specific user. * * @param userId the ID of the user to cleanup * @return A list of temp blocks removed from this dir */ public List<TempBlockMeta> cleanupUser(long userId) { List<TempBlockMeta> blocksToRemove = new ArrayList<TempBlockMeta>(); Set<Long> userTempBlocks = mUserIdToTempBlockIdsMap.get(userId); if (userTempBlocks != null) { for (long blockId : userTempBlocks) { TempBlockMeta tempBlock = mBlockIdToTempBlockMap.remove(blockId); if (tempBlock != null) { blocksToRemove.add(tempBlock); reclaimSpace(tempBlock.getBlockSize(), false); } else { LOG.error("Cannot find blockId {} when cleanup userId {}", blockId, userId); } } mUserIdToTempBlockIdsMap.remove(userId); } return blocksToRemove; }