package com.sap.runlet.operationaltransformation; /** * Accepts change operations from clients and maintains a shared state. If new * clients connect, the full state can be sent to the client for initial * synchronization. When a change {@link Operation} is received from a client * that operation will be based on some state. Since that state the * server may have applied one or more change operations already. In order to * synchronize the requesting client, the server transforms all in-between * change operations for the requesting client and sends those transformation * results back to the requesting client. The client's operation, in turn, is * disseminated to all other clients for them to merge into their local replica * of the global state. * * @author Axel Uhl D043530 * * @param <O> the type of operations that can be applied to the states * @param <S> the type of the states on which the operations perform changes */ public interface Peer<O extends Operation<S>, S> { /** * Enumeration representing the two valid roles a peer can have. There must * be exactly one server, multiple clients are allowed. * * @author Jan Karstens D046040 * */ public enum Role { SERVER, CLIENT } /** * Registers a peer with this peer for replication. From this point on, this * peer will remember which operations it has forwarded to that peer for * later transformation jobs for operations coming in from that client.<p> * * The <tt>peer</tt> is expected to set the state returned by this operation * as its initial state. * * @return the current server state; the calling client can use this as its * initial state */ S addPeer(Peer<O, S> peer); /** * Usually, the framework handles calls to this method and framework users * should therefore not need to call this method. * <p> * * Synchronizes an <tt>operation</tt> from the <tt>source</tt> peer to this * peer. The <tt>source</tt> peer specifies how many operations from this * peer it already merged into its operations sequence before having * executed <tt>operation</tt>. * <p> * * The operation has to be transformed using this peer's operational * transformation and using the sequence of operations applied to the * operation's start state up to this peer's current state. This results in * the operation that needs to be applied to the current state to produce * the next state. * <p> * * After applying this possibly transformed operation to this peer's current * state and thus producing a new current state, all registered peers except * <tt>source</tt> are notified about the change by sending them the * transformed operation. * */ void apply(Peer<O, S> source, O operation, int numberOfOperationsSourceHasMergedFromThis); /** * Applies a change operation locally to the current peer's state. */ void apply(O operation); /** * Tells this peer that the <tt>source</tt> peer has successfully merged * <tt>numberOfMergedOperations</tt> altogether coming from this peer * into its operation sequence. This peer can take this as an opportunity * to clean up the queue and remove the transformed copies of all operations * up to number <tt>numberOfMergedOperations-1</tt>. */ void confirm(Peer<O, S> source, int numberOfMergedOperations); /** * Tells the current state in which the peer is. This is the state constructed by * the sequence of calls to {@link #apply(Operation)} and the merged in notifications * from other peers. */ S getCurrentState(); /** * Blocks until the queue of tasks that works on achieving consistency across peers * has completely drained. This can be useful for testing purposes when you want to * wait until consistency has been reached across clients and server. */ void waitForNotRunning(); }