Merge pull request #14124 from wayblink/index-op

mvcc:add ut for Revisions/CountRevisions and remove RangeSince as it …
This commit is contained in:
Benjamin Wang 2022-06-21 12:41:25 +08:00 committed by GitHub
commit e0998f49e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 45 deletions

View File

@ -15,7 +15,6 @@
package mvcc
import (
"sort"
"sync"
"github.com/google/btree"
@ -29,7 +28,6 @@ type index interface {
CountRevisions(key, end []byte, atRev int64) int
Put(key []byte, rev revision)
Tombstone(key []byte, rev revision) error
RangeSince(key, end []byte, rev int64) []revision
Compact(rev int64) map[revision]struct{}
Keep(rev int64) map[revision]struct{}
Equal(b index) bool
@ -107,6 +105,9 @@ func (ti *treeIndex) unsafeVisit(key, end []byte, f func(ki *keyIndex) bool) {
})
}
// Revisions returns limited number of revisions from key(included) to end(excluded)
// at the given rev. The returned slice is sorted in the order of key. There is no limit if limit <= 0.
// The second return parameter isn't capped by the limit and reflects the total number of revisions.
func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs []revision, total int) {
ti.RLock()
defer ti.RUnlock()
@ -130,6 +131,8 @@ func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs []
return revs, total
}
// CountRevisions returns the number of revisions
// from key(included) to end(excluded) at the given rev.
func (ti *treeIndex) CountRevisions(key, end []byte, atRev int64) int {
ti.RLock()
defer ti.RUnlock()
@ -186,31 +189,6 @@ func (ti *treeIndex) Tombstone(key []byte, rev revision) error {
return ki.tombstone(ti.lg, rev.main, rev.sub)
}
// RangeSince returns all revisions from key(including) to end(excluding)
// at or after the given rev. The returned slice is sorted in the order
// of revision.
func (ti *treeIndex) RangeSince(key, end []byte, rev int64) []revision {
ti.RLock()
defer ti.RUnlock()
if end == nil {
keyi := ti.keyIndex(&keyIndex{key: key})
if keyi == nil {
return nil
}
return keyi.since(ti.lg, rev)
}
var revs []revision
ti.unsafeVisit(key, end, func(ki *keyIndex) bool {
revs = append(revs, ki.since(ti.lg, rev)...)
return true
})
sort.Sort(revisions(revs))
return revs
}
func (ti *treeIndex) Compact(rev int64) map[revision]struct{} {
available := make(map[revision]struct{})
ti.lg.Info("compact tree index", zap.Int64("revision", rev))

View File

@ -139,7 +139,7 @@ func TestIndexTombstone(t *testing.T) {
}
}
func TestIndexRangeSince(t *testing.T) {
func TestIndexRevision(t *testing.T) {
allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2"), []byte("foo2"), []byte("foo1"), []byte("foo")}
allRevs := []revision{{main: 1}, {main: 2}, {main: 3}, {main: 4}, {main: 5}, {main: 6}}
@ -148,48 +148,87 @@ func TestIndexRangeSince(t *testing.T) {
ti.Put(allKeys[i], allRevs[i])
}
atRev := int64(1)
tests := []struct {
key, end []byte
atRev int64
limit int
wrevs []revision
wcounts int
}{
// single key that not found
{
[]byte("bar"), nil, nil,
[]byte("bar"), nil, 6, 0, nil, 0,
},
// single key that found
{
[]byte("foo"), nil, []revision{{main: 1}, {main: 6}},
[]byte("foo"), nil, 6, 0, []revision{{main: 6}}, 1,
},
// range keys, return first member
// various range keys, fixed atRev, unlimited
{
[]byte("foo"), []byte("foo1"), []revision{{main: 1}, {main: 6}},
[]byte("foo"), []byte("foo1"), 6, 0, []revision{{main: 6}}, 1,
},
// range keys, return first two members
{
[]byte("foo"), []byte("foo2"), []revision{{main: 1}, {main: 2}, {main: 5}, {main: 6}},
[]byte("foo"), []byte("foo2"), 6, 0, []revision{{main: 6}, {main: 5}}, 2,
},
// range keys, return all members
{
[]byte("foo"), []byte("fop"), allRevs,
[]byte("foo"), []byte("fop"), 6, 0, []revision{{main: 6}, {main: 5}, {main: 4}}, 3,
},
// range keys, return last two members
{
[]byte("foo1"), []byte("fop"), []revision{{main: 2}, {main: 3}, {main: 4}, {main: 5}},
[]byte("foo1"), []byte("fop"), 6, 0, []revision{{main: 5}, {main: 4}}, 2,
},
// range keys, return last member
{
[]byte("foo2"), []byte("fop"), []revision{{main: 3}, {main: 4}},
[]byte("foo2"), []byte("fop"), 6, 0, []revision{{main: 4}}, 1,
},
// range keys, return nothing
{
[]byte("foo3"), []byte("fop"), nil,
[]byte("foo3"), []byte("fop"), 6, 0, nil, 0,
},
// fixed range keys, various atRev, unlimited
{
[]byte("foo1"), []byte("fop"), 1, 0, nil, 0,
},
{
[]byte("foo1"), []byte("fop"), 2, 0, []revision{{main: 2}}, 1,
},
{
[]byte("foo1"), []byte("fop"), 3, 0, []revision{{main: 2}, {main: 3}}, 2,
},
{
[]byte("foo1"), []byte("fop"), 4, 0, []revision{{main: 2}, {main: 4}}, 2,
},
{
[]byte("foo1"), []byte("fop"), 5, 0, []revision{{main: 5}, {main: 4}}, 2,
},
{
[]byte("foo1"), []byte("fop"), 6, 0, []revision{{main: 5}, {main: 4}}, 2,
},
// fixed range keys, fixed atRev, various limit
{
[]byte("foo"), []byte("fop"), 6, 1, []revision{{main: 6}}, 3,
},
{
[]byte("foo"), []byte("fop"), 6, 2, []revision{{main: 6}, {main: 5}}, 3,
},
{
[]byte("foo"), []byte("fop"), 6, 3, []revision{{main: 6}, {main: 5}, {main: 4}}, 3,
},
{
[]byte("foo"), []byte("fop"), 3, 1, []revision{{main: 1}}, 3,
},
{
[]byte("foo"), []byte("fop"), 3, 2, []revision{{main: 1}, {main: 2}}, 3,
},
{
[]byte("foo"), []byte("fop"), 3, 3, []revision{{main: 1}, {main: 2}, {main: 3}}, 3,
},
}
for i, tt := range tests {
revs := ti.RangeSince(tt.key, tt.end, atRev)
revs, _ := ti.Revisions(tt.key, tt.end, tt.atRev, tt.limit)
if !reflect.DeepEqual(revs, tt.wrevs) {
t.Errorf("#%d: revs = %+v, want %+v", i, revs, tt.wrevs)
t.Errorf("#%d limit %d: revs = %+v, want %+v", i, tt.limit, revs, tt.wrevs)
}
count := ti.CountRevisions(tt.key, tt.end, tt.atRev)
if count != tt.wcounts {
t.Errorf("#%d: count = %d, want %v", i, count, tt.wcounts)
}
}
}