/** * Initialize meta data for existing blocks in this StorageDir * * <p>Only paths satisfying the contract defined in {@link BlockMetaBase#commitPath} are legal, * should be in format like {dir}/{blockId}. other paths will be deleted. * * @throws IOException when meta data of existing committed blocks can not be loaded */ private void initializeMeta() throws IOException { File dir = new File(mDirPath); File[] paths = dir.listFiles(); if (paths == null) { return; } for (File path : paths) { if (!path.isFile()) { LOG.error("{} in StorageDir is not a file", path.getAbsolutePath()); try { FileUtils.deleteDirectory(path); } catch (IOException ioe) { LOG.error("can not delete directory {}: {}", path.getAbsolutePath(), ioe); } } else { try { long blockId = Long.valueOf(path.getName()); addBlockMeta(new BlockMeta(blockId, path.length(), this)); } catch (NumberFormatException nfe) { LOG.error( "filename of {} in StorageDir can not be parsed into long", path.getAbsolutePath()); if (path.delete()) { LOG.warn("file {} has been deleted", path.getAbsolutePath()); } else { LOG.error("can not delete file {}", path.getAbsolutePath()); } } catch (IOException ioe) { LOG.error("can not add block meta of file {}: {}", path.getAbsolutePath(), ioe); throw ioe; } } } }
/** * Commits a temp block. * * @param tempBlockMeta the meta data of the temp block to commit * @throws OutOfSpaceException when no more space left to hold the block * @throws AlreadyExistsException when the block already exists in committed blocks * @throws NotFoundException when temp block can not be found */ public synchronized void commitTempBlockMeta(TempBlockMeta tempBlockMeta) throws OutOfSpaceException, AlreadyExistsException, NotFoundException { BlockMeta block = new BlockMeta(Preconditions.checkNotNull(tempBlockMeta)); StorageDir dir = tempBlockMeta.getParentDir(); dir.removeTempBlockMeta(tempBlockMeta); dir.addBlockMeta(block); }
/** * Moves the metadata of an existing block to another location or throws IOExceptions. * * @param blockMeta the meta data of the block to move * @param newLocation new location of the block * @return the new block metadata if success, absent otherwise * @throws IllegalArgumentException when the newLocation is not in the tiered storage * @throws NotFoundException when the block to move is not found * @throws AlreadyExistsException when the block to move already exists in the destination * @throws OutOfSpaceException when destination have no extra space to hold the block to move */ public synchronized BlockMeta moveBlockMeta(BlockMeta blockMeta, BlockStoreLocation newLocation) throws NotFoundException, AlreadyExistsException, OutOfSpaceException { // If existing location belongs to the target location, simply return the current block meta. BlockStoreLocation oldLocation = blockMeta.getBlockLocation(); if (oldLocation.belongTo(newLocation)) { LOG.info("moveBlockMeta: moving {} to {} is a noop", oldLocation, newLocation); return blockMeta; } long blockSize = blockMeta.getBlockSize(); int newTierAlias = newLocation.tierAlias(); StorageTier newTier = getTier(newTierAlias); StorageDir newDir = null; if (newLocation.equals(BlockStoreLocation.anyDirInTier(newTierAlias))) { for (StorageDir dir : newTier.getStorageDirs()) { if (dir.getAvailableBytes() >= blockSize) { newDir = dir; break; } } } else { StorageDir dir = newTier.getDir(newLocation.dir()); if (dir.getAvailableBytes() >= blockSize) { newDir = dir; } } if (newDir == null) { throw new OutOfSpaceException( "Failed to move BlockMeta: newLocation " + newLocation + " does not have enough space for " + blockSize + " bytes"); } StorageDir oldDir = blockMeta.getParentDir(); oldDir.removeBlockMeta(blockMeta); BlockMeta newBlockMeta = new BlockMeta(blockMeta.getBlockId(), blockSize, newDir); newDir.addBlockMeta(newBlockMeta); return newBlockMeta; }