All Downloads are FREE. Search and download functionalities are using the official Maven repository.

alluxio.worker.block.BlockMetadataManager Maven / Gradle / Ivy

There is a newer version: 313
Show newest version
/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.worker.block;

import alluxio.Constants;
import alluxio.StorageTierAssoc;
import alluxio.WorkerStorageTierAssoc;
import alluxio.exception.BlockAlreadyExistsException;
import alluxio.exception.BlockDoesNotExistException;
import alluxio.exception.ExceptionMessage;
import alluxio.exception.InvalidWorkerStateException;
import alluxio.exception.WorkerOutOfSpaceException;
import alluxio.worker.WorkerContext;
import alluxio.worker.block.allocator.Allocator;
import alluxio.worker.block.evictor.Evictor;
import alluxio.worker.block.meta.AbstractBlockMeta;
import alluxio.worker.block.meta.BlockMeta;
import alluxio.worker.block.meta.StorageDir;
import alluxio.worker.block.meta.StorageTier;
import alluxio.worker.block.meta.TempBlockMeta;

import com.google.common.base.Preconditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.concurrent.NotThreadSafe;

/**
 * Manages the metadata of all blocks in managed space. This information is used by the
 * {@link TieredBlockStore}, {@link Allocator} and {@link Evictor}.
 * 

* All operations on block metadata such as {@link StorageTier}, {@link StorageDir} should go * through this class. */ @NotThreadSafe // TODO(bin): consider how to better expose information to Evictor and Allocator. public final class BlockMetadataManager { private static final Logger LOG = LoggerFactory.getLogger(Constants.LOGGER_TYPE); /** A list of managed {@link StorageTier}, in order from lowest tier ordinal to greatest. */ private final List mTiers; /** A map from tier alias to {@link StorageTier}. */ private final Map mAliasToTiers; private BlockMetadataManager() { try { StorageTierAssoc storageTierAssoc = new WorkerStorageTierAssoc(WorkerContext.getConf()); mAliasToTiers = new HashMap<>(storageTierAssoc.size()); mTiers = new ArrayList<>(storageTierAssoc.size()); for (int tierOrdinal = 0; tierOrdinal < storageTierAssoc.size(); tierOrdinal++) { StorageTier tier = StorageTier.newStorageTier(storageTierAssoc.getAlias(tierOrdinal)); mTiers.add(tier); mAliasToTiers.put(tier.getTierAlias(), tier); } } catch (BlockAlreadyExistsException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } catch (WorkerOutOfSpaceException e) { throw new RuntimeException(e); } } /** * Creates a new instance of {@link BlockMetadataManager}. * * @return a {@link BlockMetadataManager} instance */ public static BlockMetadataManager createBlockMetadataManager() { return new BlockMetadataManager(); } /** * Aborts a temp block. * * @param tempBlockMeta the meta data of the temp block to add * @throws BlockDoesNotExistException when block can not be found */ public void abortTempBlockMeta(TempBlockMeta tempBlockMeta) throws BlockDoesNotExistException { StorageDir dir = tempBlockMeta.getParentDir(); dir.removeTempBlockMeta(tempBlockMeta); } /** * Adds a temp block. * * @param tempBlockMeta the meta data of the temp block to add * @throws WorkerOutOfSpaceException when no more space left to hold the block * @throws BlockAlreadyExistsException when the block already exists */ public void addTempBlockMeta(TempBlockMeta tempBlockMeta) throws WorkerOutOfSpaceException, BlockAlreadyExistsException { StorageDir dir = tempBlockMeta.getParentDir(); dir.addTempBlockMeta(tempBlockMeta); } /** * Commits a temp block. * * @param tempBlockMeta the meta data of the temp block to commit * @throws WorkerOutOfSpaceException when no more space left to hold the block * @throws BlockAlreadyExistsException when the block already exists in committed blocks * @throws BlockDoesNotExistException when temp block can not be found */ public void commitTempBlockMeta(TempBlockMeta tempBlockMeta) throws WorkerOutOfSpaceException, BlockAlreadyExistsException, BlockDoesNotExistException { long blockId = tempBlockMeta.getBlockId(); if (hasBlockMeta(blockId)) { BlockMeta blockMeta = getBlockMeta(blockId); throw new BlockAlreadyExistsException(ExceptionMessage.ADD_EXISTING_BLOCK.getMessage(blockId, blockMeta.getBlockLocation().tierAlias())); } BlockMeta block = new BlockMeta(Preconditions.checkNotNull(tempBlockMeta)); StorageDir dir = tempBlockMeta.getParentDir(); dir.removeTempBlockMeta(tempBlockMeta); dir.addBlockMeta(block); } /** * Cleans up the meta data of the given temp block ids. * * @param sessionId the id of the client associated with the temp blocks * @param tempBlockIds the list of temporary block ids to be cleaned up, non temporary block ids * will be ignored. * @deprecated As of version 0.8. */ @Deprecated public void cleanupSessionTempBlocks(long sessionId, List tempBlockIds) { for (StorageTier tier : mTiers) { for (StorageDir dir : tier.getStorageDirs()) { dir.cleanupSessionTempBlocks(sessionId, tempBlockIds); } } } /** * Gets the amount of available space of given location in bytes. Master queries the total number * of bytes available on each tier of the worker, and Evictor/Allocator often cares about the * bytes at a {@link StorageDir}. Throws an {@link IllegalArgumentException} when the location * does not belong to the tiered storage. * * @param location location the check available bytes * @return available bytes */ public long getAvailableBytes(BlockStoreLocation location) { long spaceAvailable = 0; if (location.equals(BlockStoreLocation.anyTier())) { for (StorageTier tier : mTiers) { spaceAvailable += tier.getAvailableBytes(); } return spaceAvailable; } String tierAlias = location.tierAlias(); StorageTier tier = getTier(tierAlias); // TODO(calvin): This should probably be max of the capacity bytes in the dirs? if (location.equals(BlockStoreLocation.anyDirInTier(tierAlias))) { return tier.getAvailableBytes(); } int dirIndex = location.dir(); StorageDir dir = tier.getDir(dirIndex); return dir.getAvailableBytes(); } /** * Gets the metadata of a block given its block id. * * @param blockId the block id * @return metadata of the block * @throws BlockDoesNotExistException if no BlockMeta for this block id is found */ public BlockMeta getBlockMeta(long blockId) throws BlockDoesNotExistException { for (StorageTier tier : mTiers) { for (StorageDir dir : tier.getStorageDirs()) { if (dir.hasBlockMeta(blockId)) { return dir.getBlockMeta(blockId); } } } throw new BlockDoesNotExistException(ExceptionMessage.BLOCK_META_NOT_FOUND, blockId); } /** * Returns the path of a block given its location, or null if the location is not a specific * {@link StorageDir}. Throws an {@link IllegalArgumentException} if the location is not a * specific {@link StorageDir}. * * @param blockId the id of the block * @param location location of a particular {@link StorageDir} to store this block * @return the path of this block in this location */ public String getBlockPath(long blockId, BlockStoreLocation location) { return AbstractBlockMeta.commitPath(getDir(location), blockId); } /** * Gets a summary of the meta data. * * @return the metadata of this block store */ public BlockStoreMeta getBlockStoreMeta() { return BlockStoreMeta.getBlockStoreMeta(this); } /** * Gets a full summary of block store meta data. This is an expensive operation. * * @return the full metadata of this block store */ public BlockStoreMeta getBlockStoreMetaFull() { return BlockStoreMeta.getBlockStoreMetaFull(this); } /** * Gets the {@link StorageDir} given its location in the store. Throws an * {@link IllegalArgumentException} if the location is not a specific dir or the location is * invalid. * * @param location Location of the dir * @return the {@link StorageDir} object */ public StorageDir getDir(BlockStoreLocation location) { if (location.equals(BlockStoreLocation.anyTier()) || location.equals(BlockStoreLocation.anyDirInTier(location.tierAlias()))) { throw new IllegalArgumentException( ExceptionMessage.GET_DIR_FROM_NON_SPECIFIC_LOCATION.getMessage(location)); } return getTier(location.tierAlias()).getDir(location.dir()); } /** * Gets the metadata of a temp block. * * @param blockId the id of the temp block * @return metadata of the block or null * @throws BlockDoesNotExistException when block id can not be found */ public TempBlockMeta getTempBlockMeta(long blockId) throws BlockDoesNotExistException { for (StorageTier tier : mTiers) { for (StorageDir dir : tier.getStorageDirs()) { if (dir.hasTempBlockMeta(blockId)) { return dir.getTempBlockMeta(blockId); } } } throw new BlockDoesNotExistException(ExceptionMessage.TEMP_BLOCK_META_NOT_FOUND, blockId); } /** * Gets the {@link StorageTier} given its tierAlias. Throws an {@link IllegalArgumentException} if * the tierAlias is not found. * * @param tierAlias the alias of this tier * @return the {@link StorageTier} object associated with the alias */ public StorageTier getTier(String tierAlias) { StorageTier tier = mAliasToTiers.get(tierAlias); if (tier == null) { throw new IllegalArgumentException( ExceptionMessage.TIER_ALIAS_NOT_FOUND.getMessage(tierAlias)); } return tier; } /** * Gets the list of {@link StorageTier} managed. * * @return the list of {@link StorageTier}s */ public List getTiers() { return mTiers; } /** * Gets the list of {@link StorageTier} below the tier with the given tierAlias. Throws an * {@link IllegalArgumentException} if the tierAlias is not found. * * @param tierAlias the alias of a tier * @return the list of {@link StorageTier} */ public List getTiersBelow(String tierAlias) { int ordinal = getTier(tierAlias).getTierOrdinal(); return mTiers.subList(ordinal + 1, mTiers.size()); } /** * Gets all the temporary blocks associated with a session, empty list is returned if the session * has no temporary blocks. * * @param sessionId the id of the session * @return A list of temp blocks associated with the session */ public List getSessionTempBlocks(long sessionId) { List sessionTempBlocks = new ArrayList<>(); for (StorageTier tier : mTiers) { for (StorageDir dir : tier.getStorageDirs()) { sessionTempBlocks.addAll(dir.getSessionTempBlocks(sessionId)); } } return sessionTempBlocks; } /** * Checks if the storage has a given block. * * @param blockId the block id * @return true if the block is contained, false otherwise */ public boolean hasBlockMeta(long blockId) { for (StorageTier tier : mTiers) { for (StorageDir dir : tier.getStorageDirs()) { if (dir.hasBlockMeta(blockId)) { return true; } } } return false; } /** * Checks if the storage has a given temp block. * * @param blockId the temp block id * @return true if the block is contained, false otherwise */ public boolean hasTempBlockMeta(long blockId) { for (StorageTier tier : mTiers) { for (StorageDir dir : tier.getStorageDirs()) { if (dir.hasTempBlockMeta(blockId)) { return true; } } } return false; } /** * Moves an existing block to another location currently hold by a temp block. * * @param blockMeta the meta data of the block to move * @param tempBlockMeta a placeholder in the destination directory * @return the new block metadata if success, absent otherwise * @throws BlockDoesNotExistException when the block to move is not found * @throws BlockAlreadyExistsException when the block to move already exists in the destination * @throws WorkerOutOfSpaceException when destination have no extra space to hold the block to * move */ public BlockMeta moveBlockMeta(BlockMeta blockMeta, TempBlockMeta tempBlockMeta) throws BlockDoesNotExistException, WorkerOutOfSpaceException, BlockAlreadyExistsException { StorageDir srcDir = blockMeta.getParentDir(); StorageDir dstDir = tempBlockMeta.getParentDir(); srcDir.removeBlockMeta(blockMeta); BlockMeta newBlockMeta = new BlockMeta(blockMeta.getBlockId(), blockMeta.getBlockSize(), dstDir); dstDir.removeTempBlockMeta(tempBlockMeta); dstDir.addBlockMeta(newBlockMeta); return newBlockMeta; } /** * Moves the metadata of an existing block to another location or throws IOExceptions. Throws an * {@link IllegalArgumentException} if the newLocation is not in the tiered storage. * * @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 BlockDoesNotExistException when the block to move is not found * @throws BlockAlreadyExistsException when the block to move already exists in the destination * @throws WorkerOutOfSpaceException when destination have no extra space to hold the block to * move * @deprecated As of version 0.8. Use {@link #moveBlockMeta(BlockMeta, TempBlockMeta)} instead. */ @Deprecated public BlockMeta moveBlockMeta(BlockMeta blockMeta, BlockStoreLocation newLocation) throws BlockDoesNotExistException, BlockAlreadyExistsException, WorkerOutOfSpaceException { // If existing location belongs to the target location, simply return the current block meta. BlockStoreLocation oldLocation = blockMeta.getBlockLocation(); if (oldLocation.belongsTo(newLocation)) { LOG.info("moveBlockMeta: moving {} to {} is a noop", oldLocation, newLocation); return blockMeta; } long blockSize = blockMeta.getBlockSize(); String 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 WorkerOutOfSpaceException("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; } /** * Removes the metadata of a specific block. * * @param block the meta data of the block to remove * @throws BlockDoesNotExistException when block is not found */ public void removeBlockMeta(BlockMeta block) throws BlockDoesNotExistException { StorageDir dir = block.getParentDir(); dir.removeBlockMeta(block); } /** * Modifies the size of a temp block. * * @param tempBlockMeta the temp block to modify * @param newSize new size in bytes * @throws InvalidWorkerStateException when newSize is smaller than current size */ public void resizeTempBlockMeta(TempBlockMeta tempBlockMeta, long newSize) throws InvalidWorkerStateException { StorageDir dir = tempBlockMeta.getParentDir(); dir.resizeTempBlockMeta(tempBlockMeta, newSize); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy