Documentation ¶
Overview ¶
Package dragonboat is a multi-group Raft implementation.
The NodeHost struct is the facade interface for all features provided by the dragonboat package. Each NodeHost instance, identified by its RaftAddress property, usually runs on a separate host managing its CPU, storage and network resources. Each NodeHost can manage Raft nodes from many different Raft groups known as Raft clusters. Each Raft cluster is identified by its ClusterID Each Raft cluster usually consists of multiple nodes, identified by their NodeID values. Nodes from the same Raft cluster are suppose to be distributed on different NodeHost instances across the network, this brings fault tolerance to node failures as application data stored in such a Raft cluster can be available as long as the majority of its managing NodeHost instances (i.e. its underlying hosts) are available.
User applications can leverage the power of the Raft protocol implemented in dragonboat by implementing its IStateMachine or IOnDiskStateMachine component. IStateMachine and IOnDiskStateMachine is defined in github.com/mkawserm/dragonboat/v3/statemachine. Each cluster node is associated with an IStateMachine or IOnDiskStateMachine instance, it is in charge of updating, querying and snapshotting application data, with minimum exposure to the complexity of the Raft protocol implementation.
User applications can use NodeHost's APIs to update the state of their IStateMachine or IOnDiskStateMachine instances, this is called making proposals. Once accepted by the majority nodes of a Raft cluster, the proposal is considered as committed and it will be applied on all member nodes of the Raft cluster. Applications can also make linearizable reads to query the state of their IStateMachine or IOnDiskStateMachine instances. Dragonboat employs the ReadIndex protocol invented by Diego Ongaro to implement linearizable reads. Both read and write operations can be initiated on any member nodes, although initiating from the leader nodes incurs the lowest overhead.
Dragonboat guarantees the linearizability of your I/O when interacting with the IStateMachine or IOnDiskStateMachine instances. In plain English, writes (via making proposal) to your Raft cluster appears to be instantaneous, once a write is completed, all later reads (linearizable read using the ReadIndex protocol as implemented and provided in dragonboat) should return the value of that write or a later write. Once a value is returned by a linearizable read, all later reads should return the same value or the result of a later write.
To strictly provide such guarantee, we need to implement the at-most-once semantic required by linearizability. For a client, when it retries the proposal that failed to complete before its deadline during the previous attempt, it has the risk to have the same proposal committed and applied twice into the user state machine. Dragonboat prevents this by implementing the client session concept described in Diego Ongaro's PhD thesis.
NodeHost APIs for making the above mentioned application requests can be loosely classified into two categories, synchronous and asynchronous APIs. Synchronous APIs which will not return until the completion of the requested operation. Their method names all start with Sync*. The asynchronous counterpart of those asynchronous APIs, on the other hand, usually return immediately without waiting on any significant delays caused by networking or disk IO. This allows users to concurrently initiate multiple such asynchronous operations to save the total amount of time required to complete them. Users are free to choose whether they prefer to use the synchronous APIs for its simplicity or their asynchronous variants for better performance and flexibility.
Dragonboat is a feature complete Multi-Group Raft implementation - snapshotting, membership change, leadership transfer, non-voting members and disk based state machine are all provided.
Dragonboat is also extensively optimized. The Raft protocol implementation is fully pipelined, meaning proposals can start before the completion of previous proposals. This is critical for system throughput in high latency environment. Dragonboat is also fully batched, it batches internal operations whenever possible to maximize system throughput.
Index ¶
- Constants
- Variables
- func GetTestFS() config.IFS
- func IsTempError(err error) bool
- func WriteHealthMetrics(w io.Writer)
- type ClusterInfo
- type INodeUser
- type MemFS
- type Membership
- type NodeHost
- func (nh *NodeHost) CloseSession(ctx context.Context, session *client.Session) errordeprecated
- func (nh *NodeHost) GetClusterMembership(ctx context.Context, clusterID uint64) (*Membership, error)deprecated
- func (nh *NodeHost) GetLeaderID(clusterID uint64) (uint64, bool, error)
- func (nh *NodeHost) GetNewSession(ctx context.Context, clusterID uint64) (*client.Session, error)deprecated
- func (nh *NodeHost) GetNoOPSession(clusterID uint64) *client.Session
- func (nh *NodeHost) GetNodeHostInfo(opt NodeHostInfoOption) *NodeHostInfo
- func (nh *NodeHost) GetNodeUser(clusterID uint64) (INodeUser, error)
- func (nh *NodeHost) HasNodeInfo(clusterID uint64, nodeID uint64) bool
- func (nh *NodeHost) NAReadLocalNode(rs *RequestState, query []byte) ([]byte, error)
- func (nh *NodeHost) NodeHostConfig() config.NodeHostConfig
- func (nh *NodeHost) Propose(session *client.Session, cmd []byte, timeout time.Duration) (*RequestState, error)
- func (nh *NodeHost) ProposeSession(session *client.Session, timeout time.Duration) (*RequestState, error)
- func (nh *NodeHost) RaftAddress() string
- func (nh *NodeHost) ReadIndex(clusterID uint64, timeout time.Duration) (*RequestState, error)
- func (nh *NodeHost) ReadLocalNode(rs *RequestState, query interface{}) (interface{}, error)
- func (nh *NodeHost) RemoveData(clusterID uint64, nodeID uint64) error
- func (nh *NodeHost) RequestAddNode(clusterID uint64, nodeID uint64, address string, configChangeIndex uint64, ...) (*RequestState, error)
- func (nh *NodeHost) RequestAddObserver(clusterID uint64, nodeID uint64, address string, configChangeIndex uint64, ...) (*RequestState, error)
- func (nh *NodeHost) RequestAddWitness(clusterID uint64, nodeID uint64, address string, configChangeIndex uint64, ...) (*RequestState, error)
- func (nh *NodeHost) RequestCompaction(clusterID uint64, nodeID uint64) (*SysOpState, error)
- func (nh *NodeHost) RequestDeleteNode(clusterID uint64, nodeID uint64, configChangeIndex uint64, ...) (*RequestState, error)
- func (nh *NodeHost) RequestLeaderTransfer(clusterID uint64, targetNodeID uint64) error
- func (nh *NodeHost) RequestSnapshot(clusterID uint64, opt SnapshotOption, timeout time.Duration) (*RequestState, error)
- func (nh *NodeHost) StaleRead(clusterID uint64, query interface{}) (interface{}, error)
- func (nh *NodeHost) StartCluster(initialMembers map[uint64]string, join bool, ...) error
- func (nh *NodeHost) StartConcurrentCluster(initialMembers map[uint64]string, join bool, ...) error
- func (nh *NodeHost) StartOnDiskCluster(initialMembers map[uint64]string, join bool, ...) error
- func (nh *NodeHost) Stop()
- func (nh *NodeHost) StopCluster(clusterID uint64) error
- func (nh *NodeHost) StopNode(clusterID uint64, nodeID uint64) error
- func (nh *NodeHost) SyncCloseSession(ctx context.Context, cs *client.Session) error
- func (nh *NodeHost) SyncGetClusterMembership(ctx context.Context, clusterID uint64) (*Membership, error)
- func (nh *NodeHost) SyncGetSession(ctx context.Context, clusterID uint64) (*client.Session, error)
- func (nh *NodeHost) SyncPropose(ctx context.Context, session *client.Session, cmd []byte) (sm.Result, error)
- func (nh *NodeHost) SyncRead(ctx context.Context, clusterID uint64, query interface{}) (interface{}, error)
- func (nh *NodeHost) SyncRemoveData(ctx context.Context, clusterID uint64, nodeID uint64) error
- func (nh *NodeHost) SyncRequestAddNode(ctx context.Context, clusterID uint64, nodeID uint64, address string, ...) error
- func (nh *NodeHost) SyncRequestAddObserver(ctx context.Context, clusterID uint64, nodeID uint64, address string, ...) error
- func (nh *NodeHost) SyncRequestAddWitness(ctx context.Context, clusterID uint64, nodeID uint64, address string, ...) error
- func (nh *NodeHost) SyncRequestDeleteNode(ctx context.Context, clusterID uint64, nodeID uint64, configChangeIndex uint64) error
- func (nh *NodeHost) SyncRequestSnapshot(ctx context.Context, clusterID uint64, opt SnapshotOption) (uint64, error)
- type NodeHostInfo
- type NodeHostInfoOption
- type RequestResult
- func (rr *RequestResult) Aborted() bool
- func (rr *RequestResult) Committed() bool
- func (rr *RequestResult) Completed() bool
- func (rr *RequestResult) Dropped() bool
- func (rr *RequestResult) GetResult() sm.Result
- func (rr *RequestResult) Rejected() bool
- func (rr *RequestResult) SnapshotIndex() uint64
- func (rr *RequestResult) Terminated() bool
- func (rr *RequestResult) Timeout() bool
- type RequestResultCode
- type RequestState
- type SnapshotOption
- type SysOpState
Examples ¶
Constants ¶
const ( // DragonboatMajor is the major version number DragonboatMajor = 3 // DragonboatMinor is the minor version number DragonboatMinor = 3 // DragonboatPatch is the patch version number DragonboatPatch = 0 // DEVVersion is a boolean flag indicating whether this is a dev version DEVVersion = true )
Variables ¶
var ( // ErrNodeRemoved indictes that the requested node has been removed. ErrNodeRemoved = errors.New("node removed") // ErrClusterNotFound indicates that the specified cluster is not found. ErrClusterNotFound = errors.New("cluster not found") // ErrClusterAlreadyExist indicates that the specified cluster already exist. ErrClusterAlreadyExist = errors.New("cluster already exist") // ErrClusterNotStopped indicates that the specified cluster is still running // and thus prevented the requested operation to be completed. ErrClusterNotStopped = errors.New("cluster not stopped") // ErrInvalidClusterSettings indicates that cluster settings specified for // the StartCluster method are invalid. ErrInvalidClusterSettings = errors.New("cluster settings are invalid") // ErrClusterNotBootstrapped indicates that the specified cluster has not // been boostrapped yet. When starting this node, depending on whether this // node is an initial member of the Raft cluster, you must either specify // all of its initial members or set the join flag to true. // When used correctly, dragonboat only returns this error in the rare // situation when you try to restart a node crashed during its previous // bootstrap attempt. ErrClusterNotBootstrapped = errors.New("cluster not bootstrapped") // ErrDeadlineNotSet indicates that the context parameter provided does not // carry a deadline. ErrDeadlineNotSet = errors.New("deadline not set") // ErrInvalidDeadline indicates that the specified deadline is invalid, e.g. // time in the past. ErrInvalidDeadline = errors.New("invalid deadline") // ErrDirNotExist indicates that the specified dir does not exist. ErrDirNotExist = errors.New("specified dir does not exist") )
var ( // ErrInvalidOperation indicates that the requested operation is not allowed. // e.g. making read or write requests on witness node are not allowed. ErrInvalidOperation = errors.New("invalid operation") // ErrInvalidAddress indicates that the specified address is invalid. ErrInvalidAddress = errors.New("invalid address") // ErrInvalidSession indicates that the specified client session is invalid. ErrInvalidSession = errors.New("invalid session") // ErrTimeoutTooSmall indicates that the specified timeout value is too small. ErrTimeoutTooSmall = errors.New("specified timeout value is too small") // ErrPayloadTooBig indicates that the payload is too big. ErrPayloadTooBig = errors.New("payload is too big") // ErrSystemBusy indicates that the system is too busy to handle the request. // This might be caused when the Raft node reached its MaxInMemLogSize limit // or other system limits. ErrSystemBusy = errors.New("system is too busy try again later") // ErrClusterClosed indicates that the requested cluster is being shut down. ErrClusterClosed = errors.New("raft cluster already closed") // ErrClusterNotInitialized indicates that the requested operation can not be // completed as the involved raft cluster has not been initialized yet. ErrClusterNotInitialized = errors.New("raft cluster not initialized yet") // ErrBadKey indicates that the key is bad, retry the request is recommended. ErrBadKey = errors.New("bad key try again later") // ErrPendingConfigChangeExist indicates that there is already a pending // membership change exist in the system. ErrPendingConfigChangeExist = errors.New("pending config change request exist") // ErrPendingSnapshotRequestExist indicates that there is already a pending // snapshot request exist in the system. ErrPendingSnapshotRequestExist = errors.New("pending snapshot request exist") // ErrTimeout indicates that the operation timed out. ErrTimeout = errors.New("timeout") // ErrSystemStopped indicates that the system is being shut down. ErrSystemStopped = errors.New("system stopped") // ErrCanceled indicates that the request has been canceled. ErrCanceled = errors.New("request canceled") // ErrRejected indicates that the request has been rejected. ErrRejected = errors.New("request rejected") // ErrClusterNotReady indicates that the request has been dropped as the // specified raft cluster is not ready to handle the request. Unknown leader // is the most common cause of this error. ErrClusterNotReady = errors.New("request dropped as the cluster is not ready") // ErrInvalidTarget indicates that the specified node id invalid. ErrInvalidTarget = errors.New("invalid target node ID") // ErrPendingLeaderTransferExist indicates that leader transfer request exist. ErrPendingLeaderTransferExist = errors.New("pending leader transfer exist") )
var ( // ErrNoSnapshot is the error used to indicate that there is no snapshot // available. ErrNoSnapshot = errors.New("no snapshot available") )
Functions ¶
func GetTestFS ¶
GetTestFS returns a vfs instance that can be used in testing. User applications can usually ignore such vfs related types and fields.
func IsTempError ¶
IsTempError returns a boolean value indicating whether the specified error is a temporary error that worth to be retried later with the exact same input, potentially on a more suitable NodeHost instance.
func WriteHealthMetrics ¶
WriteHealthMetrics writes all health metrics in Prometheus format to the specified writer. This function is typically called by the metrics http handler.
Types ¶
type ClusterInfo ¶
type ClusterInfo struct { // ClusterID is the cluster ID of the Raft cluster node. ClusterID uint64 // NodeID is the node ID of the Raft cluster node. NodeID uint64 // Nodes is a map of member node IDs to their Raft addresses. Nodes map[uint64]string // ConfigChangeIndex is the current config change index of the Raft node. // ConfigChangeIndex is Raft Log index of the last applied membership // change entry. ConfigChangeIndex uint64 // StateMachineType is the type of the state machine. StateMachineType sm.Type // Pending is a boolean flag indicating whether details of the cluster node // is not available. The Pending flag is set to true usually because the node // has not had anything applied yet. // IsLeader indicates whether this is a leader node. IsLeader bool // IsObserver indicates whether this is a non-voting observer node. IsObserver bool // IsWitness indicates whether this is a witness node without actual log. IsWitness bool // Pending is a boolean flag indicating whether details of the cluster node // is not available. The Pending flag is set to true usually because the node // has not had anything applied yet. Pending bool }
ClusterInfo is a record for representing the state of a Raft cluster based on the knowledge of the local NodeHost instance.
type INodeUser ¶
type INodeUser interface { // Propose starts an asynchronous proposal on the Raft cluster represented by // the INodeUser instance. Its semantics is the same as the Propose() method // in NodeHost. Propose(s *client.Session, cmd []byte, timeout time.Duration) (*RequestState, error) // ReadIndex starts the asynchronous ReadIndex protocol used for linearizable // reads on the Raft cluster represented by the INodeUser instance. Its // semantics is the same as the ReadIndex() method in NodeHost. ReadIndex(timeout time.Duration) (*RequestState, error) }
INodeUser is the interface implemented by a Raft node user type. A Raft node user can be used to directly initiate proposals or read index operations without locating the Raft node in NodeHost's node list first. It is useful when doing bulk load operations on selected clusters.
type MemFS ¶
MemFS is a in memory vfs intended to be used in testing. User applications can usually ignore such vfs related types and fields.
type Membership ¶
type Membership struct { // ConfigChangeID is the Raft entry index of the last applied membership // change entry. ConfigChangeID uint64 // Nodes is a map of NodeID values to NodeHost Raft addresses for all regular // Raft nodes. Nodes map[uint64]string // Observers is a map of NodeID values to NodeHost Raft addresses for all // observers in the Raft cluster. Observers map[uint64]string // Witnesses is a map of NodeID values to NodeHost Raft addrsses for all // witnesses in the Raft cluster. Witnesses map[uint64]string // Removed is a set of NodeID values that have been removed from the Raft // cluster. They are not allowed to be added back to the cluster. Removed map[uint64]struct{} }
Membership is the struct used to describe Raft cluster membership query results.
type NodeHost ¶
type NodeHost struct {
// contains filtered or unexported fields
}
NodeHost manages Raft clusters and enables them to share resources such as transport and persistent storage etc. NodeHost is also the central access point for Dragonboat functionalities provided to applications.
func NewNodeHost ¶
func NewNodeHost(nhConfig config.NodeHostConfig) (*NodeHost, error)
NewNodeHost creates a new NodeHost instance. The returned NodeHost instance is configured using the specified NodeHostConfig instance. In a typical application, it is expected to have one NodeHost on each server.
Example ¶
// Let's say we want to put all LogDB's WAL data in a directory named wal, // everything else is stored in a directory named dragonboat. Assume the // RTT between nodes is 200 milliseconds, and the nodehost address is // myhostname:5012 nhc := config.NodeHostConfig{ WALDir: "wal", NodeHostDir: "dragonboat", RTTMillisecond: 200, RaftAddress: "myhostname:5012", } // Creates a nodehost instance using the above NodeHostConfig instnace. nh, err := NewNodeHost(nhc) if err != nil { panic(err) } log.Printf("NodeHost %s created\n", nh.RaftAddress())
Output:
func (*NodeHost) CloseSession
deprecated
CloseSession closes the specified client session by unregistering it from the system. The specified context parameter must has the timeout value set. This is a synchronous method meaning it will only return after its confirmed completion, failure or timeout.
Closed client session should no longer be used in future proposals.
Deprecated: Use NodeHost.SyncCloseSession instead. NodeHost.CloseSession will be removed in v4.0.
func (*NodeHost) GetClusterMembership
deprecated
func (nh *NodeHost) GetClusterMembership(ctx context.Context, clusterID uint64) (*Membership, error)
GetClusterMembership returns the membership information from the specified Raft cluster. The specified context parameter must has the timeout value set.
GetClusterMembership guarantees that the returned membership information is linearizable. This is a synchronous method meaning it will only return after its confirmed completion, failure or timeout.
Deprecated: Use NodeHost.SyncGetClusterMembership instead. NodeHost.GetClusterMembership will be removed in v4.0.
func (*NodeHost) GetLeaderID ¶
GetLeaderID returns the leader node ID of the specified Raft cluster based on local node's knowledge. The returned boolean value indicates whether the leader information is available.
func (*NodeHost) GetNewSession
deprecated
GetNewSession starts a synchronous proposal to create, register and return a new client session object for the specified Raft cluster. The specified context parameter must has the timeout value set.
A client session object is used to ensure that a retried proposal, e.g. proposal retried after timeout, will not be applied more than once into the IStateMachine.
Returned client session instance should not be used concurrently. Use multiple client sessions when making concurrent proposals.
Deprecated: Use NodeHost.SyncGetSession instead. NodeHost.GetNewSession will be removed in v4.0.
func (*NodeHost) GetNoOPSession ¶
GetNoOPSession returns a NO-OP client session ready to be used for making proposals. The NO-OP client session is a dummy client session that will not be checked or enforced. Use this No-OP client session when you want to ignore features provided by client sessions. A NO-OP client session is not registered on the server side and thus not required to be closed at the end of its life cycle.
Returned NO-OP client session instance can be concurrently used in multiple goroutines.
Use this NO-OP client session when your IStateMachine provides idempotence in its own implementation.
NO-OP client session must be used for making proposals on IOnDiskStateMachine based state machine.
func (*NodeHost) GetNodeHostInfo ¶
func (nh *NodeHost) GetNodeHostInfo(opt NodeHostInfoOption) *NodeHostInfo
GetNodeHostInfo returns a NodeHostInfo instance that contains all details of the NodeHost, this includes details of all Raft clusters managed by the the NodeHost instance.
func (*NodeHost) GetNodeUser ¶
GetNodeUser returns an INodeUser instance ready to be used to directly make proposals or read index operations without locating the node repeatedly in the NodeHost. A possible use case is when loading a large data set say with billions of proposals into the dragonboat based system.
func (*NodeHost) HasNodeInfo ¶
HasNodeInfo returns a boolean value indicating whether the specified node has been bootstrapped on the current NodeHost instance.
func (*NodeHost) NAReadLocalNode ¶
func (nh *NodeHost) NAReadLocalNode(rs *RequestState, query []byte) ([]byte, error)
NAReadLocalNode is a variant of ReadLocalNode, it uses byte slice as its input and output data for read only queries to minimize extra heap allocations caused by using interface{}. Users are recommended to use ReadLocalNode unless performance is the top priority.
As an optional method, the underlying state machine must implement the statemachine.IExtended interface. NAReadLocalNode returns statemachine.ErrNotImplemented if the underlying state machine does not implement the statemachine.IExtended interface.
func (*NodeHost) NodeHostConfig ¶
func (nh *NodeHost) NodeHostConfig() config.NodeHostConfig
NodeHostConfig returns the NodeHostConfig instance used for configuring this NodeHost instance.
func (*NodeHost) Propose ¶
func (nh *NodeHost) Propose(session *client.Session, cmd []byte, timeout time.Duration) (*RequestState, error)
Propose starts an asynchronous proposal on the Raft cluster specified by the Session object. The input byte slice can be reused for other purposes immediate after the return of this method.
This method returns a RequestState instance or an error immediately. Application can wait on the ResultC() channel of the returned RequestState instance to get notified for the outcome of the proposal and access to the result of the proposal.
After the proposal is completed, i.e. RequestResult is received from the ResultC() channel of the returned RequestState, unless NO-OP client session is used, it is caller's responsibility to update the Session instance accordingly based on the RequestResult.Code value. Basically, when RequestTimeout is returned, you can retry the same proposal without updating your client session instance, when a RequestRejected value is returned, it usually means the session instance has been evicted from the server side, the Raft paper recommends you to crash your client in this highly unlikely event. When the proposal completed successfully with a RequestCompleted value, application must call client.ProposalCompleted() to get the client session ready to be used in future proposals.
Example ¶
// nh is a NodeHost instance, a Raft cluster with ID 100 has already been added // this to NodeHost. // see the example on StartCluster on how to start Raft cluster. // // Use NO-OP client session, cluster ID is 100 // Check the example on the GetNewSession method to see how to use a // real client session object to make proposals. cs := enh.GetNoOPSession(100) // make a proposal with the proposal content "test-data", timeout is set to // 2000 milliseconds. rs, err := enh.Propose(cs, []byte("test-data"), 2000*time.Millisecond) if err != nil { // failed to start the proposal return } s := <-rs.ResultC() if s.Timeout() { // the proposal failed to complete before the deadline, maybe retry the // request } else if s.Completed() { // Release can only be called when the ResultC() chan has been signalled. rs.Release() // the proposal has been committed and applied // put the request state instance back to the recycle pool } else if s.Terminated() { // proposal terminated as the system is being shut down, time to exit } // note that s.Code == RequestRejected is not suppose to happen as we are // using a NO-OP client session in this example.
Output:
func (*NodeHost) ProposeSession ¶
func (nh *NodeHost) ProposeSession(session *client.Session, timeout time.Duration) (*RequestState, error)
ProposeSession starts an asynchronous proposal on the specified cluster for client session related operations. Depending on the state of the specified client session object, the supported operations are for registering or unregistering a client session. Application can select on the ResultC() channel of the returned RequestState instance to get notified for the completion (RequestResult.Completed() is true) of the operation.
func (*NodeHost) RaftAddress ¶
RaftAddress returns the Raft address of the NodeHost instance. The returned RaftAddress value is used to identify this NodeHost instance. It is also the address used for exchanging Raft messages and snapshots between distributed NodeHost instances.
func (*NodeHost) ReadIndex ¶
ReadIndex starts the asynchronous ReadIndex protocol used for linearizable read on the specified cluster. This method returns a RequestState instance or an error immediately. Application should wait on the ResultC() channel of the returned RequestState object to get notified on the outcome of the ReadIndex operation. On a successful completion, the ReadLocal method can then be invoked to query the state of the IStateMachine or IOnDiskStateMachine to complete the read operation with linearizability guarantee.
Example ¶
// nh is a NodeHost instance, a Raft cluster with ID 100 has already been added // this to NodeHost. // see the example on StartCluster on how to start Raft cluster. data := make([]byte, 1024) rs, err := enh.ReadIndex(100, 2000*time.Millisecond) if err != nil { // ReadIndex failed to start return } s := <-rs.ResultC() if s.Timeout() { // the ReadIndex operation failed to complete before the deadline, maybe // retry the request } else if s.Completed() { rs.Release() // the ReadIndex operation completed. the local IStateMachine is ready to be // queried result, err := enh.ReadLocalNode(rs, data) if err != nil { return } // use query result here _ = result } else if s.Terminated() { // the ReadIndex operation terminated as the system is being shut down, // time to exit }
Output:
func (*NodeHost) ReadLocalNode ¶
func (nh *NodeHost) ReadLocalNode(rs *RequestState, query interface{}) (interface{}, error)
ReadLocalNode queries the Raft node identified by the input RequestState instance. To ensure the IO linearizability, ReadLocalNode should only be called after receiving a RequestCompleted notification from the ReadIndex method. See ReadIndex's example for more details.
func (*NodeHost) RemoveData ¶
RemoveData tries to remove all data associated with the specified node. This method should only be used after the node has been deleted from its Raft cluster. Calling RemoveData on a node that is still a Raft cluster member will corrupt the Raft cluster.
RemoveData returns ErrClusterNotStopped when the specified node has not been fully offloaded from the NodeHost instance.
func (*NodeHost) RequestAddNode ¶
func (nh *NodeHost) RequestAddNode(clusterID uint64, nodeID uint64, address string, configChangeIndex uint64, timeout time.Duration) (*RequestState, error)
RequestAddNode is a Raft cluster membership change method for requesting the specified node to be added to the specified Raft cluster. It starts an asynchronous request to add the node to the Raft cluster membership list. Application can wait on the ResultC() channel of the returned RequestState instance to get notified for the outcome.
If there is already an observer with the same nodeID in the cluster, it will be promoted to a regular node with voting power. The address parameter of the RequestAddNode call is ignored when promoting an observer to a regular node.
After the node is successfully added to the Raft cluster, it is application's responsibility to call StartCluster on the right NodeHost instance to actually start the Raft cluster node.
Requesting a removed node back to the Raft cluster will always be rejected.
The input address parameter is the RaftAddress of the NodeHost where the new Raft node being added will be running. When the raft cluster is created with the OrderedConfigChange config flag set as false, the configChangeIndex parameter is ignored. Otherwise, it should be set to the most recent Config Change Index value returned by the SyncGetClusterMembership method. The requested add node operation will be rejected if other membership change has been applied since that earlier call to the SyncGetClusterMembership method.
Example ¶
// nh is a NodeHost instance, a Raft cluster with ID 100 has already been added // this to NodeHost. // see the example on StartCluster on how to start Raft cluster. // // request node with ID 4 running at myhostname4:5012 to be added as a member // node of raft cluster 100. the fourth parameter is OrderID. rs, err := enh.RequestAddNode(100, 4, "myhostname4:5012", 0, 2000*time.Millisecond) if err != nil { // failed to start the membership change request return } s := <-rs.ResultC() if s.Timeout() { // the request failed to complete before the deadline, maybe retry the // request } else if s.Completed() { rs.Release() // the requested new node has been added to the raft cluster, ready to // add the node to the NodeHost running at myhostname4:5012. run the // following code on the NodeHost running at myhostname4:5012 - // // NewStateMachine := func(clusterID uint64, nodeID uint64) sm.IStateMachine { // return &tests.NoOP{} // } // rc := config.Config{ // NodeID: 4, // ClusterID: 100, // ElectionRTT: 5, // HeartbeatRTT: 1, // CheckQuorum: true, // SnapshotEntries: 10000, // CompactionOverhead: 5000, // } // nh.StartCluster(nil, true, NewStateMachine, rc) } else if s.Terminated() { // request terminated as the system is being shut down, time to exit } else if s.Rejected() { // request rejected as it is out of order. try again with the latest order // id value returned by NodeHost's SyncGetClusterMembership() method. }
Output:
func (*NodeHost) RequestAddObserver ¶
func (nh *NodeHost) RequestAddObserver(clusterID uint64, nodeID uint64, address string, configChangeIndex uint64, timeout time.Duration) (*RequestState, error)
RequestAddObserver is a Raft cluster membership change method for requesting the specified node to be added to the specified Raft cluster as an observer without voting power. It starts an asynchronous request to add the specified node as an observer.
Such observer is able to receive replicated states from the leader node, but it is neither allowed to vote for leader, nor considered as a part of the quorum when replicating state. An observer can be promoted to a regular node with voting power by making a RequestAddNode call using its clusterID and nodeID values. An observer can be removed from the cluster by calling RequestDeleteNode with its clusterID and nodeID values.
Application should later call StartCluster with config.Config.IsObserver set to true on the right NodeHost to actually start the observer instance.
The input address parameter is the RaftAddress of the NodeHost where the new observer being added will be running. When the raft cluster is created with the OrderedConfigChange config flag set as false, the configChangeIndex parameter is ignored. Otherwise, it should be set to the most recent Config Change Index value returned by the SyncGetClusterMembership method. The requested add observer operation will be rejected if other membership change has been applied since that earlier call to the SyncGetClusterMembership method.
func (*NodeHost) RequestAddWitness ¶
func (nh *NodeHost) RequestAddWitness(clusterID uint64, nodeID uint64, address string, configChangeIndex uint64, timeout time.Duration) (*RequestState, error)
RequestAddWitness is a Raft cluster membership change method for requesting the specified node to be added as a witness to the given Raft cluster. It starts an asynchronous request to add the specified node as an witness.
A witness can vote in elections but it doesn't have any Raft log or application state machine associated. The witness node can not be used to initiate read, write or membership change operations on its Raft cluster. Section 11.7.2 of Diego Ongaro's thesis contains more info on such witness role.
Application should later call StartCluster with config.Config.IsWitness set to true on the right NodeHost to actually start the witness node.
The input address parameter is the RaftAddress of the NodeHost where the new witness being added will be running. When the raft cluster is created with the OrderedConfigChange config flag set as false, the configChangeIndex parameter is ignored. Otherwise, it should be set to the most recent Config Change Index value returned by the SyncGetClusterMembership method. The requested add witness operation will be rejected if other membership change has been applied since that earlier call to the SyncGetClusterMembership method.
func (*NodeHost) RequestCompaction ¶
func (nh *NodeHost) RequestCompaction(clusterID uint64, nodeID uint64) (*SysOpState, error)
RequestCompaction requests a compaction operation to be asynchronously executed in the background to reclaim disk spaces used by Raft Log entries that have already been marked as removed. This includes Raft Log entries that have already been included in created snapshots and Raft Log entries that belong to nodes already permanently removed via NodeHost.RemoveData().
By default, compaction is automatically issued after each snapshot is captured. RequestCompaction can be used to manually trigger such compaction when auto compaction is disabled by the DisableAutoCompactions option in config.Config.
The returned *SysOpState instance can be used to get notified when the requested compaction is completed. ErrRejected is returned when there is nothing to be reclaimed.
func (*NodeHost) RequestDeleteNode ¶
func (nh *NodeHost) RequestDeleteNode(clusterID uint64, nodeID uint64, configChangeIndex uint64, timeout time.Duration) (*RequestState, error)
RequestDeleteNode is a Raft cluster membership change method for requesting the specified node to be removed from the specified Raft cluster. It starts an asynchronous request to remove the node from the Raft cluster membership list. Application can wait on the ResultC() channel of the returned RequestState instance to get notified for the outcome.
It is not guaranteed that deleted node will automatically close itself and be removed from its managing NodeHost instance. It is application's responsibility to call RemoveCluster on the right NodeHost instance to actually have the cluster node removed from its managing NodeHost instance.
Once a node is successfully deleted from a Raft cluster, it will not be allowed to be added back to the cluster with the same node identity.
When the raft cluster is created with the OrderedConfigChange config flag set as false, the configChangeIndex parameter is ignored. Otherwise, it should be set to the most recent Config Change Index value returned by the SyncGetClusterMembership method. The requested delete node operation will be rejected if other membership change has been applied since that earlier call to the SyncGetClusterMembership method.
Example ¶
// nh is a NodeHost instance, a Raft cluster with ID 100 has already been added // this to NodeHost. // see the example on StartCluster on how to start Raft cluster. // // request node with ID 1 to be removed as a member node of raft cluster 100. // the third parameter is OrderID. rs, err := enh.RequestDeleteNode(100, 1, 0, 2000*time.Millisecond) if err != nil { // failed to start the membership change request return } s := <-rs.ResultC() if s.Timeout() { // the request failed to complete before the deadline, maybe retry the // request } else if s.Completed() { rs.Release() // the requested node has been removed from the raft cluster, ready to // remove the node from the NodeHost running at myhostname1:5012, e.g. // nh.RemoveCluster(100) } else if s.Terminated() { // request terminated as the system is being shut down, time to exit } else if s.Rejected() { // request rejected as it is out of order. try again with the latest order // id value returned by NodeHost's SyncGetClusterMembership() method. }
Output:
func (*NodeHost) RequestLeaderTransfer ¶
RequestLeaderTransfer makes a request to transfer the leadership of the specified Raft cluster to the target node identified by targetNodeID. It returns an error if the request fails to be started. There is no guarantee that such request can be fulfilled, i.e. the leadership transfer can still fail after a successful return of the RequestLeaderTransfer method.
func (*NodeHost) RequestSnapshot ¶
func (nh *NodeHost) RequestSnapshot(clusterID uint64, opt SnapshotOption, timeout time.Duration) (*RequestState, error)
RequestSnapshot requests a snapshot to be created asynchronously for the specified cluster node. For each node, only one ongoing snapshot operation is allowed.
Users can use an option parameter to specify details of the requested snapshot. For example, when the input SnapshotOption's Exported field is True, a snapshot will be exported to the directory pointed by the ExportPath field of the SnapshotOption instance. Such an exported snapshot is not managed by the system and it is mainly used to repair the cluster when it permanently loses its majority quorum. See the ImportSnapshot method in the tools package for more details.
When the Exported field of the input SnapshotOption instance is set to false, snapshots created as the result of RequestSnapshot are managed by Dragonboat. Users are not suppose to move, copy, modify or delete the generated snapshot. Such requested snapshot will also trigger Raft log and snapshot compactions. Similar to automatic snapshots, when a snapshot is requested on a node backed by an IOnDiskStateMachine, only the metadata portion of the state machine will be captured and saved. Requesting snapshots on IOnDiskStateMachine based nodes are typically used to trigger Raft log and snapshot compactions.
RequestSnapshot returns a RequestState instance or an error immediately. Applications can wait on the ResultC() channel of the returned RequestState instance to get notified for the outcome of the create snasphot operation. The RequestResult instance returned by the ResultC() channel tells the outcome of the snapshot operation, when successful, the SnapshotIndex method of the returned RequestResult instance reports the index of the created snapshot.
Requested snapshot operation will be rejected if there is already an existing snapshot in the system at the same Raft log index.
func (*NodeHost) StaleRead ¶
StaleRead queries the specified Raft node directly without any linearizability guarantee.
Users are recommended to use the SyncRead method or a combination of the ReadIndex and ReadLocalNode method to achieve linearizable read.
func (*NodeHost) StartCluster ¶
func (nh *NodeHost) StartCluster(initialMembers map[uint64]string, join bool, createStateMachine func(uint64, uint64) sm.IStateMachine, config config.Config) error
StartCluster adds the specified Raft cluster node to the NodeHost and starts the node to make it ready for accepting incoming requests. The node to be started is backed by a regular state machine that implements the sm.IStateMachine interface.
The input parameter initialMembers is a map of node ID to RaftAddress for all Raft cluster's initial member nodes. For the same Raft cluster, the same initialMembers map should be specified when starting its initial member nodes on distributed NodeHost instances.
The join flag indicates whether the node is a new node joining an existing cluster. createStateMachine is a factory function for creating the IStateMachine instance, config is the configuration instance that will be passed to the underlying Raft node object, the cluster ID and node ID of the involved node is given in the ClusterID and NodeID fields of the specified config parameter.
Note that this method is not for changing the membership of the specified Raft cluster, it launches a node that is already a member of the Raft cluster.
As a summary, when -
- starting a brand new Raft cluster, set join to false and specify all initial member node details in the initialMembers map.
- joining a new node to an existing Raft cluster, set join to true and leave the initialMembers map empty. This requires the joining node to have already been added as a member node of the Raft cluster.
- restarting an crashed or stopped node, set join to false and leave the initialMembers map to be empty. This applies to both initial member nodes and those joined later.
Example ¶
nhc := config.NodeHostConfig{ WALDir: "wal", NodeHostDir: "dragonboat", RTTMillisecond: 200, RaftAddress: "myhostname:5012", } // Creates a nodehost instance using the above NodeHostConfig instnace. nh, err := NewNodeHost(nhc) if err != nil { panic(err) } // config for raft rc := config.Config{ NodeID: 1, ClusterID: 100, ElectionRTT: 5, HeartbeatRTT: 1, CheckQuorum: true, SnapshotEntries: 10000, CompactionOverhead: 5000, } peers := make(map[uint64]string) peers[100] = "myhostname1:5012" peers[200] = "myhostname2:5012" peers[300] = "myhostname3:5012" // Use this NO-OP data store in this example NewStateMachine := func(clusterID uint64, nodeID uint64) sm.IStateMachine { return &tests.NoOP{} } if err := nh.StartCluster(peers, false, NewStateMachine, rc); err != nil { log.Fatalf("failed to add cluster, %v\n", err) }
Output:
func (*NodeHost) StartConcurrentCluster ¶
func (nh *NodeHost) StartConcurrentCluster(initialMembers map[uint64]string, join bool, createStateMachine func(uint64, uint64) sm.IConcurrentStateMachine, config config.Config) error
StartConcurrentCluster is similar to the StartCluster method but it is used to start a Raft node backed by a concurrent state machine.
func (*NodeHost) StartOnDiskCluster ¶
func (nh *NodeHost) StartOnDiskCluster(initialMembers map[uint64]string, join bool, createStateMachine func(uint64, uint64) sm.IOnDiskStateMachine, config config.Config) error
StartOnDiskCluster is similar to the StartCluster method but it is used to start a Raft node backed by an IOnDiskStateMachine.
func (*NodeHost) Stop ¶
func (nh *NodeHost) Stop()
Stop stops all Raft nodes managed by the NodeHost instance, closes the transport and persistent storage modules.
func (*NodeHost) StopCluster ¶
StopCluster removes and stops the Raft node associated with the specified Raft cluster from the NodeHost. The node to be removed and stopped is identified by the clusterID value.
Note that this is not the membership change operation to remove the node from the Raft cluster.
func (*NodeHost) StopNode ¶
StopNode removes the specified Raft cluster node from the NodeHost and stops that running Raft node.
Note that this is not the membership change operation to remove the node from the Raft cluster.
func (*NodeHost) SyncCloseSession ¶
SyncCloseSession closes the specified client session by unregistering it from the system. The specified context parameter must has the timeout value set. This is a synchronous method meaning it will only return after its confirmed completion, failure or timeout.
Closed client session should no longer be used in future proposals.
func (*NodeHost) SyncGetClusterMembership ¶
func (nh *NodeHost) SyncGetClusterMembership(ctx context.Context, clusterID uint64) (*Membership, error)
SyncGetClusterMembership is a rsynchronous method that queries the membership information from the specified Raft cluster. The specified context parameter must has the timeout value set.
SyncGetClusterMembership guarantees that the returned membership information is linearizable.
func (*NodeHost) SyncGetSession ¶
SyncGetSession starts a synchronous proposal to create, register and return a new client session object for the specified Raft cluster. The specified context parameter must has the timeout value set.
A client session object is used to ensure that a retried proposal, e.g. proposal retried after timeout, will not be applied more than once into the state machine.
Returned client session instance should not be used concurrently. Use multiple client sessions when you need to concurrently start multiple proposals.
Client session is not supported by IOnDiskStateMachine based state machine. NO-OP client session must be used for making proposals on IOnDiskStateMachine based state machine.
Example ¶
// nh is a NodeHost instance, a Raft cluster with ID 100 has already been added // this to NodeHost. // see the example on StartCluster on how to start Raft cluster. // // Create a client session first, cluster ID is 100 // Check the example on the SyncGetSession method to see how to use a // real client session object to make proposals. cs, err := enh.SyncGetSession(ectx, 100) if err != nil { // failed to get the client session, if it is a timeout error then try // again later. return } defer func() { if err := enh.SyncCloseSession(ectx, cs); err != nil { log.Printf("close session failed %v\n", err) } }() // make a proposal with the proposal content "test-data", timeout is set to // 2000 milliseconds. rs, err := enh.Propose(cs, []byte("test-data"), 2000*time.Millisecond) if err != nil { // failed to start the proposal return } s := <-rs.ResultC() if s.Timeout() { // the proposal failed to complete before the deadline. maybe retry // the request with the same client session instance s. // on timeout, there is actually no guarantee on whether the proposed // entry has been applied or not, the idea is that when retrying with // the same proposal using the same client session instance, dragonboat // makes sure that the proposal is retried and it will be applied if // and only if it has not been previously applied. } else if s.Completed() { rs.Release() // the proposal has been committed and applied, call // s.ProposalCompleted() to notify the client session that the previous // request has been successfully completed. this makes the client // session ready to be used when you make the next proposal. cs.ProposalCompleted() } else if s.Terminated() { // proposal terminated as the system is being shut down, time to exit } else if s.Rejected() { // client session s is not evicted from the server side, probably because // there are too many concurrent client sessions. in case you want to // strictly ensure that each proposal will never be applied twice, we // recommend to fail the client program. Note that this is highly unlikely // to happen. panic("client session already evicted") } // // now you can use the same client session instance s to make more proposals //
Output:
func (*NodeHost) SyncPropose ¶
func (nh *NodeHost) SyncPropose(ctx context.Context, session *client.Session, cmd []byte) (sm.Result, error)
SyncPropose makes a synchronous proposal on the Raft cluster specified by the input client session object. The specified context parameter must has the timeout value set.
SyncPropose returns the result returned by IStateMachine or IOnDiskStateMachine's Update method, or the error encountered. The input byte slice can be reused for other purposes immediate after the return of this method.
After calling SyncPropose, unless NO-OP client session is used, it is caller's responsibility to update the client session instance accordingly based on SyncPropose's outcome. Basically, when a ErrTimeout error is returned, application can retry the same proposal without updating the client session instance. When ErrInvalidSession error is returned, it usually means the session instance has been evicted from the server side, the Raft paper recommends to crash the client in this highly unlikely event. When the proposal completed successfully, caller must call client.ProposalCompleted() to get it ready to be used in future proposals.
func (*NodeHost) SyncRead ¶
func (nh *NodeHost) SyncRead(ctx context.Context, clusterID uint64, query interface{}) (interface{}, error)
SyncRead performs a synchronous linearizable read on the specified Raft cluster. The specified context parameter must has the timeout value set. The query byte slice specifies what to query, it will be passed to the Lookup method of the IStateMachine or IOnDiskStateMachine after the system determines that it is safe to perform the local read on IStateMachine or IOnDiskStateMachine. It returns the query result from the Lookup method or the error encountered.
func (*NodeHost) SyncRemoveData ¶
SyncRemoveData is the synchronous variant of the RemoveData. It waits for the specified node to be fully offloaded or until the ctx instance is cancelled or timeout.
Similar to RemoveData, calling SyncRemoveData on a node that is still a Raft cluster member will corrupt the Raft cluster.
func (*NodeHost) SyncRequestAddNode ¶
func (nh *NodeHost) SyncRequestAddNode(ctx context.Context, clusterID uint64, nodeID uint64, address string, configChangeIndex uint64) error
SyncRequestAddNode is the synchronous variant of the RequestAddNode method. See RequestAddNode for more details.
The input ctx must have its deadline set.
func (*NodeHost) SyncRequestAddObserver ¶
func (nh *NodeHost) SyncRequestAddObserver(ctx context.Context, clusterID uint64, nodeID uint64, address string, configChangeIndex uint64) error
SyncRequestAddObserver is the synchronous variant of the RequestAddObserver method. See RequestAddObserver for more details.
The input ctx must have its deadline set.
func (*NodeHost) SyncRequestAddWitness ¶
func (nh *NodeHost) SyncRequestAddWitness(ctx context.Context, clusterID uint64, nodeID uint64, address string, configChangeIndex uint64) error
SyncRequestAddWitness is the synchronous variant of the RequestAddWitness method. See RequestAddWitness for more details.
The input ctx must have its deadline set.
func (*NodeHost) SyncRequestDeleteNode ¶
func (nh *NodeHost) SyncRequestDeleteNode(ctx context.Context, clusterID uint64, nodeID uint64, configChangeIndex uint64) error
SyncRequestDeleteNode is the synchronous variant of the RequestDeleteNode method. See RequestDeleteNode for more details.
The input ctx must have its deadline set.
func (*NodeHost) SyncRequestSnapshot ¶
func (nh *NodeHost) SyncRequestSnapshot(ctx context.Context, clusterID uint64, opt SnapshotOption) (uint64, error)
SyncRequestSnapshot is the synchronous variant of the RequestSnapshot method. See RequestSnapshot for more details.
The input ctx must has deadline set.
SyncRequestSnapshot returns the index of the created snapshot or the error encountered.
type NodeHostInfo ¶
type NodeHostInfo struct { // RaftAddress is the public address and the identifier of the NodeHost. RaftAddress string // ClusterInfo is a list of all Raft clusters managed by the NodeHost ClusterInfoList []ClusterInfo // LogInfo is a list of raftio.NodeInfo values representing all Raft logs // stored on the NodeHost. LogInfo []raftio.NodeInfo }
NodeHostInfo provides info about the NodeHost, including its managed Raft cluster nodes and available Raft logs saved in its local persistent storage.
type NodeHostInfoOption ¶
type NodeHostInfoOption struct { // SkipLogInfo is the boolean flag indicating whether Raft Log info should be // skipped when querying the NodeHostInfo. SkipLogInfo bool }
NodeHostInfoOption is the option type used when querying NodeHostInfo.
var DefaultNodeHostInfoOption NodeHostInfoOption
DefaultNodeHostInfoOption is the default NodeHostInfoOption value. It requests the GetNodeHostInfo method to return all supported info.
type RequestResult ¶
type RequestResult struct {
// contains filtered or unexported fields
}
RequestResult is the result struct returned for the request.
func (*RequestResult) Aborted ¶
func (rr *RequestResult) Aborted() bool
Aborted returns a boolean value indicating the request is aborted.
func (*RequestResult) Committed ¶
func (rr *RequestResult) Committed() bool
Committed returns a boolean value indicating whether the request has been committed by Raft.
func (*RequestResult) Completed ¶
func (rr *RequestResult) Completed() bool
Completed returns a boolean value indicating whether the request completed successfully. For proposals, it means the proposal has been committed by the Raft cluster and applied on the local node. For ReadIndex operation, it means the cluster is now ready for a local read.
func (*RequestResult) Dropped ¶
func (rr *RequestResult) Dropped() bool
Dropped returns a boolean flag indicating whether the request has been dropped as the leader is unavailable or not ready yet. Such dropped requests can usually be retried once the leader is ready.
func (*RequestResult) GetResult ¶
func (rr *RequestResult) GetResult() sm.Result
GetResult returns the result value of the request. When making a proposal, the returned result is the value returned by the Update method of the IStateMachine instance.
func (*RequestResult) Rejected ¶
func (rr *RequestResult) Rejected() bool
Rejected returns a boolean value indicating the request is rejected. For a proposal, it means that the used client session instance is not registered or it has been evicted on the server side. When requesting a client session to be registered, Rejected means the another client session with the same client ID has already been registered. When requesting a client session to be unregistered, Rejected means the specified client session is not found on the server side. For a membership change request, it means the request is out of order and thus not applied.
func (*RequestResult) SnapshotIndex ¶
func (rr *RequestResult) SnapshotIndex() uint64
SnapshotIndex returns the index of the generated snapshot when the RequestResult is from a snapshot related request. Invoking this method on RequestResult instances not related to snapshots will cause panic.
func (*RequestResult) Terminated ¶
func (rr *RequestResult) Terminated() bool
Terminated returns a boolean value indicating the request terminated due to the requested Raft cluster is being shut down.
func (*RequestResult) Timeout ¶
func (rr *RequestResult) Timeout() bool
Timeout returns a boolean value indicating whether the request timed out.
type RequestResultCode ¶
type RequestResultCode int
RequestResultCode is the result code returned to the client to indicate the outcome of the request.
func (RequestResultCode) String ¶
func (c RequestResultCode) String() string
type RequestState ¶
type RequestState struct { // CompletedC is a channel for delivering request result to users. // // Deprecated: CompletedC has been deprecated. Use ResultC() or AppliedC() // instead. CompletedC chan RequestResult // contains filtered or unexported fields }
RequestState is the object used to provide request result to users.
func (*RequestState) AppliedC ¶
func (r *RequestState) AppliedC() chan RequestResult
AppliedC returns a channel of RequestResult for delivering request result. The returned channel reports the final outcomes of proposals and config changes, the return value can be of one of the Completed(), Dropped(), Timeout(), Rejected(), Terminated() or Aborted() values.
Use ResultC() when the client wants to be notified when proposals or config changes are committed.
func (*RequestState) Release ¶
func (r *RequestState) Release()
Release puts the RequestState instance back to an internal pool so it can be reused. Release is normally called after all RequestResult values have been received from the ResultC() channel.
func (*RequestState) ResultC ¶
func (r *RequestState) ResultC() chan RequestResult
ResultC returns a channel of RequestResult for delivering request results to users. When NotifyCommit is not enabled, the behaviour of the returned channel is the same as the one returned by the AppliedC() method. When NotifyCommit is enabled, up to two RequestResult values can be received from the returned channel. For example, for a successfully proposal that is eventually committed and applied, the returned chan RequestResult will return a RequestResult value to indicate the proposal is committed first, it will be followed by another RequestResult value indicating the proposal has been applied into the state machine.
Use AppliedC() when your client don't need extra notification when proposals and config changes are committed.
type SnapshotOption ¶
type SnapshotOption struct { // CompactionOverhead is the compaction overhead value to use for the request // snapshot operation when OverrideCompactionOverhead is true. This field is // ignored when exporting a snapshot, that is when Exported is true. CompactionOverhead uint64 // ExportPath is the path where the exported snapshot should be stored, it // must point to an existing directory for which the current user has write // permission to it. ExportPath string // Exported is a boolean flag indicating whether the snapshot requested to // be generated should be exported. For an exported snapshot, it is users' // responsibility to manage the snapshot files. By default, a requested // snapshot is not considered as exported, such a regular snapshot is managed // the system. Exported bool // OverrideCompactionOverhead defines whether the requested snapshot operation // should override the compaction overhead setting specified in node's config. // This field is ignored by the system when exporting a snapshot. OverrideCompactionOverhead bool }
SnapshotOption is the options users can specify when requesting a snapshot to be generated.
var DefaultSnapshotOption SnapshotOption
DefaultSnapshotOption is the default SnapshotOption value to use when requesting a snapshot to be generated by using NodeHost's RequestSnapshot method. DefaultSnapshotOption causes a regular snapshot to be generated and the generated snapshot is managed by the system.
type SysOpState ¶
type SysOpState struct {
// contains filtered or unexported fields
}
SysOpState is the object used to provide system maintenance operation result to users.
func (*SysOpState) CompletedC
deprecated
func (o *SysOpState) CompletedC() <-chan struct{}
CompletedC returns a struct{} chan that is closed when the requested operation is completed.
Deprecated: CompletedC() has been deprecated. Use ResultC() instead.
func (*SysOpState) ResultC ¶
func (o *SysOpState) ResultC() <-chan struct{}
ResultC returns a struct{} chan that is closed when the requested operation is completed.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package client implements the client Session struct for identifying proposal clients and their progress.
|
Package client implements the client Session struct for identifying proposal clients and their progress. |
Package config contains functions and types used for managing dragonboat's configurations.
|
Package config contains functions and types used for managing dragonboat's configurations. |
internal
|
|
logdb
Package logdb implements the persistent log storage used by Dragonboat.
|
Package logdb implements the persistent log storage used by Dragonboat. |
raft
Package raft is a distributed consensus package that implements the Raft protocol.
|
Package raft is a distributed consensus package that implements the Raft protocol. |
rsm
Package rsm implements Replicated State Machines used in Dragonboat.
|
Package rsm implements Replicated State Machines used in Dragonboat. |
settings
Package settings is used for managing internal parameters that can be set at compile time by expert level users.
|
Package settings is used for managing internal parameters that can be set at compile time by expert level users. |
tests
Package tests contains various helper functions and modules used in tests.
|
Package tests contains various helper functions and modules used in tests. |
tests/concurrentkv
concurrentkv is IConcurrentStateMachine plugin used in various tests.
|
concurrentkv is IConcurrentStateMachine plugin used in various tests. |
tests/kvtest
kvtest is IStateMachine plugin used in various tests.
|
kvtest is IStateMachine plugin used in various tests. |
transport
Package transport implements the transport component used for exchanging Raft messages between NodeHosts.
|
Package transport implements the transport component used for exchanging Raft messages between NodeHosts. |
Package logger manages loggers used in dragonboat.
|
Package logger manages loggers used in dragonboat. |
plugin
|
|
Package raftio contains structs, interfaces and function definitions required to build customized persistent Raft log storage and Raft RPC modules.
|
Package raftio contains structs, interfaces and function definitions required to build customized persistent Raft log storage and Raft RPC modules. |
Package statemachine contains the definitions of the IStateMachine and IOnDiskStateMachine interfaces to be implemented by application state machine types.
|
Package statemachine contains the definitions of the IStateMachine and IOnDiskStateMachine interfaces to be implemented by application state machine types. |