Search in sources :

Example 6 with BlockAlreadyExistsException

use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.

the class TieredBlockStore method freeSpaceInternal.

/**
   * Tries to get an eviction plan to free a certain amount of space in the given location, and
   * carries out this plan with the best effort.
   *
   * @param sessionId the session Id
   * @param availableBytes amount of space in bytes to free
   * @param location location of space
   * @throws WorkerOutOfSpaceException if it is impossible to achieve the free requirement
   * @throws IOException if I/O errors occur when removing or moving block files
   */
private void freeSpaceInternal(long sessionId, long availableBytes, BlockStoreLocation location) throws WorkerOutOfSpaceException, IOException {
    EvictionPlan plan;
    try (LockResource r = new LockResource(mMetadataReadLock)) {
        plan = mEvictor.freeSpaceWithView(availableBytes, location, getUpdatedView());
        // Absent plan means failed to evict enough space.
        if (plan == null) {
            throw new WorkerOutOfSpaceException(ExceptionMessage.NO_EVICTION_PLAN_TO_FREE_SPACE);
        }
    }
    // 1. remove blocks to make room.
    for (Pair<Long, BlockStoreLocation> blockInfo : plan.toEvict()) {
        try {
            removeBlockInternal(sessionId, blockInfo.getFirst(), blockInfo.getSecond());
        } catch (InvalidWorkerStateException e) {
            // Evictor is not working properly
            LOG.error("Failed to evict blockId {}, this is temp block", blockInfo.getFirst());
            continue;
        } catch (BlockDoesNotExistException e) {
            LOG.info("Failed to evict blockId {}, it could be already deleted", blockInfo.getFirst());
            continue;
        }
        synchronized (mBlockStoreEventListeners) {
            for (BlockStoreEventListener listener : mBlockStoreEventListeners) {
                listener.onRemoveBlockByWorker(sessionId, blockInfo.getFirst());
            }
        }
    }
    // 2. transfer blocks among tiers.
    // 2.1. group blocks move plan by the destination tier.
    Map<String, Set<BlockTransferInfo>> blocksGroupedByDestTier = new HashMap<>();
    for (BlockTransferInfo entry : plan.toMove()) {
        String alias = entry.getDstLocation().tierAlias();
        if (!blocksGroupedByDestTier.containsKey(alias)) {
            blocksGroupedByDestTier.put(alias, new HashSet<BlockTransferInfo>());
        }
        blocksGroupedByDestTier.get(alias).add(entry);
    }
    // 2.2. move blocks in the order of their dst tiers, from bottom to top
    for (int tierOrdinal = mStorageTierAssoc.size() - 1; tierOrdinal >= 0; --tierOrdinal) {
        Set<BlockTransferInfo> toMove = blocksGroupedByDestTier.get(mStorageTierAssoc.getAlias(tierOrdinal));
        if (toMove == null) {
            toMove = new HashSet<>();
        }
        for (BlockTransferInfo entry : toMove) {
            long blockId = entry.getBlockId();
            BlockStoreLocation oldLocation = entry.getSrcLocation();
            BlockStoreLocation newLocation = entry.getDstLocation();
            MoveBlockResult moveResult;
            try {
                moveResult = moveBlockInternal(sessionId, blockId, oldLocation, newLocation);
            } catch (InvalidWorkerStateException e) {
                // Evictor is not working properly
                LOG.error("Failed to evict blockId {}, this is temp block", blockId);
                continue;
            } catch (BlockAlreadyExistsException e) {
                continue;
            } catch (BlockDoesNotExistException e) {
                LOG.info("Failed to move blockId {}, it could be already deleted", blockId);
                continue;
            }
            if (moveResult.getSuccess()) {
                synchronized (mBlockStoreEventListeners) {
                    for (BlockStoreEventListener listener : mBlockStoreEventListeners) {
                        listener.onMoveBlockByWorker(sessionId, blockId, moveResult.getSrcLocation(), newLocation);
                    }
                }
            }
        }
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) BlockTransferInfo(alluxio.worker.block.evictor.BlockTransferInfo) WorkerOutOfSpaceException(alluxio.exception.WorkerOutOfSpaceException) BlockAlreadyExistsException(alluxio.exception.BlockAlreadyExistsException) LockResource(alluxio.resource.LockResource) BlockDoesNotExistException(alluxio.exception.BlockDoesNotExistException) EvictionPlan(alluxio.worker.block.evictor.EvictionPlan) InvalidWorkerStateException(alluxio.exception.InvalidWorkerStateException)

Example 7 with BlockAlreadyExistsException

use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.

the class TieredBlockStore method commitBlockInternal.

/**
   * Commits a temp block.
   *
   * @param sessionId the id of session
   * @param blockId the id of block
   * @return destination location to move the block
   * @throws BlockDoesNotExistException if block id can not be found in temporary blocks
   * @throws BlockAlreadyExistsException if block id already exists in committed blocks
   * @throws InvalidWorkerStateException if block id is not owned by session id
   * @throws IOException if I/O errors occur when deleting the block file
   */
private BlockStoreLocation commitBlockInternal(long sessionId, long blockId) throws BlockAlreadyExistsException, InvalidWorkerStateException, BlockDoesNotExistException, IOException {
    long lockId = mLockManager.lockBlock(sessionId, blockId, BlockLockType.WRITE);
    try {
        // When committing TempBlockMeta, the final BlockMeta calculates the block size according to
        // the actual file size of this TempBlockMeta. Therefore, commitTempBlockMeta must happen
        // after moving actual block file to its committed path.
        BlockStoreLocation loc;
        String srcPath;
        String dstPath;
        TempBlockMeta tempBlockMeta;
        try (LockResource r = new LockResource(mMetadataReadLock)) {
            checkTempBlockOwnedBySession(sessionId, blockId);
            tempBlockMeta = mMetaManager.getTempBlockMeta(blockId);
            srcPath = tempBlockMeta.getPath();
            dstPath = tempBlockMeta.getCommitPath();
            loc = tempBlockMeta.getBlockLocation();
        }
        // Heavy IO is guarded by block lock but not metadata lock. This may throw IOException.
        FileUtils.move(srcPath, dstPath);
        try (LockResource r = new LockResource(mMetadataWriteLock)) {
            mMetaManager.commitTempBlockMeta(tempBlockMeta);
        } catch (BlockAlreadyExistsException | BlockDoesNotExistException | WorkerOutOfSpaceException e) {
            // we shall never reach here
            throw Throwables.propagate(e);
        }
        return loc;
    } finally {
        mLockManager.unlockBlock(lockId);
    }
}
Also used : BlockAlreadyExistsException(alluxio.exception.BlockAlreadyExistsException) LockResource(alluxio.resource.LockResource) TempBlockMeta(alluxio.worker.block.meta.TempBlockMeta) BlockDoesNotExistException(alluxio.exception.BlockDoesNotExistException) WorkerOutOfSpaceException(alluxio.exception.WorkerOutOfSpaceException)

Example 8 with BlockAlreadyExistsException

use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.

the class TieredBlockStore method moveBlockInternal.

/**
   * Moves a block to new location only if allocator finds available space in newLocation. This
   * method will not trigger any eviction. Returns {@link MoveBlockResult}.
   *
   * @param sessionId session Id
   * @param blockId block Id
   * @param oldLocation the source location of the block
   * @param newLocation new location to move this block
   * @return the resulting information about the move operation
   * @throws BlockDoesNotExistException if block is not found
   * @throws BlockAlreadyExistsException if a block with same Id already exists in new location
   * @throws InvalidWorkerStateException if the block to move is a temp block
   * @throws IOException if I/O errors occur when moving block file
   */
private MoveBlockResult moveBlockInternal(long sessionId, long blockId, BlockStoreLocation oldLocation, BlockStoreLocation newLocation) throws BlockDoesNotExistException, BlockAlreadyExistsException, InvalidWorkerStateException, IOException {
    long lockId = mLockManager.lockBlock(sessionId, blockId, BlockLockType.WRITE);
    try {
        long blockSize;
        String srcFilePath;
        String dstFilePath;
        BlockMeta srcBlockMeta;
        BlockStoreLocation srcLocation;
        BlockStoreLocation dstLocation;
        try (LockResource r = new LockResource(mMetadataReadLock)) {
            if (mMetaManager.hasTempBlockMeta(blockId)) {
                throw new InvalidWorkerStateException(ExceptionMessage.MOVE_UNCOMMITTED_BLOCK, blockId);
            }
            srcBlockMeta = mMetaManager.getBlockMeta(blockId);
            srcLocation = srcBlockMeta.getBlockLocation();
            srcFilePath = srcBlockMeta.getPath();
            blockSize = srcBlockMeta.getBlockSize();
        }
        if (!srcLocation.belongsTo(oldLocation)) {
            throw new BlockDoesNotExistException(ExceptionMessage.BLOCK_NOT_FOUND_AT_LOCATION, blockId, oldLocation);
        }
        TempBlockMeta dstTempBlock = createBlockMetaInternal(sessionId, blockId, newLocation, blockSize, false);
        if (dstTempBlock == null) {
            return new MoveBlockResult(false, blockSize, null, null);
        }
        // When `newLocation` is some specific location, the `newLocation` and the `dstLocation` are
        // just the same; while for `newLocation` with a wildcard significance, the `dstLocation`
        // is a specific one with specific tier and dir which belongs to newLocation.
        dstLocation = dstTempBlock.getBlockLocation();
        // internally from the newLocation and return success with specific block location.
        if (dstLocation.belongsTo(srcLocation)) {
            mMetaManager.abortTempBlockMeta(dstTempBlock);
            return new MoveBlockResult(true, blockSize, srcLocation, dstLocation);
        }
        dstFilePath = dstTempBlock.getCommitPath();
        // Heavy IO is guarded by block lock but not metadata lock. This may throw IOException.
        FileUtils.move(srcFilePath, dstFilePath);
        try (LockResource r = new LockResource(mMetadataWriteLock)) {
            // If this metadata update fails, we panic for now.
            // TODO(bin): Implement rollback scheme to recover from IO failures.
            mMetaManager.moveBlockMeta(srcBlockMeta, dstTempBlock);
        } catch (BlockAlreadyExistsException | BlockDoesNotExistException | WorkerOutOfSpaceException e) {
            // we shall never reach here
            throw Throwables.propagate(e);
        }
        return new MoveBlockResult(true, blockSize, srcLocation, dstLocation);
    } finally {
        mLockManager.unlockBlock(lockId);
    }
}
Also used : BlockAlreadyExistsException(alluxio.exception.BlockAlreadyExistsException) LockResource(alluxio.resource.LockResource) TempBlockMeta(alluxio.worker.block.meta.TempBlockMeta) BlockMeta(alluxio.worker.block.meta.BlockMeta) TempBlockMeta(alluxio.worker.block.meta.TempBlockMeta) BlockDoesNotExistException(alluxio.exception.BlockDoesNotExistException) WorkerOutOfSpaceException(alluxio.exception.WorkerOutOfSpaceException) InvalidWorkerStateException(alluxio.exception.InvalidWorkerStateException)

Example 9 with BlockAlreadyExistsException

use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.

the class BlockMetadataManager method commitTempBlockMeta.

/**
   * Commits a temp block.
   *
   * @param tempBlockMeta the metadata 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);
}
Also used : BlockAlreadyExistsException(alluxio.exception.BlockAlreadyExistsException) StorageDir(alluxio.worker.block.meta.StorageDir) AbstractBlockMeta(alluxio.worker.block.meta.AbstractBlockMeta) BlockMeta(alluxio.worker.block.meta.BlockMeta) TempBlockMeta(alluxio.worker.block.meta.TempBlockMeta)

Example 10 with BlockAlreadyExistsException

use of alluxio.exception.BlockAlreadyExistsException in project alluxio by Alluxio.

the class BlockWorkerTest method commitBlockOnRetry.

/**
   * Tests that commitBlock doesn't throw an exception when {@link BlockAlreadyExistsException} gets
   * thrown by the block store.
   */
@Test
public void commitBlockOnRetry() throws Exception {
    long blockId = mRandom.nextLong();
    long length = mRandom.nextLong();
    long lockId = mRandom.nextLong();
    long sessionId = mRandom.nextLong();
    long usedBytes = mRandom.nextLong();
    String tierAlias = "MEM";
    HashMap<String, Long> usedBytesOnTiers = new HashMap<>();
    usedBytesOnTiers.put(tierAlias, usedBytes);
    BlockMeta blockMeta = PowerMockito.mock(BlockMeta.class);
    BlockStoreLocation blockStoreLocation = PowerMockito.mock(BlockStoreLocation.class);
    BlockStoreMeta blockStoreMeta = PowerMockito.mock(BlockStoreMeta.class);
    when(mBlockStore.lockBlock(sessionId, blockId)).thenReturn(lockId);
    when(mBlockStore.getBlockMeta(sessionId, blockId, lockId)).thenReturn(blockMeta);
    when(mBlockStore.getBlockStoreMeta()).thenReturn(blockStoreMeta);
    when(blockMeta.getBlockLocation()).thenReturn(blockStoreLocation);
    when(blockStoreLocation.tierAlias()).thenReturn(tierAlias);
    when(blockMeta.getBlockSize()).thenReturn(length);
    when(blockStoreMeta.getUsedBytesOnTiers()).thenReturn(usedBytesOnTiers);
    doThrow(new BlockAlreadyExistsException("")).when(mBlockStore).commitBlock(sessionId, blockId);
    mBlockWorker.commitBlock(sessionId, blockId);
}
Also used : BlockAlreadyExistsException(alluxio.exception.BlockAlreadyExistsException) HashMap(java.util.HashMap) Matchers.anyLong(org.mockito.Matchers.anyLong) BlockMeta(alluxio.worker.block.meta.BlockMeta) TempBlockMeta(alluxio.worker.block.meta.TempBlockMeta) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest) Test(org.junit.Test)

Aggregations

BlockAlreadyExistsException (alluxio.exception.BlockAlreadyExistsException)10 TempBlockMeta (alluxio.worker.block.meta.TempBlockMeta)7 WorkerOutOfSpaceException (alluxio.exception.WorkerOutOfSpaceException)5 BlockDoesNotExistException (alluxio.exception.BlockDoesNotExistException)4 InvalidWorkerStateException (alluxio.exception.InvalidWorkerStateException)4 LockResource (alluxio.resource.LockResource)4 BlockMeta (alluxio.worker.block.meta.BlockMeta)4 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 ConnectionFailedException (alluxio.exception.ConnectionFailedException)1 AlluxioTException (alluxio.thrift.AlluxioTException)1 BlockTransferInfo (alluxio.worker.block.evictor.BlockTransferInfo)1 EvictionPlan (alluxio.worker.block.evictor.EvictionPlan)1 LocalFileBlockWriter (alluxio.worker.block.io.LocalFileBlockWriter)1 AbstractBlockMeta (alluxio.worker.block.meta.AbstractBlockMeta)1 StorageDir (alluxio.worker.block.meta.StorageDir)1 StorageDirView (alluxio.worker.block.meta.StorageDirView)1 UnderFileSystemBlockMeta (alluxio.worker.block.meta.UnderFileSystemBlockMeta)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1