/**
* Licensed to the zk1931 under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* The ASF 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 com.github.zk1931.jzab;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.util.Set;
/**
* The state machine interface for interacting with {@link Zab}.
*/
public interface StateMachine {
/**
* Converts a message to an idempotent transaction. This method is called only
* on the leader after the Zxid has been assigned but before proposing the
* message to followers.
*
* @param zxid zxid of the message.
* @param message the original message
* @return an idempotent state update based on the original message. This is
* what gets proposed to followers.
*/
ByteBuffer preprocess(Zxid zxid, ByteBuffer message);
/**
* Callback for {@link Zab#send}. This method is called from a single
* thread to ensure that the state updates are applied in the same order
* as they arrived. {@link Zab} assumes that the transaction is successfully
* applied to the state machine when this method returns.
*
* @param zxid zxid of the message
* @param stateUpdate the incremental state update
* @param clientId the id of the client who sends the request. The request
* delivered in RECOVERING phase has clientId sets to null.
* @param ctx the context object.
*/
void deliver(Zxid zxid, ByteBuffer stateUpdate, String clientId, Object ctx);
/**
* Callback for {@link Zab#flush}. This method is called from the same
* thread as the {@link StateMachine#deliver} callback.
*
* @param flushRequest the flush request.
* @param ctx the context object.
*/
void flushed(Zxid zxid, ByteBuffer flushRequest, Object ctx);
/**
* Callback for {@link Zab#takeSnapshot}.
*
* @param filePath the path for the snapshot file.
* @param ctx the context object.
*/
void snapshotDone(String filePath, Object ctx);
/**
* Callback for {@link Zab#remove}.
*
* @param serverId the ID of the server whom gets removed.
* @param ctx the context object.
*/
void removed(String serverId, Object ctx);
/**
* Serializes the application state to a {@link FileOutputStream}.
*
* @param fos file to write the state to.
*/
void save(FileOutputStream fos);
/**
* Deserializes the application state from a {@link FileInputStream}.
*
* @param fis file to read the state from.
*/
void restore(FileInputStream fis);
/**
* Notifies the state machine that {@link Zab} is in recovering phase. When
* {@link Zab} goes from leading/following phase to recovering phase, there
* might be requests that have been submitted to {@link Zab} but haven't been
* delivered back to the state machine. These requests, along with their
* associated contexts, are passed backed to the state machine. Note that
* these requests might or might not have been committed by {@link Zab}.
*
* @param pendingRequests the pending requests, see {@link PendingRequests}.
*/
void recovering(PendingRequests pendingRequests);
/**
* Notifies the state machine that {@link Zab} is in leading phase with given
* sets of active followers and cluster members. This method gets called when
* {@link Zab} transitions from recovering phase to leading phase. It also
* gets called when there is a change in active followers or cluster
* membership while {@link Zab} is in leading phase. This method is called
* from the same thread as {@link StateMachine#deliver}.
*
* @param activeFollowers current alive followers.
* @param clusterMembers the members of new configuration.
*/
void leading(Set<String> activeFollowers, Set<String> clusterMembers);
/**
* Notifies the state machine that {@link Zab} is in following phase with
* given leader and cluster members. This method gets called when {@link Zab}
* transitions from recovering phase to following phase. It also gets called
* when there is a change in cluster membership while {@link Zab} is in
* following phase. This method is called from the same thread as
* {@link StateMachine#deliver}.
*
*
* @param leader current leader.
* @param clusterMembers the members of new configuration.
*/
void following(String leader, Set<String> clusterMembers);
}