diff --git a/raft/log.go b/raft/log.go index e31144ec5..117b4d733 100644 --- a/raft/log.go +++ b/raft/log.go @@ -261,6 +261,8 @@ func (l *raftLog) slice(lo uint64, hi uint64) []pb.Entry { // This should never fail because it has been checked before. log.Panicf("entries[%d:%d) from storage is out of bound", lo, min(hi, l.unstable.offset)) return nil + } else if err == ErrUnavailable { + return nil } else if err != nil { panic(err) // TODO(bdarnell) } diff --git a/raft/log_unstable.go b/raft/log_unstable.go index f3aa79dbc..aac885d36 100644 --- a/raft/log_unstable.go +++ b/raft/log_unstable.go @@ -34,10 +34,11 @@ type unstable struct { offset uint64 } -// maybeFirstIndex returns the first index if it has a snapshot. +// maybeFirstIndex returns the index of the first possible entry in entries +// if it has a snapshot. func (u *unstable) maybeFirstIndex() (uint64, bool) { if u.snapshot != nil { - return u.snapshot.Metadata.Index, true + return u.snapshot.Metadata.Index + 1, true } return 0, false } diff --git a/raft/storage.go b/raft/storage.go index 90c6ae809..9ffc06a70 100644 --- a/raft/storage.go +++ b/raft/storage.go @@ -28,6 +28,8 @@ import ( // index is unavailable because it predates the last snapshot. var ErrCompacted = errors.New("requested index is unavailable due to compaction") +var ErrUnavailable = errors.New("requested entry at index is unavailable") + // Storage is an interface that may be implemented by the application // to retrieve log entries from storage. // @@ -47,8 +49,9 @@ type Storage interface { // LastIndex returns the index of the last entry in the log. LastIndex() (uint64, error) // FirstIndex returns the index of the first log entry that is - // available via Entries (older entries have been incorporated - // into the latest Snapshot). + // possibly available via Entries (older entries have been incorporated + // into the latest Snapshot; if storage only contains the dummy entry the + // first log entry is not available). FirstIndex() (uint64, error) // Snapshot returns the most recent snapshot. Snapshot() (pb.Snapshot, error) @@ -95,6 +98,10 @@ func (ms *MemoryStorage) Entries(lo, hi uint64) ([]pb.Entry, error) { if lo <= offset { return nil, ErrCompacted } + // only contains dummy entries. + if len(ms.ents) == 1 { + return nil, ErrUnavailable + } return ms.ents[lo-offset : hi-offset], nil }