/** Return all of the neighbors with whom we share the provided range. */
  static Set<InetAddress> getNeighbors(String table, Range<Token> toRepair) {
    StorageService ss = StorageService.instance;
    Map<Range<Token>, List<InetAddress>> replicaSets = ss.getRangeToAddressMap(table);
    Range<Token> rangeSuperSet = null;
    for (Range<Token> range : ss.getLocalRanges(table)) {
      if (range.contains(toRepair)) {
        rangeSuperSet = range;
        break;
      } else if (range.intersects(toRepair)) {
        throw new IllegalArgumentException(
            "Requested range intersects a local range but is not fully contained in one; this would lead to imprecise repair");
      }
    }
    if (rangeSuperSet == null || !replicaSets.containsKey(toRepair)) return Collections.emptySet();

    Set<InetAddress> neighbors = new HashSet<InetAddress>(replicaSets.get(rangeSuperSet));
    neighbors.remove(FBUtilities.getBroadcastAddress());
    // Excluding all node with version <= 0.7 since they don't know how to
    // create a correct merkle tree (they build it over the full range)
    Iterator<InetAddress> iter = neighbors.iterator();
    while (iter.hasNext()) {
      InetAddress endpoint = iter.next();
      if (Gossiper.instance.getVersion(endpoint) <= MessagingService.VERSION_07) {
        logger.info(
            "Excluding "
                + endpoint
                + " from repair because it is on version 0.7 or sooner. You should consider updating this node before running repair again.");
        iter.remove();
      }
    }
    return neighbors;
  }
 public RepairSession(
     Range<Token> range, String tablename, boolean isSequential, String... cfnames) {
   this(
       UUIDGen.makeType1UUIDFromHost(FBUtilities.getBroadcastAddress()).toString(),
       range,
       tablename,
       isSequential,
       cfnames);
 }
 static Message makeVerb(TreeRequest request, int version) {
   try {
     FastByteArrayOutputStream bos = new FastByteArrayOutputStream();
     DataOutputStream dos = new DataOutputStream(bos);
     SERIALIZER.serialize(request, dos, version);
     return new Message(
         FBUtilities.getBroadcastAddress(),
         StorageService.Verb.TREE_REQUEST,
         bos.toByteArray(),
         version);
   } catch (IOException e) {
     throw new RuntimeException(e);
   }
 }
      /** 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();
      }
  /**
   * Responds to the node that requested the given valid tree.
   *
   * @param validator A locally generated validator
   * @param local localhost (parameterized for testing)
   */
  void respond(Validator validator, InetAddress local) {
    MessagingService ms = MessagingService.instance();

    try {
      Message message = TreeResponseVerbHandler.makeVerb(local, validator);
      if (!validator.request.endpoint.equals(FBUtilities.getBroadcastAddress()))
        logger.info(
            String.format(
                "[repair #%s] Sending completed merkle tree to %s for %s",
                validator.request.sessionid, validator.request.endpoint, validator.request.cf));
      ms.sendOneWay(message, validator.request.endpoint);
    } catch (Exception e) {
      logger.error(
          String.format(
              "[repair #%s] Error sending completed merkle tree to %s for %s ",
              validator.request.sessionid, validator.request.endpoint, validator.request.cf),
          e);
    }
  }
 private String repairedNodes() {
   StringBuilder sb = new StringBuilder();
   sb.append(FBUtilities.getBroadcastAddress());
   for (InetAddress ep : endpoints) sb.append(", ").append(ep);
   return sb.toString();
 }
 /**
  * Called after the validation lifecycle to respond with the now valid tree. Runs in
  * Stage.ANTIENTROPY.
  */
 public void run() {
   // respond to the request that triggered this validation
   AntiEntropyService.instance.respond(this, FBUtilities.getBroadcastAddress());
 }