From 9df0e7715d4b67e043c4c157b3347228b6e4e386 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Tue, 25 Nov 2014 15:13:07 -0800 Subject: [PATCH] raft: do not panic on out of date compaction --- etcdserver/server.go | 11 ++++++++++- raft/log_test.go | 8 +++++++- raft/storage.go | 12 +++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/etcdserver/server.go b/etcdserver/server.go index 03d99ca7d..d7d8e3fab 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -808,7 +808,16 @@ func (s *EtcdServer) snapshot(snapi uint64, snapnodes []uint64) { if err != nil { log.Panicf("store save should never fail: %v", err) } - s.raftStorage.Compact(snapi, &raftpb.ConfState{Nodes: snapnodes}, d) + err = s.raftStorage.Compact(snapi, &raftpb.ConfState{Nodes: snapnodes}, d) + if err != nil { + // the snapshot was done asynchronously with the progress of raft. + // raft might have already got a newer snapshot and called compact. + if err == raft.ErrCompacted { + return + } + log.Panicf("etcdserver: unexpected compaction error %v", err) + } + if err := s.storage.Cut(); err != nil { log.Panicf("rotate wal file should never fail: %v", err) } diff --git a/raft/log_test.go b/raft/log_test.go index de3046493..80a57428a 100644 --- a/raft/log_test.go +++ b/raft/log_test.go @@ -488,7 +488,13 @@ func TestCompaction(t *testing.T) { raftLog.appliedTo(raftLog.committed) for j := 0; j < len(tt.compact); j++ { - storage.Compact(tt.compact[j], nil, nil) + err := storage.Compact(tt.compact[j], nil, nil) + if err != nil { + if tt.wallow { + t.Errorf("#%d.%d allow = %t, want %t", i, j, false, tt.wallow) + } + continue + } if len(raftLog.allEntries()) != tt.wleft[j] { t.Errorf("#%d.%d len = %d, want %d", i, j, len(raftLog.allEntries()), tt.wleft[j]) } diff --git a/raft/storage.go b/raft/storage.go index dcfbb6f5d..8516bad03 100644 --- a/raft/storage.go +++ b/raft/storage.go @@ -18,13 +18,13 @@ package raft import ( "errors" - "fmt" + "log" "sync" pb "github.com/coreos/etcd/raft/raftpb" ) -// ErrCompacted is returned by Storage.Entries when a requested +// ErrCompacted is returned by Storage.Entries/Compact when a requested // index is unavailable because it predates the last snapshot. var ErrCompacted = errors.New("requested index is unavailable due to compaction") @@ -154,9 +154,11 @@ func (ms *MemoryStorage) Compact(i uint64, cs *pb.ConfState, data []byte) error ms.Lock() defer ms.Unlock() offset := ms.snapshot.Metadata.Index - if i <= offset || i > offset+uint64(len(ms.ents))-1 { - panic(fmt.Sprintf("compact %d out of bounds (%d, %d)", i, offset, - offset+uint64(len(ms.ents))-1)) + if i <= offset { + return ErrCompacted + } + if i > offset+uint64(len(ms.ents))-1 { + log.Panicf("compact %d out of bound lastindex(%d)", i, offset+uint64(len(ms.ents))-1) } i -= offset ents := make([]pb.Entry, 1, 1+uint64(len(ms.ents))-i)