Explorar el Código

storage: fix hash by iterating kv

Xiang Li hace 10 años
padre
commit
385e17583f
Se han modificado 3 ficheros con 33 adiciones y 7 borrados
  1. 30 0
      storage/backend/backend.go
  2. 2 7
      storage/kvstore.go
  3. 1 0
      storage/kvstore_test.go

+ 30 - 0
storage/backend/backend.go

@@ -15,6 +15,8 @@
 package backend
 
 import (
+	"fmt"
+	"hash/crc32"
 	"io"
 	"log"
 	"time"
@@ -25,6 +27,7 @@ import (
 type Backend interface {
 	BatchTx() BatchTx
 	Snapshot(w io.Writer) (n int64, err error)
+	Hash() (uint32, error)
 	ForceCommit()
 	Close() error
 }
@@ -84,6 +87,33 @@ func (b *backend) Snapshot(w io.Writer) (n int64, err error) {
 	return n, err
 }
 
+func (b *backend) Hash() (uint32, error) {
+	h := crc32.New(crc32.MakeTable(crc32.Castagnoli))
+
+	err := b.db.View(func(tx *bolt.Tx) error {
+		c := tx.Cursor()
+		for next, _ := c.First(); next != nil; next, _ = c.Next() {
+			b := tx.Bucket(next)
+			if b == nil {
+				return fmt.Errorf("cannot get hash of bucket %s", string(next))
+			}
+			h.Write(next)
+			b.ForEach(func(k, v []byte) error {
+				h.Write(k)
+				h.Write(v)
+				return nil
+			})
+		}
+		return nil
+	})
+
+	if err != nil {
+		return 0, err
+	}
+
+	return h.Sum32(), nil
+}
+
 func (b *backend) run() {
 	defer close(b.donec)
 

+ 2 - 7
storage/kvstore.go

@@ -16,7 +16,6 @@ package storage
 
 import (
 	"errors"
-	"hash/crc32"
 	"io"
 	"log"
 	"math"
@@ -289,12 +288,8 @@ func (s *store) Compact(rev int64) error {
 }
 
 func (s *store) Hash() (uint32, error) {
-	h := crc32.New(crc32.MakeTable(crc32.Castagnoli))
-	_, err := s.Snapshot(h)
-	if err != nil {
-		return 0, err
-	}
-	return h.Sum32(), nil
+	s.b.ForceCommit()
+	return s.b.Hash()
 }
 
 func (s *store) Snapshot(w io.Writer) (int64, error) {

+ 1 - 0
storage/kvstore_test.go

@@ -722,6 +722,7 @@ type fakeBackend struct {
 }
 
 func (b *fakeBackend) BatchTx() backend.BatchTx                  { return b.tx }
+func (b *fakeBackend) Hash() (uint32, error)                     { return 0, nil }
 func (b *fakeBackend) Snapshot(w io.Writer) (n int64, err error) { return 0, errors.New("unsupported") }
 func (b *fakeBackend) ForceCommit()                              {}
 func (b *fakeBackend) Close() error                              { return nil }