/*
* Copyright 2014 WANdisco
*
* WANdisco licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package c5db.interfaces.replication;
import com.google.common.util.concurrent.ListenableFuture;
import org.jetlang.channels.Subscriber;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
/**
* A replicator instance that is used to keep logs in sync across a quorum.
*/
public interface Replicator {
/**
* Return the ID of the quorum (that is, group of coordinating replicators) that this
* replicator belongs to. For a given Replicator instance, this will always return the
* same value.
*/
String getQuorumId();
/**
* Return a future containing the Replicator's current quorum configuration; that is,
* the set of peers it recognizes as being part of its quorum. This set can change
* if directed to locally (for instance using the method changeQuorum) or if a remote
* leader initiates a quorum change.
*/
ListenableFuture<QuorumConfiguration> getQuorumConfiguration();
/**
* Change the members of the quorum to a new collection of peers (which may include peers in
* the current quorum).
*
* @param newPeers The collection of peer IDs in the new quorum.
* @return a future which will return the replicator receipt for logging the transitional
* quorum configuration entry, when the entry's index known. The transitional quorum
* configuration combines the current group of peers with the given collection of new peers.
* When that transitional configuration is committed, the quorum configuration is guaranteed
* to go through; prior to that commit, it is possible that a fault will cancel the quorum
* change operation.
* <p>
* The actual completion of the quorum change will be signaled by a ReplicatorInstanceEvent
* indicating the commitment of the quorum configuration consisting of the given peers,
*/
ListenableFuture<ReplicatorReceipt> changeQuorum(Collection<Long> newPeers) throws InterruptedException;
/**
* Submit data to be replicated.
* TODO we may want a variation of this method which does not block
*
* @param data Some data to log.
* @return a listenable for a receipt for the log request, OR null if we aren't the leader.
* The receipt gives information about the replication request that can be used, in conjunction
* with commit notices, to determine if and when the request was successful.
*/
ListenableFuture<ReplicatorReceipt> logData(List<ByteBuffer> data) throws InterruptedException;
/**
* @return The numerical ID for the server, or node, on which this Replicator resides. More
* than one Replicator may have the same node ID, but any two Replicators operating at the same
* time with the same ID will have different quorum IDs. And, considering all the Replicators
* operating at some time within a single quorum, all must have different node IDs.
*/
long getId();
/**
* Each time the Replicator changes State, it emits that State from this Subscriber.
*/
Subscriber<State> getStateChannel();
// What state is this instance in?
public enum State {
FOLLOWER,
CANDIDATE,
LEADER,
}
/**
* The Replicator issues events from this Subscriber on various conditions. See the comments on
* {@link c5db.interfaces.replication.ReplicatorInstanceEvent} for more information.
*/
Subscriber<ReplicatorInstanceEvent> getEventChannel();
/**
* Get the Replicator's commit notice channel. By matching these issued IndexCommitNotices
* against the ReplicatorReceipts returned when logging entries or changing quorums, users
* of the Replicator can determine whether those submissions were successfully replicated
* to the quorum.
*/
Subscriber<IndexCommitNotice> getCommitNoticeChannel();
}