diff --git a/skl/skl.go b/skl/skl.go index cdfc599be..43694f14b 100644 --- a/skl/skl.go +++ b/skl/skl.go @@ -34,11 +34,11 @@ package skl import ( "math" - "math/rand" "sync/atomic" "unsafe" "github.com/dgraph-io/badger/v2/y" + "github.com/dgraph-io/ristretto/z" ) const ( @@ -165,9 +165,9 @@ func (s *node) casNextOffset(h int, old, val uint32) bool { // return n != nil && y.CompareKeys(key, n.key) > 0 //} -func randomHeight() int { +func (s *Skiplist) randomHeight() int { h := 1 - for h < maxHeight && rand.Uint32() <= heightIncrease { + for h < maxHeight && z.FastRand() <= heightIncrease { h++ } return h @@ -300,7 +300,7 @@ func (s *Skiplist) Put(key []byte, v y.ValueStruct) { } // We do need to create a new node. - height := randomHeight() + height := s.randomHeight() x := newNode(s.arena, key, v, height) // Try to increase s.height via CAS. diff --git a/skl/skl_test.go b/skl/skl_test.go index 6bd075862..0be7a64e4 100644 --- a/skl/skl_test.go +++ b/skl/skl_test.go @@ -499,7 +499,7 @@ func BenchmarkReadWriteMap(b *testing.B) { b.RunParallel(func(pb *testing.PB) { rng := rand.New(rand.NewSource(time.Now().UnixNano())) for pb.Next() { - if rand.Float32() < readFrac { + if rng.Float32() < readFrac { mutex.RLock() _, ok := m[string(randomKey(rng))] mutex.RUnlock() @@ -516,3 +516,16 @@ func BenchmarkReadWriteMap(b *testing.B) { }) } } + +func BenchmarkWrite(b *testing.B) { + value := newValue(123) + l := NewSkiplist(int64((b.N + 1) * MaxNodeSize)) + defer l.DecrRef() + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + for pb.Next() { + l.Put(randomKey(rng), y.ValueStruct{Value: value, Meta: 0, UserMeta: 0}) + } + }) +} diff --git a/table/table.go b/table/table.go index d68169384..fc20be7c0 100644 --- a/table/table.go +++ b/table/table.go @@ -232,6 +232,7 @@ func OpenTable(fd *os.File, opts Options) (*Table, error) { if err := t.initBiggestAndSmallest(); err != nil { return nil, errors.Wrapf(err, "failed to initialize table") } + if opts.ChkMode == options.OnTableRead || opts.ChkMode == options.OnTableAndBlockRead { if err := t.VerifyChecksum(); err != nil { _ = fd.Close() @@ -320,6 +321,9 @@ func (t *Table) readIndex() error { readPos -= 4 buf := t.readNoFail(readPos, 4) checksumLen := int(y.BytesToU32(buf)) + if checksumLen < 0 { + return errors.New("checksum length less than zero. Data corrupted") + } // Read checksum. expectedChk := &pb.Checksum{} diff --git a/table/table_test.go b/table/table_test.go index 82bddf591..7aa47d547 100644 --- a/table/table_test.go +++ b/table/table_test.go @@ -743,7 +743,10 @@ func TestTableChecksum(t *testing.T) { f := buildTestTable(t, "k", 10000, opts) fi, err := f.Stat() require.NoError(t, err, "unable to get file information") - f.WriteAt(rb, rand.Int63n(fi.Size())) + // Write random bytes at random location. + n, err := f.WriteAt(rb, rand.Int63n(fi.Size())) + require.NoError(t, err) + require.Equal(t, n, len(rb)) _, err = OpenTable(f, opts) if err == nil || !strings.Contains(err.Error(), "checksum") {