private List<Integer> findLeavingServiceSources() { List<Integer> srcIndices = new ArrayList<>(); for (int i = 0; i < getSrcNodes().length; i++) { if (getSrcNodes()[i].isDecommissionInProgress() || (getSrcNodes()[i].isEnteringMaintenance() && getSrcNodes()[i].isAlive())) { srcIndices.add(i); } } return srcIndices; } }
/** * We have all the internal blocks but not enough racks. Thus we do not need * to do decoding but only simply make an extra copy of an internal block. In * this scenario, use this method to choose the source datanode for simple * replication. * @return The index of the source datanode. */ private int chooseSource4SimpleReplication() { Map<String, List<Integer>> map = new HashMap<>(); for (int i = 0; i < getSrcNodes().length; i++) { final String rack = getSrcNodes()[i].getNetworkLocation(); List<Integer> dnList = map.get(rack); if (dnList == null) { dnList = new ArrayList<>(); map.put(rack, dnList); } dnList.add(i); } List<Integer> max = null; for (Map.Entry<String, List<Integer>> entry : map.entrySet()) { if (max == null || entry.getValue().size() > max.size()) { max = entry.getValue(); } } assert max != null; return max.get(0); }
/** * @return true if the current source nodes cover all the internal blocks. * I.e., we only need to have more racks. */ private boolean hasAllInternalBlocks() { final BlockInfoStriped block = (BlockInfoStriped) getBlock(); if (getSrcNodes().length < block.getRealTotalBlockNum()) { return false; } BitSet bitSet = new BitSet(block.getTotalBlockNum()); for (byte index : liveBlockIndicies) { bitSet.set(index); } for (int i = 0; i < block.getRealDataBlockNum(); i++) { if (!bitSet.get(i)) { return false; } } for (int i = block.getDataBlockNum(); i < block.getTotalBlockNum(); i++) { if (!bitSet.get(i)) { return false; } } return true; }
private void createReplicationWork(int sourceIndex, DatanodeStorageInfo target) { BlockInfoStriped stripedBlk = (BlockInfoStriped) getBlock(); final byte blockIndex = liveBlockIndicies[sourceIndex]; final DatanodeDescriptor source = getSrcNodes()[sourceIndex]; final long internBlkLen = StripedBlockUtil.getInternalBlockLength( stripedBlk.getNumBytes(), stripedBlk.getCellSize(), stripedBlk.getDataBlockNum(), blockIndex); final Block targetBlk = new Block(stripedBlk.getBlockId() + blockIndex, internBlkLen, stripedBlk.getGenerationStamp()); source.addBlockToBeReplicated(targetBlk, new DatanodeStorageInfo[] {target}); if (BlockManager.LOG.isDebugEnabled()) { BlockManager.LOG.debug("Add replication task from source {} to " + "target {} for EC block {}", source, target, targetBlk); } }
@Override void chooseTargets(BlockPlacementPolicy blockplacement, BlockStoragePolicySuite storagePolicySuite, Set<Node> excludedNodes) { // TODO: new placement policy for EC considering multiple writers DatanodeStorageInfo[] chosenTargets = blockplacement.chooseTarget( getSrcPath(), getAdditionalReplRequired(), getSrcNodes()[0], getLiveReplicaStorages(), false, excludedNodes, getBlockSize(), storagePolicySuite.getPolicy(getStoragePolicyID()), null); setTargets(chosenTargets); }
@Override void addTaskToDatanode(NumberReplicas numberReplicas) { final DatanodeStorageInfo[] targets = getTargets(); assert targets.length > 0; BlockInfoStriped stripedBlk = (BlockInfoStriped) getBlock(); if (hasNotEnoughRack()) { // if we already have all the internal blocks, but not enough racks, // we only need to replicate one internal block to a new rack int sourceIndex = chooseSource4SimpleReplication(); createReplicationWork(sourceIndex, targets[0]); } else if ((numberReplicas.decommissioning() > 0 || numberReplicas.liveEnteringMaintenanceReplicas() > 0) && hasAllInternalBlocks()) { List<Integer> leavingServiceSources = findLeavingServiceSources(); // decommissioningSources.size() should be >= targets.length final int num = Math.min(leavingServiceSources.size(), targets.length); for (int i = 0; i < num; i++) { createReplicationWork(leavingServiceSources.get(i), targets[i]); } } else { targets[0].getDatanodeDescriptor().addBlockToBeErasureCoded( new ExtendedBlock(blockPoolId, stripedBlk), getSrcNodes(), targets, getLiveBlockIndicies(), stripedBlk.getErasureCodingPolicy()); } }