package com.cube.cluster;
import java.time.Instant;
import java.util.Objects;
/**
* Represents a node in the Cube database cluster.
*/
public class ClusterNode {
private final String nodeId;
private final String host;
private final int port;
private final String datacenter;
private final String rack;
private volatile NodeState state;
private volatile Instant lastHeartbeat;
private volatile long version; // For gossip protocol
public enum NodeState {
ALIVE, // Node is responding
SUSPECTED, // Node may be down
DEAD, // Node is confirmed down
LEAVING, // Node is leaving cluster
JOINING // Node is joining cluster
}
public ClusterNode(String nodeId, String host, int port) {
this(nodeId, host, port, "dc1", "rack1");
}
public ClusterNode(String nodeId, String host, int port, String datacenter, String rack) {
this.nodeId = nodeId;
this.host = host;
this.port = port;
this.datacenter = datacenter;
this.rack = rack;
this.state = NodeState.ALIVE;
this.lastHeartbeat = Instant.now();
this.version = 0;
}
public String getNodeId() {
return nodeId;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getDatacenter() {
return datacenter;
}
public String getRack() {
return rack;
}
public NodeState getState() {
return state;
}
public void setState(NodeState state) {
this.state = state;
}
public Instant getLastHeartbeat() {
return lastHeartbeat;
}
public void updateHeartbeat() {
this.lastHeartbeat = Instant.now();
this.state = NodeState.ALIVE;
}
public long getVersion() {
return version;
}
public void incrementVersion() {
this.version++;
}
/**
* Get the endpoint address (host:port)
*/
public String getEndpoint() {
return host + ":" + port;
}
/**
* Check if node is alive
*/
public boolean isAlive() {
return state == NodeState.ALIVE;
}
/**
* Check if node is in same datacenter
*/
public boolean isInSameDatacenter(ClusterNode other) {
return this.datacenter.equals(other.datacenter);
}
/**
* Check if node is in same rack
*/
public boolean isInSameRack(ClusterNode other) {
return this.rack.equals(other.rack);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClusterNode that = (ClusterNode) o;
return Objects.equals(nodeId, that.nodeId);
}
@Override
public int hashCode() {
return Objects.hash(nodeId);
}
@Override
public String toString() {
return "ClusterNode{" +
"nodeId='" + nodeId + '\'' +
", endpoint=" + getEndpoint() +
", state=" + state +
", dc=" + datacenter +
", rack=" + rack +
'}';
}
}