/*
* 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.exception.BlockAlreadyExistsException;
import alluxio.exception.BlockDoesNotExistException;
import alluxio.exception.InvalidWorkerStateException;
import alluxio.exception.WorkerOutOfSpaceException;
import alluxio.worker.SessionCleanable;
import alluxio.worker.block.evictor.EvictionPlan;
import alluxio.worker.block.io.BlockReader;
import alluxio.worker.block.io.BlockWriter;
import alluxio.worker.block.meta.BlockMeta;
import alluxio.worker.block.meta.TempBlockMeta;
import java.io.IOException;
import java.util.Set;
/**
* A blob store interface to represent the local storage managing and serving all the blocks in the
* local storage.
*/
interface BlockStore extends SessionCleanable {
/**
* Locks an existing block and guards subsequent reads on this block.
*
* @param sessionId the id of the session to lock this block
* @param blockId the id of the block to lock
* @return the lock id (non-negative) if the lock is acquired successfully
* @throws BlockDoesNotExistException if block id can not be found, for example, evicted already
*/
long lockBlock(long sessionId, long blockId) throws BlockDoesNotExistException;
/**
* Locks an existing block and guards subsequent reads on this block. If the lock fails, return
* {@link BlockLockManager#INVALID_LOCK_ID}.
*
* @param sessionId the id of the session to lock this block
* @param blockId the id of the block to lock
* @return the lock id (non-negative) that uniquely identifies the lock obtained or
* {@link BlockLockManager#INVALID_LOCK_ID} if it failed to lock
*/
long lockBlockNoException(long sessionId, long blockId);
/**
* Releases an acquired block lock based on a lockId (returned by {@link #lockBlock(long, long)}.
*
* @param lockId the id of the lock returned by {@link #lockBlock(long, long)}
* @throws BlockDoesNotExistException if lockId can not be found
*/
void unlockBlock(long lockId) throws BlockDoesNotExistException;
/**
* Releases an acquired block lock based on a session id and block id.
* TODO(calvin): temporary, will be removed after changing client side code.
*
* @param sessionId the id of the session to lock this block
* @param blockId the id of the block to lock
* @return false if it fails to unlock due to the lock is not found
*/
boolean unlockBlock(long sessionId, long blockId);
/**
* Creates the metadata of a new block and assigns a temporary path (e.g., a subdir of the final
* location named after session id) to store its data. The location can be a location with
* specific tier and dir, or {@link BlockStoreLocation#anyTier()}, or
* {@link BlockStoreLocation#anyDirInTier(String)}.
* <p>
* Before commit, all the data written to this block will be stored in the temp path and the block
* is only "visible" to its writer client.
*
* @param sessionId the id of the session
* @param blockId the id of the block to create
* @param location location to create this block
* @param initialBlockSize initial size of this block in bytes
* @return metadata of the temp block created
* @throws IllegalArgumentException if location does not belong to tiered storage
* @throws BlockAlreadyExistsException if block id already exists, either temporary or committed,
* or block in eviction plan already exists
* @throws WorkerOutOfSpaceException if this Store has no more space than the initialBlockSize
*/
TempBlockMeta createBlock(long sessionId, long blockId, BlockStoreLocation location,
long initialBlockSize) throws BlockAlreadyExistsException, WorkerOutOfSpaceException,
IOException;
/**
* Gets the metadata of a block given its block id or throws {@link BlockDoesNotExistException}.
* This method does not require a lock id so the block is possible to be moved or removed after it
* returns.
*
* @param blockId the block id
* @return metadata of the block
* @throws BlockDoesNotExistException if no BlockMeta for this block id is found
*/
BlockMeta getVolatileBlockMeta(long blockId) throws BlockDoesNotExistException;
/**
* Gets the metadata of a specific block from local storage.
* <p>
* This method requires the lock id returned by a previously acquired
* {@link #lockBlock(long, long)}.
*
* @param sessionId the id of the session to get this file
* @param blockId the id of the block
* @param lockId the id of the lock
* @return metadata of the block
* @throws BlockDoesNotExistException if the block id can not be found in committed blocks or
* lockId can not be found
* @throws InvalidWorkerStateException if session id or block id is not the same as that in the
* LockRecord of lockId
*/
BlockMeta getBlockMeta(long sessionId, long blockId, long lockId)
throws BlockDoesNotExistException, InvalidWorkerStateException;
/**
* Gets the temp metadata of a specific block from local storage.
*
* @param sessionId the id of the session to get this file
* @param blockId the id of the block
* @return metadata of the block or null if the temp block does not exist
*/
TempBlockMeta getTempBlockMeta(long sessionId, long blockId);
/**
* Commits a temporary block to the local store. After commit, the block will be available in this
* block store for all clients to access. Since a temp block is "private" to the writer, this
* method requires no previously acquired lock.
*
* @param sessionId the id of the session
* @param blockId the id of a temp block
* @throws BlockAlreadyExistsException if block id already exists in committed blocks
* @throws BlockDoesNotExistException if the temporary block can not be found
* @throws InvalidWorkerStateException if block id does not belong to session id
* @throws WorkerOutOfSpaceException if there is no more space left to hold the block
*/
void commitBlock(long sessionId, long blockId) throws BlockAlreadyExistsException,
BlockDoesNotExistException, InvalidWorkerStateException, IOException,
WorkerOutOfSpaceException;
/**
* Aborts a temporary block. The metadata of this block will not be added, its data will be
* deleted and the space will be reclaimed. Since a temp block is "private" to the writer, this
* requires no previously acquired lock.
*
* @param sessionId the id of the session
* @param blockId the id of a temp block
* @throws BlockAlreadyExistsException if block id already exists in committed blocks
* @throws BlockDoesNotExistException if the temporary block can not be found
* @throws InvalidWorkerStateException if block id does not belong to session id
*/
void abortBlock(long sessionId, long blockId) throws BlockAlreadyExistsException,
BlockDoesNotExistException, InvalidWorkerStateException, IOException;
/**
* Requests to increase the size of a temp block. Since a temp block is "private" to the writer
* client, this operation requires no previously acquired lock.
*
* @param sessionId the id of the session to request space
* @param blockId the id of the temp block
* @param additionalBytes the amount of more space to request in bytes, never be less than 0
* @throws BlockDoesNotExistException if block id can not be found, or some block in eviction plan
* cannot be found
* @throws WorkerOutOfSpaceException if requested space can not be satisfied
*/
void requestSpace(long sessionId, long blockId, long additionalBytes)
throws BlockDoesNotExistException, WorkerOutOfSpaceException, IOException;
/**
* Creates a writer to write data to a temp block. Since the temp block is "private" to the
* writer, this operation requires no previously acquired lock.
*
* @param sessionId the id of the session to get the writer
* @param blockId the id of the temp block
* @return a {@link BlockWriter} instance on this block
* @throws BlockDoesNotExistException if the block can not be found
* @throws BlockAlreadyExistsException if a committed block with the same ID exists
* @throws InvalidWorkerStateException if the worker state is invalid
*/
BlockWriter getBlockWriter(long sessionId, long blockId)
throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException,
IOException;
/**
* Creates a reader of an existing block to read data from this block.
* <p>
* This operation requires the lock id returned by a previously acquired
* {@link #lockBlock(long, long)}.
*
* @param sessionId the id of the session to get the reader
* @param blockId the id of an existing block
* @param lockId the id of the lock returned by {@link #lockBlock(long, long)}
* @return a {@link BlockReader} instance on this block
* @throws BlockDoesNotExistException if lockId is not found
* @throws InvalidWorkerStateException if session id or block id is not the same as that in the
* LockRecord of lockId
*/
BlockReader getBlockReader(long sessionId, long blockId, long lockId)
throws BlockDoesNotExistException, InvalidWorkerStateException, IOException;
/**
* Moves an existing block to a new location.
*
* @param sessionId the id of the session to move a block
* @param blockId the id of an existing block
* @param newLocation the location of the destination
* @throws IllegalArgumentException if newLocation does not belong to the tiered storage
* @throws BlockDoesNotExistException if block id can not be found
* @throws BlockAlreadyExistsException if block id already exists in committed blocks of the
* newLocation
* @throws InvalidWorkerStateException if block id has not been committed
* @throws WorkerOutOfSpaceException if newLocation does not have enough extra space to hold the
* block
*/
void moveBlock(long sessionId, long blockId, BlockStoreLocation newLocation)
throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException,
WorkerOutOfSpaceException, IOException;
/**
* Moves an existing block to a new location.
*
* @param sessionId the id of the session to remove a block
* @param blockId the id of an existing block
* @param oldLocation the location of the source
* @param newLocation the location of the destination
* @throws IllegalArgumentException if newLocation does not belong to the tiered storage
* @throws BlockDoesNotExistException if block id can not be found
* @throws BlockAlreadyExistsException if block id already exists in committed blocks of the
* newLocation
* @throws InvalidWorkerStateException if block id has not been committed
* @throws WorkerOutOfSpaceException if newLocation does not have enough extra space to hold the
* block
*/
void moveBlock(long sessionId, long blockId, BlockStoreLocation oldLocation,
BlockStoreLocation newLocation) throws BlockDoesNotExistException,
BlockAlreadyExistsException, InvalidWorkerStateException, WorkerOutOfSpaceException,
IOException;
/**
* Removes an existing block. If the block can not be found in this store.
*
* @param sessionId the id of the session to remove a block
* @param blockId the id of an existing block
* @throws InvalidWorkerStateException if block id has not been committed
* @throws BlockDoesNotExistException if block can not be found
*/
void removeBlock(long sessionId, long blockId) throws InvalidWorkerStateException,
BlockDoesNotExistException, IOException;
/**
* Removes an existing block. If the block can not be found in this store.
*
* @param sessionId the id of the session to move a block
* @param blockId the id of an existing block
* @param location the location of the block
* @throws InvalidWorkerStateException if block id has not been committed
* @throws BlockDoesNotExistException if block can not be found
*/
void removeBlock(long sessionId, long blockId, BlockStoreLocation location)
throws InvalidWorkerStateException, BlockDoesNotExistException, IOException;
/**
* Notifies the block store that a block was accessed so the block store could update accordingly
* the registered listeners such as evictor and allocator on block access.
*
* @param sessionId the id of the session to access a block
* @param blockId the id of an accessed block
* @throws BlockDoesNotExistException if the block id is not found
*/
void accessBlock(long sessionId, long blockId) throws BlockDoesNotExistException;
/**
* Gets the metadata of the entire store in a snapshot. There is no guarantee the state will be
* consistent with the snapshot after this method is called.
* This function should be cheap since it is called for every block.
*
* @return store metadata
*/
BlockStoreMeta getBlockStoreMeta();
/**
* Similar as {@link BlockStoreMeta#getBlockStoreMeta} except that this includes more information
* about the block store (e.g. blockId list). This is an expensive operation.
*
* @return full store metadata
*/
BlockStoreMeta getBlockStoreMetaFull();
/**
* Checks if the storage has a given block.
*
* @param blockId the block id
* @return true if the block is contained, false otherwise
*/
boolean hasBlockMeta(long blockId);
/**
* Cleans up the data associated with a specific session (typically a dead session). Clean up
* entails unlocking the block locks of this session, reclaiming space of temp blocks created by
* this session, and deleting the session temporary folder.
*
* @param sessionId the session id
*/
void cleanupSession(long sessionId);
/**
* Frees space to make a specific amount of bytes available in the location.
*
* @param sessionId the session id
* @param availableBytes the amount of free space in bytes
* @param location the location to free space
* @throws WorkerOutOfSpaceException if there is not enough space
* @throws BlockDoesNotExistException if blocks in {@link EvictionPlan} can not be found
*/
void freeSpace(long sessionId, long availableBytes, BlockStoreLocation location)
throws WorkerOutOfSpaceException, BlockDoesNotExistException, IOException;
/**
* Registers a {@link BlockStoreEventListener} to this block store.
*
* @param listener the listener to those events
*/
void registerBlockStoreEventListener(BlockStoreEventListener listener);
/**
* Update the pinned inodes.
*
* @param inodes a set of inodes that are currently pinned
*/
void updatePinnedInodes(Set<Long> inodes);
}