blob: 7ec51289263f2249abe6f2651341bdd0b6f7ffc8 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package raft
import (
"io"
"v.io/v23/context"
"v.io/v23/verror"
)
var (
errOutOfSequence = verror.Register(pkgPath+".errOutOfSequence", verror.NoRetry, "{1:}{2:} append {3}, {4} out of sequence{:_}")
)
// persistent represents all the persistent state for the raft algorithm. The division exists should we
// want to replace the file system based store with something else.
type persistent interface {
// AppendLog appends cmds to the log starting at Index prevIndex+1. It will return
// an error if there does not exist a previous command at index preIndex with term
// prevTerm. It will also return an error if we cannot write to the persistent store.
AppendToLog(ctx *context.T, prevTerm Term, prevIndex Index, entries []LogEntry) error
// SetCurrentTerm, SetVotedFor, and SetCurrentTermAndVotedFor changes the non-log persistent state.
SetCurrentTerm(Term) error
IncCurrentTerm() error
SetVotedFor(id string) error
SetCurrentTermAndVotedFor(term Term, id string) error
// CurrentTerm returns the current Term.
CurrentTerm() Term
// LastIndex returns the highest index in the log.
LastIndex() Index
// LastTerm returns the highest term in the log.
LastTerm() Term
// GetVotedFor returns the current voted for string.
VotedFor() string
// Close all state. No other calls can be made on this object following
// the Close().
Close()
// Lookup returns the log entry at that index or nil if none exists.
Lookup(Index) *logEntry
// LookupPrevious returns the index and term preceding Index. It returns false if there is none.
// This is used when appending entries to the log. The leader needs to send the follower the
// term and index of the last entry appended to the log, and the follower has to check if it
// matches what they have at that point. However, either one may no longer have that entry, the
// leader because he is continuing after restoring from a snapshot or the follower because he has
// trimmed the log after a snapshot or for either when this is the first log record. I could
// have entered fake log entries but this seemed easier since it is closer to the logic from the
// raft paper.
//
// Granted I could avoid returning the previous index and have each client do the index-1. I just
// felt like doing it once rather than on every call.
LookupPrevious(Index) (Term, Index, bool)
// ConsiderSnapshot checks to see if it is time for a snapshot and, if so, calls back the client to
// generate a snapshot and then trims the log. On return it is safe to continue
// RaftClient.Apply()ing commands although the snapshot may still be in progress.
ConsiderSnapshot(ctx *context.T, lastAppliedTerm Term, lastAppliedIndex Index)
// SnapshotFromLeader receives and stores a snapshot from the leader and then restores the
// client state from the snapshot. 'lastTermApplied' and 'lastIndexApplied' represent the last
// log entry RaftClient.Apply()ed before the snapshot was taken.
SnapshotFromLeader(ctx *context.T, lastTermApplied Term, lastIndexApplied Index, call raftProtoInstallSnapshotServerCall) error
// OpenLatestSnapshot opens the latest snapshot and returns a reader for it. The returned Term
// and Index represent the last log entry RaftClient.Appy()ed before the snapshot was taken.
OpenLatestSnapshot(ctx *context.T) (io.Reader, Term, Index, error)
}