code: private boolean setupPipelineForAppend(LocatedBlock lastBlock) throws IOException {
      if (nodes == null || nodes.length == 0) {
        String msg = "Could not get block locations. " +
            "Source file \"" + src
            + "\" - Aborting...";
        DFSClient.LOG.warn(msg);
        setLastException(new IOException(msg));
        closed = true;
        if (streamer != null) streamer.close();
        return false;
      }
      
      boolean success = createBlockOutputStream(nodes, dfsClient.clientName, false, true);
      long oldGenerationStamp = 
          ((LocatedBlockWithOldGS)lastBlock).getOldGenerationStamp();
      
      if (success) {
        // bump up the generation stamp in NN.
        Block newBlock = lastBlock.getBlock();
        Block oldBlock = new Block(newBlock.getBlockId(), newBlock.getNumBytes(), 
            oldGenerationStamp);
        dfsClient.namenode.updatePipeline(dfsClient.clientName, 
            oldBlock, newBlock, nodes);
      } else {
        DFSClient.LOG.warn("Fall back to block recovery process when trying" +
            " to setup the append pipeline for file " + src);
        // set the old generation stamp 
        block.setGenerationStamp(oldGenerationStamp);
        // fall back the block recovery
        while(processDatanodeError(true, true)) {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException  e) {
            lastException = new IOException(e);
            break;
          }
        }
      }
      return success;
    }
docs: Setup the Append pipeline, the length of current pipeline will shrink
  if any datanodes are dead during the process.