code: private void removeDatanode(DatanodeDescriptor nodeInfo) {
      synchronized (heartbeats) {
        if (nodeInfo.isAlive) {
          updateStats(nodeInfo, false);
          heartbeats.remove(nodeInfo);
          nodeInfo.isAlive = false;
        }
      }
  
      for (Iterator<BlockInfo> it = nodeInfo.getBlockIterator(); it.hasNext();) {
        removeStoredBlock(it.next(), nodeInfo);
      }
      unprotectedRemoveDatanode(nodeInfo);
      clusterMap.remove(nodeInfo);
  
      // remove this datanode from any INodeFileUnderConstruction so
      // concurrent readers don't get down datanodes
      // (we need a copy of the Set since removeTargets may modify it)
      Set<INodeFileUnderConstruction> iNodeFileSet =
        new HashSet<INodeFileUnderConstruction>(nodeInfo.getOpenINodes());
      for (INodeFileUnderConstruction iNodeFile : iNodeFileSet) {
        iNodeFile.removeTarget(nodeInfo);
      }
    }
docs: remove a datanode descriptor
  
  @param nodeInfo datanode descriptor