1
0
Fork 0

Fix restart issue after chunked-loading

master
Philip O'Toole 9 months ago
parent 428b44f365
commit 0ef35f1cbc

@ -53,8 +53,9 @@ func (l *Log) Indexes() (uint64, uint64, error) {
// log entry written to the Raft log. Returns an index of
// zero if no such log exists.
func (l *Log) LastCommandIndex(fi, li uint64) (uint64, error) {
// Check for empty log.
if li == 0 {
// Check for empty log. According to the interface defintion, if
// the first index is zero, or the last, the log is empty.
if fi == 0 || li == 0 {
return 0, nil
}

@ -246,6 +246,73 @@ func Test_LogNewExistNotEmptyNoFreelistSync(t *testing.T) {
}
}
func Test_LogDeleteAll(t *testing.T) {
path := mustTempFile()
defer os.Remove(path)
// Write some entries directory to the BoltDB Raft store.
bs, err := raftboltdb.NewBoltStore(path)
if err != nil {
t.Fatalf("failed to create bolt store: %s", err)
}
for i := 1; i < 5; i++ {
if err := bs.StoreLog(&raft.Log{
Index: uint64(i),
}); err != nil {
t.Fatalf("failed to write entry to raft log: %s", err)
}
}
if err := bs.Close(); err != nil {
t.Fatalf("failed to close bolt db: %s", err)
}
l, err := New(path, true)
if err != nil {
t.Fatalf("failed to create new log: %s", err)
}
// Check indices.
fi, err := l.FirstIndex()
if err != nil {
t.Fatalf("failed to get first index: %s", err)
}
if fi != 1 {
t.Fatalf("got wrong value for first index of log: %d", fi)
}
li, err := l.LastIndex()
if err != nil {
t.Fatalf("failed to get last index: %s", err)
}
if li != 4 {
t.Fatalf("got wrong value for last index of log: %d", li)
}
lci, err := l.LastCommandIndex(fi, li)
if err != nil {
t.Fatalf("failed to get last command index: %s", err)
}
if lci != 4 {
t.Fatalf("got wrong value for last command index of log: %d", lci)
}
if err := l.DeleteRange(1, 4); err != nil {
t.Fatalf("failed to delete range: %s", err)
}
fi, err = l.FirstIndex()
if err != nil {
t.Fatalf("failed to get first index: %s", err)
}
if fi != 0 {
t.Fatalf("got wrong value for first index of empty log: %d", fi)
}
li, err = l.LastIndex()
if err != nil {
t.Fatalf("failed to get last index: %s", err)
}
if li != 0 {
t.Fatalf("got wrong value for last index of empty log: %d", li)
}
}
func Test_LogLastCommandIndexNotExist(t *testing.T) {
path := mustTempFile()
defer os.Remove(path)

@ -2,10 +2,13 @@ package store
import (
"fmt"
"os"
"path/filepath"
"testing"
"time"
"github.com/rqlite/rqlite/command"
"github.com/rqlite/rqlite/command/chunking"
)
func test_OpenStoreCloseStartup(t *testing.T, s *Store) {
@ -276,3 +279,59 @@ func Test_StoreSnapshotStressSingleNode(t *testing.T) {
defer ln.Close()
test_SnapshotStress(t, s)
}
func Test_StoreLoadChunk_Restart(t *testing.T) {
s, ln := mustNewStore(t)
defer ln.Close()
if err := s.Open(); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
if err := s.Bootstrap(NewServer(s.ID(), s.Addr(), true)); err != nil {
t.Fatalf("failed to bootstrap single-node store: %s", err.Error())
}
defer s.Close(true)
if _, err := s.WaitForLeader(10 * time.Second); err != nil {
t.Fatalf("Error waiting for leader: %s", err)
}
// Open the SQLite file for loading.
f, err := os.Open(filepath.Join("testdata", "load.sqlite"))
if err != nil {
t.Fatalf("failed to open SQLite file: %s", err.Error())
}
defer f.Close()
numSnapshots := s.numSnapshots
chunker := chunking.NewChunker(f, 2048)
for {
chunk, err := chunker.Next()
if err != nil {
t.Fatalf("failed to read next chunk: %s", err.Error())
}
err = s.LoadChunk(chunk)
if err != nil {
t.Fatalf("failed to load chunk: %s", err.Error())
}
if chunk.IsLast {
break
}
}
// Chunked loading should trigger a snapshot, so check that the snapshot
// exists. Check that numSnapshots is 1
testPoll(t, func() bool {
s.numSnapshotsMu.Lock()
defer s.numSnapshotsMu.Unlock()
return s.numSnapshots == numSnapshots+1
}, 100*time.Millisecond, 3*time.Second)
// Check store can be re-opened.
if err := s.Close(true); err != nil {
t.Fatalf("failed to close single-node store: %s", err.Error())
}
if err := s.Open(); err != nil {
t.Fatalf("failed to open single-node store: %s", err.Error())
}
}

Loading…
Cancel
Save