use of io.atomix.protocols.raft.storage.system.Configuration in project atomix by atomix.
the class RaftClusterContext method listen.
@Override
public synchronized CompletableFuture<Void> listen(Collection<NodeId> cluster) {
if (joinFuture != null)
return joinFuture;
// If no configuration was loaded from disk, create a new configuration.
if (configuration == null) {
member.setType(RaftMember.Type.PASSIVE);
// Create a set of cluster members, excluding the local member which is joining a cluster.
Set<RaftMember> activeMembers = cluster.stream().filter(m -> !m.equals(member.nodeId())).map(m -> new DefaultRaftMember(m, RaftMember.Type.ACTIVE, member.getLastUpdated())).collect(Collectors.toSet());
// fail the join.
if (activeMembers.isEmpty()) {
return Futures.exceptionalFuture(new IllegalStateException("cannot join empty cluster"));
}
// Create a new configuration and configure the cluster. Once the cluster is configured, the configuration
// will be stored on disk to ensure the cluster can fall back to the provided configuration if necessary.
configure(new Configuration(0, 0, member.getLastUpdated().toEpochMilli(), activeMembers));
}
return join();
}
use of io.atomix.protocols.raft.storage.system.Configuration in project atomix by atomix.
the class InactiveRole method onConfigure.
@Override
public CompletableFuture<ConfigureResponse> onConfigure(ConfigureRequest request) {
raft.checkThread();
logRequest(request);
updateTermAndLeader(request.term(), request.leader());
Configuration configuration = new Configuration(request.index(), request.term(), request.timestamp(), request.members());
// Configure the cluster membership. This will cause this server to transition to the
// appropriate state if its type has changed.
raft.getCluster().configure(configuration);
// case the received configuration was an older configuration that was not applied.
if (raft.getCommitIndex() >= raft.getCluster().getConfiguration().index()) {
raft.getCluster().commit();
}
return CompletableFuture.completedFuture(logResponse(ConfigureResponse.builder().withStatus(RaftResponse.Status.OK).build()));
}
use of io.atomix.protocols.raft.storage.system.Configuration in project atomix by atomix.
the class LeaderRole method configure.
/**
* Commits the given configuration.
*/
protected CompletableFuture<Long> configure(Collection<RaftMember> members) {
raft.checkThread();
final long term = raft.getTerm();
return appendAndCompact(new ConfigurationEntry(term, System.currentTimeMillis(), members)).thenComposeAsync(entry -> {
// Store the index of the configuration entry in order to prevent other configurations from
// being logged and committed concurrently. This is an important safety property of Raft.
configuring = entry.index();
raft.getCluster().configure(new Configuration(entry.index(), entry.entry().term(), entry.entry().timestamp(), entry.entry().members()));
return appender.appendEntries(entry.index()).whenComplete((commitIndex, commitError) -> {
raft.checkThread();
if (isRunning() && commitError == null) {
raft.getServiceManager().<OperationResult>apply(entry.index());
}
configuring = 0;
});
}, raft.getThreadContext());
}
use of io.atomix.protocols.raft.storage.system.Configuration in project atomix by atomix.
the class LeaderRole method onReconfigure.
@Override
public CompletableFuture<ReconfigureResponse> onReconfigure(final ReconfigureRequest request) {
raft.checkThread();
logRequest(request);
// See https://groups.google.com/forum/#!topic/raft-dev/t4xj6dJTP6E
if (configuring() || initializing()) {
return CompletableFuture.completedFuture(logResponse(ReconfigureResponse.builder().withStatus(RaftResponse.Status.ERROR).build()));
}
// If the member is not a known member of the cluster, fail the promotion.
DefaultRaftMember existingMember = raft.getCluster().getMember(request.member().nodeId());
if (existingMember == null) {
return CompletableFuture.completedFuture(logResponse(ReconfigureResponse.builder().withStatus(RaftResponse.Status.ERROR).withError(RaftError.Type.UNKNOWN_SESSION).build()));
}
// the leader, fail the request to ensure servers can't reconfigure an old configuration.
if (request.index() > 0 && request.index() < raft.getCluster().getConfiguration().index() || request.term() != raft.getCluster().getConfiguration().term()) {
return CompletableFuture.completedFuture(logResponse(ReconfigureResponse.builder().withStatus(RaftResponse.Status.ERROR).withError(RaftError.Type.CONFIGURATION_ERROR).build()));
}
// If the member type has not changed, complete the configuration change successfully.
if (existingMember.getType() == request.member().getType()) {
Configuration configuration = raft.getCluster().getConfiguration();
return CompletableFuture.completedFuture(logResponse(ReconfigureResponse.builder().withStatus(RaftResponse.Status.OK).withIndex(configuration.index()).withTerm(raft.getCluster().getConfiguration().term()).withTime(raft.getCluster().getConfiguration().time()).withMembers(configuration.members()).build()));
}
// Update the member type.
existingMember.update(request.member().getType(), Instant.now());
Collection<RaftMember> members = raft.getCluster().getMembers();
CompletableFuture<ReconfigureResponse> future = new CompletableFuture<>();
configure(members).whenComplete((index, error) -> {
if (error == null) {
future.complete(logResponse(ReconfigureResponse.builder().withStatus(RaftResponse.Status.OK).withIndex(index).withTerm(raft.getCluster().getConfiguration().term()).withTime(raft.getCluster().getConfiguration().time()).withMembers(members).build()));
} else {
future.complete(logResponse(ReconfigureResponse.builder().withStatus(RaftResponse.Status.ERROR).withError(RaftError.Type.PROTOCOL_ERROR).build()));
}
});
return future;
}
Aggregations