/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.hops.transaction.context; import io.hops.exception.StorageCallPreventedException; import io.hops.exception.StorageException; import io.hops.exception.TransactionContextException; import io.hops.metadata.common.FinderType; import io.hops.metadata.hdfs.dal.PendingBlockDataAccess; import io.hops.transaction.lock.TransactionLocks; import org.apache.hadoop.hdfs.server.blockmanagement.PendingBlockInfo; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; public class PendingBlockContext extends BaseReplicaContext<BlockPK, PendingBlockInfo> { private final PendingBlockDataAccess<PendingBlockInfo> dataAccess; private boolean allPendingRead = false; public PendingBlockContext(PendingBlockDataAccess dataAccess) { this.dataAccess = dataAccess; } @Override public void update(PendingBlockInfo pendingBlockInfo) throws TransactionContextException { super.update(pendingBlockInfo); if(isLogDebugEnabled()) { log("added-pending", "bid", pendingBlockInfo.getBlockId(), "numInProgress", pendingBlockInfo.getNumReplicas()); } } @Override public void remove(PendingBlockInfo pendingBlockInfo) throws TransactionContextException { super.remove(pendingBlockInfo); if(isLogDebugEnabled()) { log("removed-pending", "bid", pendingBlockInfo.getBlockId()); } } @Override public PendingBlockInfo find(FinderType<PendingBlockInfo> finder, Object... params) throws TransactionContextException, StorageException { PendingBlockInfo.Finder pFinder = (PendingBlockInfo.Finder) finder; switch (pFinder) { case ByBlockIdAndINodeId: return findByBlockId(pFinder, params); } throw new RuntimeException(UNSUPPORTED_FINDER); } @Override public Collection<PendingBlockInfo> findList( FinderType<PendingBlockInfo> finder, Object... params) throws TransactionContextException, StorageException { PendingBlockInfo.Finder pFinder = (PendingBlockInfo.Finder) finder; switch (pFinder) { case All: return findAll(pFinder); case ByINodeId: return findByINodeId(pFinder, params); case ByINodeIds: return findByINodeIds(pFinder, params); } throw new RuntimeException(UNSUPPORTED_FINDER); } @Override public void prepare(TransactionLocks tlm) throws TransactionContextException, StorageException { dataAccess.prepare(getRemoved(), getAdded(), getModified()); } @Override public void clear() throws TransactionContextException { super.clear(); allPendingRead = false; } @Override PendingBlockInfo cloneEntity(PendingBlockInfo pendingBlockInfo) { return cloneEntity(pendingBlockInfo, pendingBlockInfo.getInodeId()); } @Override PendingBlockInfo cloneEntity(PendingBlockInfo pendingBlockInfo, int inodeId) { return new PendingBlockInfo(pendingBlockInfo.getBlockId(), inodeId, pendingBlockInfo.getTimeStamp(), pendingBlockInfo.getNumReplicas()); } @Override BlockPK getKey(PendingBlockInfo pendingBlockInfo) { return new BlockPK(pendingBlockInfo.getBlockId(), pendingBlockInfo.getInodeId()); } private PendingBlockInfo findByBlockId(PendingBlockInfo.Finder pFinder, Object[] params) throws StorageCallPreventedException, StorageException { final long blockId = (Long) params[0]; final int inodeId = (Integer) params[1]; PendingBlockInfo result = null; if (containsByBlock(blockId) || containsByINode(inodeId)) { List<PendingBlockInfo> pblks = getByBlock(blockId); if (pblks != null) { if (pblks.size() > 1) { throw new IllegalStateException( "you should have only one " + "PendingBlockInfo per block"); } if (!pblks.isEmpty()) { result = pblks.get(0); } } hit(pFinder, result, "bid", blockId, "inodeid", inodeId); } else { aboutToAccessStorage(pFinder, params); result = dataAccess.findByPKey(blockId, inodeId); gotFromDB(new BlockPK(blockId, inodeId), result); miss(pFinder, result, "bid", blockId, "inodeid", inodeId); } return result; } private List<PendingBlockInfo> findAll(PendingBlockInfo.Finder pFinder) throws StorageCallPreventedException, StorageException { List<PendingBlockInfo> result = null; if (allPendingRead) { result = new ArrayList<PendingBlockInfo>(getAll()); hit(pFinder, result); } else { aboutToAccessStorage(pFinder); result = dataAccess.findAll(); gotFromDB(result); allPendingRead = true; miss(pFinder, result); } return result; } private List<PendingBlockInfo> findByINodeId(PendingBlockInfo.Finder pFinder, Object[] params) throws StorageCallPreventedException, StorageException { final int inodeId = (Integer) params[0]; List<PendingBlockInfo> result = null; if (containsByINode(inodeId)) { result = getByINode(inodeId); hit(pFinder, result, "inodeid", inodeId); } else { aboutToAccessStorage(pFinder, params); result = dataAccess.findByINodeId(inodeId); gotFromDB(new BlockPK(inodeId), result); miss(pFinder, result, "inodeid", inodeId); } return result; } private List<PendingBlockInfo> findByINodeIds(PendingBlockInfo.Finder pFinder, Object[] params) throws StorageCallPreventedException, StorageException { final int[] inodeIds = (int[]) params[0]; List<PendingBlockInfo> result = null; aboutToAccessStorage(pFinder, params); result = dataAccess.findByINodeIds(inodeIds); gotFromDB(BlockPK.getBlockKeys(inodeIds), result); miss(pFinder, result, "inodeids", Arrays.toString(inodeIds)); return result; } }