/*
* 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.UfsBlockAccessTokenUnavailableException;
import alluxio.exception.WorkerOutOfSpaceException;
import alluxio.proto.dataserver.Protocol;
import alluxio.wire.FileInfo;
import alluxio.worker.SessionCleanable;
import alluxio.worker.Worker;
import alluxio.worker.block.io.BlockReader;
import alluxio.worker.block.io.BlockWriter;
import alluxio.worker.block.meta.BlockMeta;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
* A block worker in the Alluxio system.
*/
public interface BlockWorker extends Worker, SessionCleanable {
/**
* @return the worker data service bind host
*/
BlockStore getBlockStore();
/**
* @return the worker id
*/
AtomicReference<Long> getWorkerId();
/**
* @return the worker service handler
*/
BlockWorkerClientServiceHandler getWorkerServiceHandler();
/**
* Aborts the temporary block created by the session.
*
* @param sessionId the id of the client
* @param blockId the id of the block to be aborted
* @throws BlockAlreadyExistsException if blockId already exists in committed blocks
* @throws BlockDoesNotExistException if the temporary block cannot be found
* @throws InvalidWorkerStateException if blockId does not belong to sessionId
*/
void abortBlock(long sessionId, long blockId) throws BlockAlreadyExistsException,
BlockDoesNotExistException, InvalidWorkerStateException, IOException;
/**
* Access the block for a given session. This should be called to update the evictor when
* necessary.
*
* @param sessionId the id of the client
* @param blockId the id of the block to access
* @throws BlockDoesNotExistException this exception is not thrown in the tiered block store
* implementation
*/
void accessBlock(long sessionId, long blockId) throws BlockDoesNotExistException;
/**
* Commits a block to Alluxio managed space. The block must be temporary. The block is persisted
* after {@link BlockStore#commitBlock(long, long)}. The block will not be accessible until
* {@link BlockMasterClient#commitBlock(long, long, String, long, long)} succeeds.
*
* @param sessionId the id of the client
* @param blockId the id of the block to commit
* @throws BlockAlreadyExistsException if blockId already exists in committed blocks
* @throws BlockDoesNotExistException if the temporary block cannot be found
* @throws InvalidWorkerStateException if blockId does not belong to sessionId
* @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;
/**
* Creates a block in Alluxio managed space. The block will be temporary until it is committed.
* Throws an {@link IllegalArgumentException} if the location does not belong to tiered storage.
*
* @param sessionId the id of the client
* @param blockId the id of the block to create
* @param tierAlias the alias of the tier to place the new block in,
* {@link BlockStoreLocation#ANY_TIER} for any tier
* @param initialBytes the initial amount of bytes to be allocated
* @return a string representing the path to the local file
* @throws BlockAlreadyExistsException if blockId 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
*/
String createBlock(long sessionId, long blockId, String tierAlias, long initialBytes)
throws BlockAlreadyExistsException, WorkerOutOfSpaceException, IOException;
/**
* Creates a block. This method is only called from a data server.
* Calls {@link #getTempBlockWriterRemote(long, long)} to get a writer for writing to the block.
* Throws an {@link IllegalArgumentException} if the location does not belong to tiered storage.
*
* @param sessionId the id of the client
* @param blockId the id of the block to be created
* @param tierAlias the alias of the tier to place the new block in
* @param initialBytes the initial amount of bytes to be allocated
* @throws BlockAlreadyExistsException if blockId 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
*/
void createBlockRemote(long sessionId, long blockId, String tierAlias, long initialBytes)
throws BlockAlreadyExistsException, WorkerOutOfSpaceException, IOException;
/**
* Frees space to make a specific amount of bytes available in the tier.
*
* @param sessionId the session id
* @param availableBytes the amount of free space in bytes
* @param tierAlias the alias of the tier to free space
* @throws WorkerOutOfSpaceException if there is not enough space
* @throws BlockDoesNotExistException if blocks can not be found
* @throws BlockAlreadyExistsException if blocks to move already exists in destination location
* @throws InvalidWorkerStateException if blocks to move/evict is uncommitted
*/
void freeSpace(long sessionId, long availableBytes, String tierAlias)
throws WorkerOutOfSpaceException, BlockDoesNotExistException, IOException,
BlockAlreadyExistsException, InvalidWorkerStateException;
/**
* Opens a {@link BlockWriter} for an existing temporary block. This method is only called from a
* data server.
*
* The temporary block must already exist with
* {@link #createBlockRemote(long, long, String, long)}.
*
* @param sessionId the id of the client
* @param blockId the id of the block to be opened for writing
* @return the block writer for the local block file
* @throws BlockDoesNotExistException if the block cannot be found
* @throws BlockAlreadyExistsException if a committed block with the same ID exists
* @throws InvalidWorkerStateException if the worker state is invalid
*/
BlockWriter getTempBlockWriterRemote(long sessionId, long blockId)
throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException,
IOException;
/**
* Gets a report for the periodic heartbeat to master. Contains the blocks added since the last
* heart beat and blocks removed since the last heartbeat.
*
* @return a block heartbeat report
*/
BlockHeartbeatReport getReport();
/**
* Gets the metadata for the entire block store. Contains the block mapping per storage dir and
* the total capacity and used capacity of each tier. This function is cheap.
*
* @return the block store metadata
*/
BlockStoreMeta getStoreMeta();
/**
* Similar as {@link BlockWorker#getStoreMeta} except that this also contains full blockId
* list. This function is expensive.
*
* @return the full block store metadata
*/
BlockStoreMeta getStoreMetaFull();
/**
* Gets the metadata of a block given its blockId or throws IOException. 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 {@link BlockMeta} for this blockId is found
*/
BlockMeta getVolatileBlockMeta(long blockId) throws BlockDoesNotExistException;
/**
* Gets the metadata of a specific block from local storage.
* <p>
* Unlike {@link #getVolatileBlockMeta(long)}, 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;
/**
* 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);
/**
* Obtains a read lock the block.
*
* @param sessionId the id of the client
* @param blockId the id of the block to be locked
* @return the lock id that uniquely identifies the lock obtained
* @throws BlockDoesNotExistException if blockId cannot be found, for example, evicted already
*/
long lockBlock(long sessionId, long blockId) throws BlockDoesNotExistException;
/**
* Obtains a read lock the block without throwing an exception. If the lock fails, return
* {@link BlockLockManager#INVALID_LOCK_ID}.
*
* @param sessionId the id of the client
* @param blockId the id of the block to be locked
* @return the lock id that uniquely identifies the lock obtained or
* {@link BlockLockManager#INVALID_LOCK_ID} if it failed to lock
*/
long lockBlockNoException(long sessionId, long blockId);
/**
* Moves a block from its current location to a target location, currently only tier level moves
* are supported. Throws an {@link IllegalArgumentException} if the tierAlias is out of range of
* tiered storage.
*
* @param sessionId the id of the client
* @param blockId the id of the block to move
* @param tierAlias the alias of the tier to move the block to
* @throws BlockDoesNotExistException if blockId cannot be found
* @throws BlockAlreadyExistsException if blockId already exists in committed blocks of the
* newLocation
* @throws InvalidWorkerStateException if blockId has not been committed
* @throws WorkerOutOfSpaceException if newLocation does not have enough extra space to hold the
* block
*/
void moveBlock(long sessionId, long blockId, String tierAlias)
throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException,
WorkerOutOfSpaceException, IOException;
/**
* Gets the path to the block file in local storage. The block must be a permanent block, and the
* caller must first obtain the lock on the block.
*
* @param sessionId the id of the client
* @param blockId the id of the block to read
* @param lockId the id of the lock on this block
* @return a string representing the path to this block in local storage
* @throws BlockDoesNotExistException if the blockId cannot be found in committed blocks or lockId
* cannot be found
* @throws InvalidWorkerStateException if sessionId or blockId is not the same as that in the
* LockRecord of lockId
*/
String readBlock(long sessionId, long blockId, long lockId)
throws BlockDoesNotExistException, InvalidWorkerStateException;
/**
* Gets the block reader for the block. This method is only called by a data server.
*
* @param sessionId the id of the client
* @param blockId the id of the block to read
* @param lockId the id of the lock on this block
* @return the block reader for the block
* @throws BlockDoesNotExistException if lockId is not found
* @throws InvalidWorkerStateException if sessionId or blockId is not the same as that in the
* LockRecord of lockId
*/
BlockReader readBlockRemote(long sessionId, long blockId, long lockId)
throws BlockDoesNotExistException, InvalidWorkerStateException, IOException;
/**
* Gets a block reader to read a UFS block. This method is only called by the data server.
*
* @param sessionId the client session ID
* @param blockId the ID of the UFS block to read
* @param offset the offset within the block
* @return the block reader instance
* @throws BlockDoesNotExistException if the block does not exist in the UFS block store
*/
BlockReader readUfsBlock(long sessionId, long blockId, long offset)
throws BlockDoesNotExistException, IOException;
/**
* Frees a block from Alluxio managed space.
*
* @param sessionId the id of the client
* @param blockId the id of the block to be freed
* @throws InvalidWorkerStateException if blockId has not been committed
* @throws BlockDoesNotExistException if block cannot be found
*/
void removeBlock(long sessionId, long blockId)
throws InvalidWorkerStateException, BlockDoesNotExistException, IOException;
/**
* Request an amount of space for a block in its storage directory. The block must be a temporary
* block.
*
* @param sessionId the id of the client
* @param blockId the id of the block to allocate space to
* @param additionalBytes the amount of bytes to allocate
* @throws BlockDoesNotExistException if blockId 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;
/**
* Releases the lock with the specified lock id.
*
* @param lockId the id of the lock to release
* @throws BlockDoesNotExistException if lock id cannot be found
*/
void unlockBlock(long lockId) throws BlockDoesNotExistException;
/**
* Releases the lock with the specified session and block id.
*
* @param sessionId the session id
* @param blockId the block id
* @return false if it fails to unlock due to the lock is not found
*/
// TODO(calvin): Remove when lock and reads are separate operations.
boolean unlockBlock(long sessionId, long blockId);
/**
* Handles the heartbeat from a client.
*
* @param sessionId the id of the client
*/
void sessionHeartbeat(long sessionId);
/**
* Sets the pinlist for the underlying block store. Typically called by {@link PinListSync}.
*
* @param pinnedInodes a set of pinned inodes
*/
void updatePinList(Set<Long> pinnedInodes);
/**
* Gets the file information.
*
* @param fileId the file id
* @return the file info
*/
FileInfo getFileInfo(long fileId) throws IOException;
/**
* Opens a UFS block. It registers the block metadata information to the UFS block store. It
* throws an {@link UfsBlockAccessTokenUnavailableException} if the number of concurrent readers
* on this block exceeds a threshold.
*
* @param sessionId the session ID
* @param blockId the block ID
* @param options the options
* @return whether the UFS block is successfully opened
* @throws BlockAlreadyExistsException if the UFS block already exists in the
* {@link UnderFileSystemBlockStore}
*/
boolean openUfsBlock(long sessionId, long blockId, Protocol.OpenUfsBlockOptions options)
throws BlockAlreadyExistsException;
/**
* Closes a UFS block for a client session. It also commits the block to Alluxio block store
* if the UFS block has been cached successfully.
*
* @param sessionId the session ID
* @param blockId the block ID
* @throws BlockAlreadyExistsException if it fails to commit the block to Alluxio block store
* because the block exists in the Alluxio block store
* @throws BlockDoesNotExistException if the UFS block does not exist in the
* {@link UnderFileSystemBlockStore}
* @throws WorkerOutOfSpaceException the the worker does not have enough space to commit the block
*/
void closeUfsBlock(long sessionId, long blockId)
throws BlockAlreadyExistsException, BlockDoesNotExistException, IOException,
WorkerOutOfSpaceException;
}