From 27c9a0535c8c5dcd403cf6be2f376d21144cbeea Mon Sep 17 00:00:00 2001 From: Yicheng Qin Date: Fri, 22 Aug 2014 15:13:45 -0700 Subject: [PATCH] server: add tests for on-disk snapshot --- etcd/etcd_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++ etcd/participant.go | 2 +- raft/raft.go | 1 + 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/etcd/etcd_test.go b/etcd/etcd_test.go index 527151950..bd0ed49cb 100644 --- a/etcd/etcd_test.go +++ b/etcd/etcd_test.go @@ -24,6 +24,7 @@ import ( "net/http/httptest" "net/url" "os" + "path" "reflect" "strings" "testing" @@ -286,6 +287,64 @@ func TestRestoreSnapshotFromLeader(t *testing.T) { } } +func TestSaveSnapshot(t *testing.T) { + defer afterTest(t) + + cl := testCluster{Size: 1} + cl.Start() + defer cl.Destroy() + + n := cl.Node(0) + // TODO(xiangli): tunable compact; reduce testing time + for i := 0; i < defaultCompact; i++ { + n.Participant().Set("/foo", false, "bar", store.Permanent) + } + snapname := fmt.Sprintf("%016x-%016x-%016x.snap", n.Participant().clusterId, 1, defaultCompact) + snappath := path.Join(n.Config.DataDir, "snap", snapname) + if _, err := os.Stat(snappath); err != nil { + t.Errorf("err = %v, want nil", err) + } + walname := fmt.Sprintf("%016x-%016x.wal", 1, defaultCompact) + walpath := path.Join(n.Config.DataDir, "wal", walname) + if _, err := os.Stat(walpath); err != nil { + t.Errorf("err = %v, want nil", err) + } +} + +func TestRestoreSnapshotFromDisk(t *testing.T) { + defer afterTest(t) + + cl := testCluster{Size: 1} + cl.Start() + defer cl.Destroy() + + lead, _ := cl.Leader() + for i := 0; i < defaultCompact+10; i++ { + cl.Participant(lead).Set(fmt.Sprint("/foo", i), false, fmt.Sprint("bar", i), store.Permanent) + } + + cl.Stop() + cl.Restart() + + lead, _ = cl.Leader() + // check store is recovered + for i := 0; i < defaultCompact+10; i++ { + ev, err := cl.Participant(lead).Store.Get(fmt.Sprint("/foo", i), false, false) + if err != nil { + t.Errorf("get err = %v", err) + continue + } + w := fmt.Sprint("bar", i) + if g := *ev.Node.Value; g != w { + t.Errorf("value = %v, want %v", g, w) + } + } + // check new proposal could be submitted + if _, err := cl.Participant(lead).Set("/foo", false, "bar", store.Permanent); err != nil { + t.Fatal(err) + } +} + type testCluster struct { Size int TLS bool diff --git a/etcd/participant.go b/etcd/participant.go index b05c04278..5bb62a176 100644 --- a/etcd/participant.go +++ b/etcd/participant.go @@ -167,7 +167,7 @@ func newParticipant(c *conf.Config, client *v2client, peerHub *peerHub, tickDura p.id = n.Id p.node.Node = raft.Recover(n.Id, s, n.Ents, n.State, defaultHeartbeat, defaultElection) p.apply(p.node.Next()) - log.Printf("id=%x participant.load path=%s snap=%+v state=\"%+v\" len(ents)=%d", p.id, p.cfg.DataDir, s, n.State, len(n.Ents)) + log.Printf("id=%x participant.load path=%s snapIndex=%d state=\"%+v\" len(ents)=%d", p.id, p.cfg.DataDir, snapIndex, n.State, len(n.Ents)) if w, err = wal.Open(walDir); err != nil { return nil, err } diff --git a/raft/raft.go b/raft/raft.go index 85cd8e748..fa4fb79ee 100644 --- a/raft/raft.go +++ b/raft/raft.go @@ -511,6 +511,7 @@ func (sm *stateMachine) restore(s Snapshot) bool { for _, n := range s.Nodes { if n == sm.id { sm.addIns(n, sm.raftLog.lastIndex(), sm.raftLog.lastIndex()+1) + sm.promotable = true } else { sm.addIns(n, 0, sm.raftLog.lastIndex()+1) }