/**
  * Submit differencers for running. All tree *must* have been received before this is called.
  */
 public void submitDifferencers() {
   // We need to difference all trees one against another
   for (int i = 0; i < trees.size() - 1; ++i) {
     TreeResponse r1 = trees.get(i);
     for (int j = i + 1; j < trees.size(); ++j) {
       TreeResponse r2 = trees.get(j);
       Differencer differencer = new Differencer(cfname, r1, r2);
       logger.debug("Queueing comparison {}", differencer);
       differencers.add(differencer);
     }
   }
   differencers.start();
   trees.clear(); // allows gc to do its thing
 }
      /** Send merkle tree request to every involved neighbor. */
      public void sendTreeRequests() {
        // send requests to all nodes
        List<InetAddress> allEndpoints = new ArrayList<InetAddress>(endpoints);
        allEndpoints.add(FBUtilities.getBroadcastAddress());

        if (isSequential) makeSnapshots(endpoints);

        for (InetAddress endpoint : allEndpoints)
          treeRequests.add(
              new TreeRequest(getName(), endpoint, range, new CFPair(tablename, cfname)));

        logger.info(
            String.format(
                "[repair #%s] requesting merkle trees for %s (to %s)",
                getName(), cfname, allEndpoints));
        treeRequests.start();
        requestsSent.signalAll();
      }
      /**
       * Add a new received tree and return the number of remaining tree to be received for the job
       * to be complete.
       *
       * <p>Callers may assume exactly one addTree call will result in zero remaining endpoints.
       */
      public synchronized int addTree(TreeRequest request, MerkleTree tree) {
        // Wait for all request to have been performed (see #3400)
        try {
          requestsSent.await();
        } catch (InterruptedException e) {
          throw new AssertionError("Interrupted while waiting for requests to be sent");
        }

        assert request.cf.right.equals(cfname);
        trees.add(new TreeResponse(request.endpoint, tree));
        return treeRequests.completed(request);
      }
 /** @return true if the @param differencer was the last remaining */
 synchronized boolean completedSynchronization(Differencer differencer) {
   return differencers.completed(differencer) == 0;
 }