Search in sources :

Example 1 with ClusterEvent

use of io.atomix.cluster.ClusterEvent in project atomix by atomix.

the class DefaultClusterService method sendHeartbeat.

/**
 * Sends a heartbeat to the given peer.
 */
private void sendHeartbeat(Endpoint endpoint, byte[] payload) {
    messagingService.sendAndReceive(endpoint, HEARTBEAT_MESSAGE, payload).whenComplete((response, error) -> {
        if (error == null) {
            Collection<StatefulNode> nodes = SERIALIZER.decode(response);
            boolean sendHeartbeats = false;
            for (StatefulNode node : nodes) {
                if (this.nodes.putIfAbsent(node.id(), node) == null) {
                    post(new ClusterEvent(ClusterEvent.Type.NODE_ADDED, node));
                    post(new ClusterEvent(ClusterEvent.Type.NODE_ACTIVATED, node));
                    sendHeartbeats = true;
                }
            }
            if (sendHeartbeats) {
                sendHeartbeats();
            }
        } else {
            LOGGER.trace("Sending heartbeat to {} failed", endpoint, error);
        }
    });
}
Also used : ClusterEvent(io.atomix.cluster.ClusterEvent)

Example 2 with ClusterEvent

use of io.atomix.cluster.ClusterEvent 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));
        }
    }
}
Also used : ClusterMetadataEventListener(io.atomix.cluster.ClusterMetadataEventListener) Node(io.atomix.cluster.Node) NodeId(io.atomix.cluster.NodeId) ScheduledFuture(java.util.concurrent.ScheduledFuture) AbstractListenerManager(io.atomix.utils.event.AbstractListenerManager) ClusterEvent(io.atomix.cluster.ClusterEvent) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) ManagedClusterService(io.atomix.cluster.ManagedClusterService) ClusterMetadataEvent(io.atomix.cluster.ClusterMetadataEvent) Threads.namedThreads(io.atomix.utils.concurrent.Threads.namedThreads) State(io.atomix.cluster.Node.State) Map(java.util.Map) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) KryoNamespace(io.atomix.utils.serializer.KryoNamespace) ExecutorService(java.util.concurrent.ExecutorService) ImmutableSet(com.google.common.collect.ImmutableSet) Logger(org.slf4j.Logger) Collection(java.util.Collection) Preconditions.checkNotNull(com.google.common.base.Preconditions.checkNotNull) Set(java.util.Set) Endpoint(io.atomix.messaging.Endpoint) ClusterMetadataService(io.atomix.cluster.ClusterMetadataService) Maps(com.google.common.collect.Maps) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Executors(java.util.concurrent.Executors) TimeUnit(java.util.concurrent.TimeUnit) ClusterEventListener(io.atomix.cluster.ClusterEventListener) MessagingService(io.atomix.messaging.MessagingService) KryoNamespaces(io.atomix.utils.serializer.KryoNamespaces) LoggerFactory.getLogger(org.slf4j.LoggerFactory.getLogger) ClusterService(io.atomix.cluster.ClusterService) Serializer(io.atomix.utils.serializer.Serializer) ClusterEvent(io.atomix.cluster.ClusterEvent) NodeId(io.atomix.cluster.NodeId)

Example 3 with ClusterEvent

use of io.atomix.cluster.ClusterEvent in project atomix by atomix.

the class DefaultClusterService method activateNode.

/**
 * Activates the given node.
 */
private void activateNode(StatefulNode node) {
    StatefulNode existingNode = nodes.get(node.id());
    if (existingNode == null) {
        node.setState(State.ACTIVE);
        nodes.put(node.id(), node);
        post(new ClusterEvent(ClusterEvent.Type.NODE_ADDED, node));
        post(new ClusterEvent(ClusterEvent.Type.NODE_ACTIVATED, node));
        sendHeartbeat(node.endpoint(), SERIALIZER.encode(new ClusterHeartbeat(localNode.id(), localNode.type(), localNode.zone(), localNode.rack(), localNode.host())));
    } else if (existingNode.getState() == State.INACTIVE) {
        existingNode.setState(State.ACTIVE);
        post(new ClusterEvent(ClusterEvent.Type.NODE_ACTIVATED, existingNode));
    }
}
Also used : ClusterEvent(io.atomix.cluster.ClusterEvent)

Example 4 with ClusterEvent

use of io.atomix.cluster.ClusterEvent in project atomix by atomix.

the class AtomixTest method testClientJoinLeave.

/**
 * Tests a client joining and leaving the cluster.
 */
@Test
public void testClientJoinLeave() throws Exception {
    List<CompletableFuture<Atomix>> futures = new ArrayList<>();
    futures.add(startAtomix(Node.Type.CORE, 1, 1, 2, 3));
    futures.add(startAtomix(Node.Type.CORE, 2, 1, 2, 3));
    futures.add(startAtomix(Node.Type.CORE, 3, 1, 2, 3));
    Futures.allOf(futures).join();
    TestClusterEventListener dataListener = new TestClusterEventListener();
    instances.get(0).clusterService().addListener(dataListener);
    Atomix client1 = startAtomix(Node.Type.CLIENT, 4, 1, 2, 3).join();
    // client1 added to data node
    ClusterEvent event1 = dataListener.event();
    assertEquals(ClusterEvent.Type.NODE_ADDED, event1.type());
    event1 = dataListener.event();
    assertEquals(ClusterEvent.Type.NODE_ACTIVATED, event1.type());
    Thread.sleep(1000);
    TestClusterEventListener clientListener = new TestClusterEventListener();
    client1.clusterService().addListener(clientListener);
    Atomix client2 = startAtomix(Node.Type.CLIENT, 5, 1, 2, 3).join();
    // client2 added to data node
    ClusterEvent event2 = dataListener.event();
    assertEquals(ClusterEvent.Type.NODE_ADDED, event2.type());
    event2 = dataListener.event();
    assertEquals(ClusterEvent.Type.NODE_ACTIVATED, event2.type());
    // client2 added to client node
    event1 = clientListener.event();
    assertEquals(ClusterEvent.Type.NODE_ADDED, event1.type());
    event1 = clientListener.event();
    assertEquals(ClusterEvent.Type.NODE_ACTIVATED, event1.type());
    client2.stop().join();
    // client2 removed from data node
    event1 = dataListener.event();
    assertEquals(ClusterEvent.Type.NODE_DEACTIVATED, event1.type());
    event1 = dataListener.event();
    assertEquals(ClusterEvent.Type.NODE_REMOVED, event1.type());
    // client2 removed from client node
    event1 = clientListener.event();
    assertEquals(ClusterEvent.Type.NODE_DEACTIVATED, event1.type());
    event1 = clientListener.event();
    assertEquals(ClusterEvent.Type.NODE_REMOVED, event1.type());
}
Also used : ClusterEvent(io.atomix.cluster.ClusterEvent) CompletableFuture(java.util.concurrent.CompletableFuture) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Example 5 with ClusterEvent

use of io.atomix.cluster.ClusterEvent in project atomix by atomix.

the class DefaultClusterService method deactivateNode.

/**
 * Deactivates the given node.
 */
private void deactivateNode(StatefulNode node) {
    StatefulNode existingNode = nodes.get(node.id());
    if (existingNode != null && existingNode.getState() == State.ACTIVE) {
        existingNode.setState(State.INACTIVE);
        switch(existingNode.type()) {
            case CORE:
                post(new ClusterEvent(ClusterEvent.Type.NODE_DEACTIVATED, existingNode));
                break;
            case DATA:
            case CLIENT:
                post(new ClusterEvent(ClusterEvent.Type.NODE_DEACTIVATED, existingNode));
                post(new ClusterEvent(ClusterEvent.Type.NODE_REMOVED, existingNode));
                break;
            default:
                throw new AssertionError();
        }
    }
}
Also used : ClusterEvent(io.atomix.cluster.ClusterEvent)

Aggregations

ClusterEvent (io.atomix.cluster.ClusterEvent)5 CompletableFuture (java.util.concurrent.CompletableFuture)2 Preconditions.checkNotNull (com.google.common.base.Preconditions.checkNotNull)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Maps (com.google.common.collect.Maps)1 Sets (com.google.common.collect.Sets)1 ClusterEventListener (io.atomix.cluster.ClusterEventListener)1 ClusterMetadataEvent (io.atomix.cluster.ClusterMetadataEvent)1 ClusterMetadataEventListener (io.atomix.cluster.ClusterMetadataEventListener)1 ClusterMetadataService (io.atomix.cluster.ClusterMetadataService)1 ClusterService (io.atomix.cluster.ClusterService)1 ManagedClusterService (io.atomix.cluster.ManagedClusterService)1 Node (io.atomix.cluster.Node)1 State (io.atomix.cluster.Node.State)1 NodeId (io.atomix.cluster.NodeId)1 Endpoint (io.atomix.messaging.Endpoint)1 MessagingService (io.atomix.messaging.MessagingService)1 Threads.namedThreads (io.atomix.utils.concurrent.Threads.namedThreads)1 AbstractListenerManager (io.atomix.utils.event.AbstractListenerManager)1 KryoNamespace (io.atomix.utils.serializer.KryoNamespace)1