diff --git a/etcdserver/api/v3rpc/maintenance.go b/etcdserver/api/v3rpc/maintenance.go index 552398bb2..a64ac2636 100644 --- a/etcdserver/api/v3rpc/maintenance.go +++ b/etcdserver/api/v3rpc/maintenance.go @@ -19,12 +19,17 @@ import ( "github.com/coreos/etcd/etcdserver" pb "github.com/coreos/etcd/etcdserver/etcdserverpb" + "github.com/coreos/etcd/mvcc" "github.com/coreos/etcd/mvcc/backend" "github.com/coreos/etcd/pkg/types" "github.com/coreos/etcd/version" "golang.org/x/net/context" ) +type KVGetter interface { + KV() mvcc.ConsistentWatchableKV +} + type BackendGetter interface { Backend() backend.Backend } @@ -41,13 +46,14 @@ type RaftStatusGetter interface { type maintenanceServer struct { rg RaftStatusGetter + kg KVGetter bg BackendGetter a Alarmer hdr header } func NewMaintenanceServer(s *etcdserver.EtcdServer) pb.MaintenanceServer { - return &maintenanceServer{rg: s, bg: s, a: s, hdr: newHeader(s)} + return &maintenanceServer{rg: s, kg: s, bg: s, a: s, hdr: newHeader(s)} } func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { @@ -97,11 +103,11 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance } func (ms *maintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) { - h, err := ms.bg.Backend().Hash() + h, rev, err := ms.kg.KV().Hash() if err != nil { return nil, togRPCError(err) } - resp := &pb.HashResponse{Header: &pb.ResponseHeader{Revision: ms.hdr.rev()}, Hash: h} + resp := &pb.HashResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: h} ms.hdr.fill(resp.Header) return resp, nil } diff --git a/mvcc/kv.go b/mvcc/kv.go index a8415a772..9c3d6bb5e 100644 --- a/mvcc/kv.go +++ b/mvcc/kv.go @@ -70,9 +70,9 @@ type KV interface { // Compact frees all superseded keys with revisions less than rev. Compact(rev int64) (<-chan struct{}, error) - // Hash retrieves the hash of KV state. + // Hash retrieves the hash of KV state and revision. // This method is designed for consistency checking purpose. - Hash() (uint32, error) + Hash() (hash uint32, revision int64, err error) // Commit commits txns into the underlying backend. Commit() diff --git a/mvcc/kv_test.go b/mvcc/kv_test.go index 6c045844b..3085346ab 100644 --- a/mvcc/kv_test.go +++ b/mvcc/kv_test.go @@ -620,7 +620,7 @@ func TestKVHash(t *testing.T) { kv := NewStore(b, &lease.FakeLessor{}, nil) kv.Put([]byte("foo0"), []byte("bar0"), lease.NoLease) kv.Put([]byte("foo1"), []byte("bar0"), lease.NoLease) - hashes[i], err = kv.Hash() + hashes[i], _, err = kv.Hash() if err != nil { t.Fatalf("failed to get hash: %v", err) } diff --git a/mvcc/kvstore.go b/mvcc/kvstore.go index 3ea286ca0..fb24868c3 100644 --- a/mvcc/kvstore.go +++ b/mvcc/kvstore.go @@ -293,9 +293,15 @@ func (s *store) Compact(rev int64) (<-chan struct{}, error) { return ch, nil } -func (s *store) Hash() (uint32, error) { +func (s *store) Hash() (uint32, int64, error) { s.b.ForceCommit() - return s.b.Hash() + + s.mu.Lock() + defer s.mu.Unlock() + + h, err := s.b.Hash() + rev := s.currentRev.main + return h, rev, err } func (s *store) Commit() { s.b.ForceCommit() }