use of io.atomix.cluster.NodeId in project atomix by atomix.
the class RaftPartitionGroup method buildPartitions.
private Collection<PartitionMetadata> buildPartitions(ClusterService clusterService) {
int partitionSize = this.partitionSize;
if (partitionSize == 0) {
partitionSize = clusterService.getNodes().size();
}
List<NodeId> sorted = new ArrayList<>(clusterService.getNodes().stream().filter(node -> node.type() == Node.Type.CORE).map(Node::id).collect(Collectors.toSet()));
Collections.sort(sorted);
int length = sorted.size();
int count = Math.min(partitionSize, length);
Set<PartitionMetadata> metadata = Sets.newHashSet();
for (int i = 0; i < partitions.size(); i++) {
PartitionId partitionId = sortedPartitionIds.get(i);
Set<NodeId> set = new HashSet<>(count);
for (int j = 0; j < count; j++) {
set.add(sorted.get((i + j) % length));
}
metadata.add(new PartitionMetadata(partitionId, set));
}
return metadata;
}
use of io.atomix.cluster.NodeId in project atomix by atomix.
the class DefaultClusterMetadataService method sendAdvertisement.
/**
* Sends an anti-entropy advertisement to the given node.
*/
private void sendAdvertisement(Endpoint endpoint) {
clock.increment();
ClusterMetadataAdvertisement advertisement = new ClusterMetadataAdvertisement(Maps.newHashMap(Maps.transformValues(nodes, node -> new NodeDigest(node.timestamp(), node.tombstone()))));
messagingService.sendAndReceive(endpoint, ADVERTISEMENT_MESSAGE, SERIALIZER.encode(advertisement)).whenComplete((response, error) -> {
if (error == null) {
Set<NodeId> nodes = SERIALIZER.decode(response);
for (NodeId nodeId : nodes) {
ReplicatedNode node = this.nodes.get(nodeId);
if (node != null) {
sendUpdate(endpoint, new NodeUpdate(node, clock.increment()));
}
}
} else {
log.warn("Anti-entropy advertisement to {} failed!", endpoint);
}
});
}
use of io.atomix.cluster.NodeId in project atomix by atomix.
the class DefaultClusterMetadataService method handleAdvertisement.
/**
* Handles an anti-entropy advertisement.
*/
private byte[] handleAdvertisement(Endpoint endpoint, byte[] payload) {
LogicalTimestamp timestamp = clock.increment();
ClusterMetadataAdvertisement advertisement = SERIALIZER.decode(payload);
Set<NodeId> staleNodes = nodes.values().stream().map(node -> {
NodeDigest digest = advertisement.digest(node.id());
if (digest == null || node.isNewerThan(digest.timestamp())) {
sendUpdate(endpoint, new NodeUpdate(node, timestamp));
} else if (digest.isNewerThan(node.timestamp())) {
if (digest.tombstone()) {
if (!node.tombstone()) {
nodes.put(node.id(), new ReplicatedNode(node.id(), node.type(), node.endpoint(), node.zone(), node.rack(), node.host(), digest.timestamp(), true));
post(new ClusterMetadataEvent(ClusterMetadataEvent.Type.METADATA_CHANGED, getMetadata()));
}
} else {
return node.id();
}
}
return null;
}).filter(Objects::nonNull).collect(Collectors.toSet());
return SERIALIZER.encode(Sets.newHashSet(Sets.union(Sets.difference(advertisement.digests(), nodes.keySet()), staleNodes)));
}
use of io.atomix.cluster.NodeId in project atomix by atomix.
the class DefaultClusterService method handleMetadataEvent.
/**
* Handles a cluster metadata change event.
*/
private void handleMetadataEvent(ClusterMetadataEvent event) {
// Iterate through all bootstrap nodes and add any missing data nodes, triggering NODE_ADDED events.
// Collect the bootstrap node IDs into a set.
Set<NodeId> bootstrapNodes = event.subject().bootstrapNodes().stream().map(node -> {
StatefulNode existingNode = nodes.get(node.id());
if (existingNode == null) {
StatefulNode newNode = new StatefulNode(node.id(), node.type(), node.endpoint(), node.zone(), node.rack(), node.host());
nodes.put(newNode.id(), newNode);
post(new ClusterEvent(ClusterEvent.Type.NODE_ADDED, newNode));
}
return node.id();
}).collect(Collectors.toSet());
// Filter the set of data node IDs from the local node information.
Set<NodeId> dataNodes = nodes.entrySet().stream().filter(entry -> entry.getValue().type() == Node.Type.CORE).map(entry -> entry.getKey()).collect(Collectors.toSet());
// Compute the set of local data nodes missing in the set of bootstrap nodes.
Set<NodeId> missingNodes = Sets.difference(dataNodes, bootstrapNodes);
// For each missing data node, remove the node and trigger a NODE_REMOVED event.
for (NodeId nodeId : missingNodes) {
StatefulNode existingNode = nodes.remove(nodeId);
if (existingNode != null) {
post(new ClusterEvent(ClusterEvent.Type.NODE_REMOVED, existingNode));
}
}
}
use of io.atomix.cluster.NodeId in project atomix by atomix.
the class PrimaryBackupTest method createClient.
/**
* Creates a Raft client.
*/
private PrimaryBackupClient createClient() throws Throwable {
NodeId nodeId = nextNodeId();
PrimaryBackupClient client = PrimaryBackupClient.builder().withClientName("test").withClusterService(new TestClusterService(nodeId, nodes)).withSessionIdProvider(() -> CompletableFuture.completedFuture(nextSessionId())).withPrimaryElection(election).withProtocol(protocolFactory.newClientProtocol(nodeId)).build();
clients.add(client);
return client;
}
Aggregations