NodeIDType - This abstract class should be inherited by replica coordination protocols. The only abstract method the inheritor needs to implement is coordinateRequest(.). For example, this method could lazily propagate the request to all replicas; or it could ensure reliable receipt from a threshold number of replicas for durability, and so on. Notes: In general, coordinateRequest(.) is app-specific logic. But most common cases, e.g., linearizability, sequential, causal, eventual, etc. can be implemented agnostic to app-specific details with supporting libraries that we can provide. A request is not an entity that definitively does or does not need coordination. A request, e.g., a read request, may or may not need coordination depending on the replica coordination protocol, which is why it is here.
public abstract class AbstractReplicaCoordinator<NodeIDType> extends java.lang.Object implements Repliconfigurable, ReplicaCoordinator<NodeIDType>, AppRequestParserBytes
| Modifier and Type | Field and Description |
|---|---|
protected Repliconfigurable |
app |
protected Messenger<NodeIDType,?> |
messenger |
| Modifier | Constructor and Description |
|---|---|
protected |
AbstractReplicaCoordinator(Replicable app) |
|
AbstractReplicaCoordinator(Replicable app,
Messenger<NodeIDType,?> messenger) |
| Modifier and Type | Method and Description |
|---|---|
protected void |
callCallback(Request request,
boolean handled,
ExecutedCallback requestCallback) |
java.lang.String |
checkpoint(java.lang.String name)
Checkpoints the current application state and returns it.
|
abstract boolean |
coordinateRequest(Request request,
ExecutedCallback callback)
Start of abstract methods
|
boolean |
createReplicaGroup(java.util.Map<java.lang.String,java.lang.String> nameStates,
java.util.Set<NodeIDType> nodes)
Default implementation that can be overridden for more batching
optimization.
|
abstract boolean |
createReplicaGroup(java.lang.String serviceName,
int epoch,
java.lang.String state,
java.util.Set<NodeIDType> nodes)
This method should return true if the replica group is successfully
created or one already exists with the same set of nodes.
|
boolean |
deleteFinalState(java.lang.String name,
int epoch)
Garbage-collects the final state for name, epoch.
|
abstract boolean |
deleteReplicaGroup(java.lang.String serviceName,
int epoch)
This method should result in all state corresponding to serviceName being
deleted
|
boolean |
execute(Request request) |
boolean |
execute(Request request,
boolean noReplyToClient)
This method must handle the request atomically and return true if
successful or throw an exception or return false.
|
boolean |
execute(Request request,
boolean noReplyToClient,
ExecutedCallback requestCallback)
This method is a wrapper for Application.handleRequest and meant to be
invoked by the class that implements this AbstractReplicaCoordinator or
its helper classes.
|
java.util.Set<IntegerPacketType> |
getAppRequestTypes()
Need to return just app's request types.
|
protected java.lang.String |
getARARNodesAsString() |
protected java.lang.String |
getARRCNodesAsString() |
protected ReconfiguratorCallback |
getCallback() |
java.util.Set<IntegerPacketType> |
getCoordinatorRequestTypes() |
java.lang.Integer |
getEpoch(java.lang.String name)
Returns the current (unique) epoch for name.
|
java.lang.String |
getFinalState(java.lang.String name,
int epoch)
Return the final checkpointed state for name, epoch.
|
protected Messenger<NodeIDType,?> |
getMessenger() |
protected java.util.Set<IntegerPacketType> |
getMutualAuthAppRequestTypes() |
NodeIDType |
getMyID() |
abstract java.util.Set<NodeIDType> |
getReplicaGroup(java.lang.String serviceName)
This method must return the replica group that was most recently
successfully created for the serviceName using createReplicaGroup.
|
Request |
getRequest(byte[] bytes,
NIOHeader header)
The implementation of this method is tied to and must be the inverse of
Request.toBytes(), , i.e., invoking getRequest(request.toBytes(),
header).equals(request). |
protected Request |
getRequest(ReplicableClientRequest rcr,
NIOHeader header) |
Request |
getRequest(java.lang.String stringified)
An application must support string-to-
Request conversion and
back. |
ReconfigurableRequest |
getStopRequest(java.lang.String name,
int epoch)
Returns a stop request that when executed by the app ensures that no
subsequent request after the stop is executed in that epoch.
|
protected boolean |
handleIncoming(Request request,
ExecutedCallback callback)
Coordinate if needed, else hand over to app.
|
boolean |
hasLargeCheckpoints() |
void |
putInitialState(java.lang.String name,
int epoch,
java.lang.String state)
Inserts the specified state as the initial state for name, epoch.
|
protected void |
registerCoordination(IntegerPacketType... types) |
boolean |
restore(java.lang.String name,
java.lang.String state)
Resets the current application state for
name to state. |
protected void |
sendAllLazy(Request request)
Request propagation helper methods
|
protected AbstractReplicaCoordinator<NodeIDType> |
setCallback(ReconfiguratorCallback callback)
This "default" callback will be called after every request execution.
|
void |
setLargeCheckpoints()
Enables large checkpoints.
|
protected void |
setMessenger(Messenger<NodeIDType,?> messenger) |
protected AbstractReplicaCoordinator<NodeIDType> |
setStopCallback(ReconfiguratorCallback callback)
Used only at active replicas.
|
void |
stop()
End of private helper methods
|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitgetMutualAuthRequestTypes, getRequestTypes, getServerAuthRequestTypesprotected final Repliconfigurable app
protected Messenger<NodeIDType,?> messenger
protected AbstractReplicaCoordinator(Replicable app)
public AbstractReplicaCoordinator(Replicable app, Messenger<NodeIDType,?> messenger)
app - messenger - public abstract boolean coordinateRequest(Request request, ExecutedCallback callback) throws java.io.IOException, RequestParseException
coordinateRequest in interface ReplicaCoordinator<NodeIDType>request - callback - java.io.IOExceptionRequestParseExceptionpublic abstract boolean createReplicaGroup(java.lang.String serviceName,
int epoch,
java.lang.String state,
java.util.Set<NodeIDType> nodes)
ReplicaCoordinatorcreateReplicaGroup in interface ReplicaCoordinator<NodeIDType>public abstract boolean deleteReplicaGroup(java.lang.String serviceName,
int epoch)
ReplicaCoordinatordeleteReplicaGroup in interface ReplicaCoordinator<NodeIDType>public abstract java.util.Set<NodeIDType> getReplicaGroup(java.lang.String serviceName)
ReplicaCoordinatorgetReplicaGroup in interface ReplicaCoordinator<NodeIDType>serviceName.public java.util.Set<IntegerPacketType> getCoordinatorRequestTypes()
AppRequestParser.getRequestTypes() - getAppRequestTypes(). This
method must be overridden for non-default behavior.protected void setMessenger(Messenger<NodeIDType,?> messenger)
protected Messenger<NodeIDType,?> getMessenger()
protected void registerCoordination(IntegerPacketType... types)
protected final AbstractReplicaCoordinator<NodeIDType> setCallback(ReconfiguratorCallback callback)
callback - thisprotected final ReconfiguratorCallback getCallback()
protected final AbstractReplicaCoordinator<NodeIDType> setStopCallback(ReconfiguratorCallback callback)
callback - thisprotected boolean handleIncoming(Request request, ExecutedCallback callback)
request - public boolean execute(Request request)
execute in interface Applicationpublic boolean execute(Request request, boolean noReplyToClient)
Replicableexecute in interface ReplicablenoReplyToClient - If true, the application is expected to not send a response
back to the originating client (say, because this request is
part of a post-crash roll-forward or only the "entry replica"
that received the request from the client is expected to
respond back. If false, the application is expected to either
send a response (if any) back to the client via the
ClientMessenger interface or delegate response
messaging to paxos via the ClientRequest.getResponse()
interface.request.getServiceName()) altogether after a limited
number of retries, so the replica group may get stuck unless it
returns true after a limited number of retries. Thus, with paxos
as the replica coordination protocol, returning false is not
really an option as paxos has no way to "roll back" a request
whose global order has already been agreed upon.
With replica coordination protocols other than paxos, the boolean
return value could be used in protocol-specific ways, e.g., a
primary-backup protocol might normally execute a request at just
one replica but relay the request to one or more backups if the
return value of Application.execute(Request) is false.
public boolean execute(Request request, boolean noReplyToClient, ExecutedCallback requestCallback)
request - noReplyToClient - requestCallback - public final Request getRequest(java.lang.String stringified) throws RequestParseException
AppRequestParserRequest conversion and
back. Furthermore, the conversion to a string and back must preserve the
return values of all Request methods, i.e.,
Application.getRequest
(request.toString())).equals(request) must be true.getRequest in interface AppRequestParserRequest corresponding to stringified.RequestParseExceptionpublic final Request getRequest(byte[] bytes, NIOHeader header) throws RequestParseException
AppRequestParserRequest.toBytes(), , i.e., invoking getRequest(request.toBytes(),
header).equals(request).getRequest in interface AppRequestParsergetRequest in interface AppRequestParserBytesmessage.RequestParseExceptionprotected final Request getRequest(ReplicableClientRequest rcr, NIOHeader header) throws RequestParseException
RequestParseExceptionpublic java.util.Set<IntegerPacketType> getAppRequestTypes()
public ReconfigurableRequest getStopRequest(java.lang.String name, int epoch)
ReconfigurablegetStopRequest in interface Reconfigurablename:epoch.public java.lang.String getFinalState(java.lang.String name,
int epoch)
ReconfigurablegetFinalState in interface Reconfigurablepublic void putInitialState(java.lang.String name,
int epoch,
java.lang.String state)
ReconfigurableputInitialState in interface Reconfigurablepublic boolean deleteFinalState(java.lang.String name,
int epoch)
ReconfigurabledeleteFinalState in interface Reconfigurablename:epoch was deleted or did not
exist to begin with.public java.lang.Integer getEpoch(java.lang.String name)
ReconfigurablegetEpoch in interface Reconfigurablename.public java.lang.String checkpoint(java.lang.String name)
Replicablecheckpoint in interface Replicable
Note that state may simply be an app-specific handle,
e.g., a file name, representing the state as opposed to the
actual state. The application is responsible for interpreting the
state returned by Replicable.checkpoint(String) and that supplied
in Replicable.restore(String, String) in a consistent manner.
public boolean restore(java.lang.String name,
java.lang.String state)
Replicablename to state.
Note that state may simply be an app-specific handle, e.g., a
file name, representing the state as opposed to the actual state. The
application is responsible for interpreting the state returned by
Replicable.checkpoint(String) and that supplied in
Replicable.restore(String, String) in a consistent manner.
restore in interface Replicableprotected final void callCallback(Request request, boolean handled, ExecutedCallback requestCallback)
public NodeIDType getMyID()
public boolean hasLargeCheckpoints()
public void setLargeCheckpoints()
public boolean createReplicaGroup(java.util.Map<java.lang.String,java.lang.String> nameStates,
java.util.Set<NodeIDType> nodes)
nameStates - nodes - public void stop()
protected void sendAllLazy(Request request) throws java.io.IOException, RequestParseException, org.json.JSONException
java.io.IOExceptionRequestParseExceptionorg.json.JSONExceptionprotected java.util.Set<IntegerPacketType> getMutualAuthAppRequestTypes()
AppRequestParser.getMutualAuthRequestTypes()protected java.lang.String getARARNodesAsString()
protected java.lang.String getARRCNodesAsString()