Search in sources :

Example 1 with PrimaryTerm

use of io.atomix.primitive.partition.PrimaryTerm in project atomix by atomix.

the class PrimaryElectorService method enter.

/**
 * Applies an {@link PrimaryElectorOperations.Enter} commit.
 *
 * @param commit commit entry
 * @return topic leader. If no previous leader existed this is the node that just entered the race.
 */
protected PrimaryTerm enter(Commit<? extends PrimaryElectorOperations.Enter> commit) {
    try {
        PartitionId partitionId = commit.value().partitionId();
        PrimaryTerm oldTerm = term(partitionId);
        Registration registration = new Registration(commit.value().member(), commit.session().sessionId().id());
        PrimaryTerm newTerm = elections.compute(partitionId, (k, v) -> {
            if (v == null) {
                return new ElectionState(partitionId, registration, elections);
            } else {
                if (!v.isDuplicate(registration)) {
                    return new ElectionState(v).addRegistration(registration);
                } else {
                    return v;
                }
            }
        }).term();
        if (!Objects.equals(oldTerm, newTerm)) {
            notifyTermChange(partitionId, newTerm);
            scheduleRebalance();
        }
        return newTerm;
    } catch (Exception e) {
        getLogger().error("State machine operation failed", e);
        throw Throwables.propagate(e);
    }
}
Also used : ServiceExecutor(io.atomix.primitive.service.ServiceExecutor) Arrays(java.util.Arrays) BufferInput(io.atomix.storage.buffer.BufferInput) CHANGE(io.atomix.primitive.partition.impl.PrimaryElectorEvents.CHANGE) PrimaryElectionEvent(io.atomix.primitive.partition.PrimaryElectionEvent) HashMap(java.util.HashMap) PartitionId(io.atomix.primitive.partition.PartitionId) LinkedHashMap(java.util.LinkedHashMap) Lists(com.google.common.collect.Lists) Duration(java.time.Duration) Map(java.util.Map) PrimaryTerm(io.atomix.primitive.partition.PrimaryTerm) KryoNamespace(io.atomix.utils.serializer.KryoNamespace) Session(io.atomix.primitive.session.Session) Scheduled(io.atomix.utils.concurrent.Scheduled) LinkedList(java.util.LinkedList) Commit(io.atomix.primitive.service.Commit) MoreObjects(com.google.common.base.MoreObjects) Throwables(com.google.common.base.Throwables) Set(java.util.Set) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Member(io.atomix.primitive.partition.Member) BufferOutput(io.atomix.storage.buffer.BufferOutput) Objects(java.util.Objects) List(java.util.List) AbstractPrimitiveService(io.atomix.primitive.service.AbstractPrimitiveService) Optional(java.util.Optional) Serializer(io.atomix.utils.serializer.Serializer) PartitionId(io.atomix.primitive.partition.PartitionId) PrimaryTerm(io.atomix.primitive.partition.PrimaryTerm)

Example 2 with PrimaryTerm

use of io.atomix.primitive.partition.PrimaryTerm in project atomix by atomix.

the class PrimaryElectorService method rebalance.

/**
 * Periodically rebalances primaries.
 */
private void rebalance() {
    boolean rebalanced = false;
    for (ElectionState election : elections.values()) {
        // Count the total number of primaries for this election's primary.
        int primaryCount = election.countPrimaries(election.primary);
        // Find the registration with the fewest number of primaries.
        int minCandidateCount = 0;
        for (Registration candidate : election.registrations) {
            if (minCandidateCount == 0) {
                minCandidateCount = election.countPrimaries(candidate);
            } else {
                minCandidateCount = Math.min(minCandidateCount, election.countPrimaries(candidate));
            }
        }
        // primaries then transfer leadership to the candidate.
        if (minCandidateCount < primaryCount) {
            for (Registration candidate : election.registrations) {
                if (election.countPrimaries(candidate) < primaryCount) {
                    PrimaryTerm oldTerm = election.term();
                    elections.put(election.partitionId, election.transfer(candidate.member()));
                    PrimaryTerm newTerm = term(election.partitionId);
                    if (!Objects.equals(oldTerm, newTerm)) {
                        notifyTermChange(election.partitionId, newTerm);
                        rebalanced = true;
                    }
                }
            }
        }
    }
    // change to recognize the primary change and replicate state first.
    if (rebalanced) {
        scheduleRebalance();
    }
}
Also used : PrimaryTerm(io.atomix.primitive.partition.PrimaryTerm)

Example 3 with PrimaryTerm

use of io.atomix.primitive.partition.PrimaryTerm in project atomix by atomix.

the class PrimaryBackupProxy method execute.

private void execute(PrimitiveOperation operation, ComposableFuture<byte[]> future) {
    ExecuteRequest request = ExecuteRequest.request(descriptor, sessionId.id(), clusterService.getLocalNode().id(), operation);
    log.trace("Sending {} to {}", request, term.primary());
    PrimaryTerm term = this.term;
    if (term.primary() != null) {
        protocol.execute(term.primary().nodeId(), request).whenCompleteAsync((response, error) -> {
            if (error == null) {
                log.trace("Received {}", response);
                if (response.status() == Status.OK) {
                    future.complete(response.result());
                } else {
                    if (this.term.term() > term.term()) {
                        execute(operation).whenComplete(future);
                    } else {
                        primaryElection.getTerm().whenComplete((newTerm, termError) -> {
                            if (termError == null) {
                                if (newTerm.term() > term.term() && newTerm.primary() != null) {
                                    execute(operation).whenComplete(future);
                                } else {
                                    future.completeExceptionally(new PrimitiveException.Unavailable());
                                }
                            } else {
                                future.completeExceptionally(new PrimitiveException.Unavailable());
                            }
                        });
                    }
                }
            } else {
                future.completeExceptionally(error);
            }
        }, threadContext);
    } else {
        future.completeExceptionally(new ConnectException());
    }
}
Also used : ExecuteRequest(io.atomix.protocols.backup.protocol.ExecuteRequest) PrimaryTerm(io.atomix.primitive.partition.PrimaryTerm) PrimitiveException(io.atomix.primitive.PrimitiveException) ConnectException(java.net.ConnectException)

Example 4 with PrimaryTerm

use of io.atomix.primitive.partition.PrimaryTerm in project atomix by atomix.

the class PrimaryElectorService method onSessionEnd.

private void onSessionEnd(Session session) {
    listeners.remove(session.sessionId().id());
    Set<PartitionId> partitions = elections.keySet();
    partitions.forEach(partitionId -> {
        PrimaryTerm oldTerm = term(partitionId);
        elections.compute(partitionId, (k, v) -> v.cleanup(session));
        PrimaryTerm newTerm = term(partitionId);
        if (!Objects.equals(oldTerm, newTerm)) {
            notifyTermChange(partitionId, newTerm);
            scheduleRebalance();
        }
    });
}
Also used : PartitionId(io.atomix.primitive.partition.PartitionId) PrimaryTerm(io.atomix.primitive.partition.PrimaryTerm)

Aggregations

PrimaryTerm (io.atomix.primitive.partition.PrimaryTerm)4 PartitionId (io.atomix.primitive.partition.PartitionId)2 MoreObjects (com.google.common.base.MoreObjects)1 Throwables (com.google.common.base.Throwables)1 Lists (com.google.common.collect.Lists)1 Sets (com.google.common.collect.Sets)1 PrimitiveException (io.atomix.primitive.PrimitiveException)1 Member (io.atomix.primitive.partition.Member)1 PrimaryElectionEvent (io.atomix.primitive.partition.PrimaryElectionEvent)1 CHANGE (io.atomix.primitive.partition.impl.PrimaryElectorEvents.CHANGE)1 AbstractPrimitiveService (io.atomix.primitive.service.AbstractPrimitiveService)1 Commit (io.atomix.primitive.service.Commit)1 ServiceExecutor (io.atomix.primitive.service.ServiceExecutor)1 Session (io.atomix.primitive.session.Session)1 ExecuteRequest (io.atomix.protocols.backup.protocol.ExecuteRequest)1 BufferInput (io.atomix.storage.buffer.BufferInput)1 BufferOutput (io.atomix.storage.buffer.BufferOutput)1 Scheduled (io.atomix.utils.concurrent.Scheduled)1 KryoNamespace (io.atomix.utils.serializer.KryoNamespace)1 Serializer (io.atomix.utils.serializer.Serializer)1