/** 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()); }