当 dfs.hosts.exclude 的地址写入 conf 之后,refreshNodes 就可以拿到 exclude list 并对其进行操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/** * Rereads conf to get hosts and exclude list file names. * Rereads the files to update the hosts and exclude lists. It * checks if any of the hosts have changed states: */ publicvoidrefreshNodes(final Configuration conf)throws IOException { refreshHostsReader(conf); namesystem.writeLock(); try { refreshDatanodes(); countSoftwareVersions(); } finally { namesystem.writeUnlock(); } }
public void startDecommission(DatanodeDescriptor node) { if (!node.isDecommissionInProgress() && !node.isDecommissioned()) { // Update DN stats maintained by HeartbeatManager hbManager.startDecommission(node); // hbManager.startDecommission will set dead node to decommissioned. if (node.isDecommissionInProgress()) { for (DatanodeStorageInfo storage : node.getStorageInfos()) { LOG.info("Starting decommission of {} {} with {} blocks", node, storage, storage.numBlocks()); } node.getLeavingServiceStatus().setStartTime(monotonicNow()); monitor.startTrackingNode(node); } } else { LOG.trace("startDecommission: Node {} in {}, nothing to do.", node, node.getAdminState()); } }
/** * Move any pending nodes into outOfServiceNodeBlocks to initiate the * decommission or maintenance mode process. * * This method must be executed under the namenode write lock to prevent * the pendingNodes list from being modified externally. */ privatevoidprocessPendingNodes() { while (!pendingNodes.isEmpty() && (maxConcurrentTrackedNodes == 0 || outOfServiceNodeBlocks.size() < maxConcurrentTrackedNodes)) { outOfServiceNodeBlocks.put(pendingNodes.poll(), null); } }
privatevoidcheck() { final List<DatanodeDescriptor> toRemove = newArrayList<>();
if (outOfServiceNodeBlocks.size() == 0) { // No nodes currently being tracked so simply return return; }
// Check if there are any pending nodes to process, ie those where the // storage has not been scanned yet. For all which are pending, scan // the storage and load the under-replicated block list into // outOfServiceNodeBlocks. As this does not modify any external structures // it can be done under the namenode *read* lock, and the lock can be // dropped between each storage on each node. // // TODO - This is an expensive call, depending on how many nodes are // to be processed, but it requires only the read lock and it will // be dropped and re-taken frequently. We may want to throttle this // to process only a few nodes per iteration. outOfServiceNodeBlocks.keySet() .stream() .filter(n -> outOfServiceNodeBlocks.get(n) == null) .forEach(n -> scanDatanodeStorage(n, true));
processMaintenanceNodes(); // First check the pending replication list and remove any blocks // which are now replicated OK. This list is constrained in size so this // call should not be overly expensive. processPendingReplication();
// Now move a limited number of blocks to pending moveBlocksToPending();
// Check if any nodes have reached zero blocks and also update the stats // exposed via JMX for all nodes still being processed. checkForCompletedNodes(toRemove);
// Finally move the nodes to their final state if they are ready. processCompletedNodes(toRemove); }
Iterator<DatanodeDescriptor> nodeIter = Iterables.cycle(iterators.keySet()).iterator(); while (nodeIter.hasNext()) { // Cycle through each node with blocks which still need processed DatanodeDescriptordn= nodeIter.next(); Iterator<BlockInfo> blockIt = iterators.get(dn); while (blockIt.hasNext()) { // Process the blocks for the node until we find one that needs // replication if (blocksProcessed >= blocksPerLock) { blocksProcessed = 0; namesystem.writeUnlock(); namesystem.writeLock(); } blocksProcessed++; if (nextBlockAddedToPending(blockIt, dn)) { // Exit the inner "block" loop so an iterator for the next datanode // is used for the next block. pendingCount++; break; } }