diff --git a/mvcc/index_test.go b/mvcc/index_test.go index ef8df88fb3eb..d05315601bee 100644 --- a/mvcc/index_test.go +++ b/mvcc/index_test.go @@ -193,7 +193,7 @@ func TestIndexRangeSince(t *testing.T) { } } -func TestIndexCompact(t *testing.T) { +func TestIndexCompactAndKeep(t *testing.T) { maxRev := int64(20) tests := []struct { key []byte @@ -215,7 +215,7 @@ func TestIndexCompact(t *testing.T) { {[]byte("foo1"), false, revision{10, 1}, revision{10, 1}, 1}, } - // Continuous Compact + // Continuous Compact and Keep ti := newTreeIndex() for _, tt := range tests { if tt.remove { @@ -226,7 +226,10 @@ func TestIndexCompact(t *testing.T) { } for i := int64(1); i < maxRev; i++ { am := ti.Compact(i) - + keep := ti.Keep(i) + if !(reflect.DeepEqual(am, keep)) { + t.Errorf("#%d: compact keep %v != Keep keep %v", i, am, keep) + } wti := &treeIndex{tree: btree.New(32)} for _, tt := range tests { if _, ok := am[tt.rev]; ok || tt.rev.GreaterThan(revision{main: i}) { @@ -242,7 +245,7 @@ func TestIndexCompact(t *testing.T) { } } - // Once Compact + // Once Compact and Keep for i := int64(1); i < maxRev; i++ { ti := newTreeIndex() for _, tt := range tests { @@ -253,7 +256,10 @@ func TestIndexCompact(t *testing.T) { } } am := ti.Compact(i) - + keep := ti.Keep(i) + if !(reflect.DeepEqual(am, keep)) { + t.Errorf("#%d: compact keep %v != Keep keep %v", i, am, keep) + } wti := &treeIndex{tree: btree.New(32)} for _, tt := range tests { if _, ok := am[tt.rev]; ok || tt.rev.GreaterThan(revision{main: i}) { diff --git a/mvcc/key_index.go b/mvcc/key_index.go index fe812008cc71..8181d9d21c91 100644 --- a/mvcc/key_index.go +++ b/mvcc/key_index.go @@ -189,7 +189,7 @@ func (ki *keyIndex) compact(atRev int64, available map[revision]struct{}) { genIdx, revIndex := ki.doCompact(atRev, available) - g := ki.generations[genIdx] + g := &ki.generations[genIdx] if !g.isEmpty() { // remove the previous contents. if revIndex != -1 { @@ -213,7 +213,7 @@ func (ki *keyIndex) keep(atRev int64, available map[revision]struct{}) { } genIdx, revIndex := ki.doCompact(atRev, available) - g := ki.generations[genIdx] + g := &ki.generations[genIdx] if !g.isEmpty() { // remove any tombstone if revIndex == len(g.revs)-1 && genIdx != len(ki.generations)-1 { diff --git a/mvcc/key_index_test.go b/mvcc/key_index_test.go index bfaed9856e77..01b603275d89 100644 --- a/mvcc/key_index_test.go +++ b/mvcc/key_index_test.go @@ -205,7 +205,7 @@ func TestKeyIndexTombstone(t *testing.T) { } } -func TestKeyIndexCompact(t *testing.T) { +func TestKeyIndexCompactAndKeep(t *testing.T) { tests := []struct { compact int64 @@ -441,10 +441,19 @@ func TestKeyIndexCompact(t *testing.T) { }, } - // Continuous Compaction + // Continuous Compaction and finding Keep ki := newTestKeyIndex() for i, tt := range tests { am := make(map[revision]struct{}) + kiclone := cloneKeyIndex(ki) + ki.keep(tt.compact, am) + if !reflect.DeepEqual(ki, kiclone) { + t.Errorf("#%d: ki = %+v, want %+v", i, ki, kiclone) + } + if !reflect.DeepEqual(am, tt.wam) { + t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam) + } + am = make(map[revision]struct{}) ki.compact(tt.compact, am) if !reflect.DeepEqual(ki, tt.wki) { t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki) @@ -454,11 +463,20 @@ func TestKeyIndexCompact(t *testing.T) { } } - // Jump Compaction + // Jump Compaction and finding Keep ki = newTestKeyIndex() for i, tt := range tests { if (i%2 == 0 && i < 6) || (i%2 == 1 && i > 6) { am := make(map[revision]struct{}) + kiclone := cloneKeyIndex(ki) + ki.keep(tt.compact, am) + if !reflect.DeepEqual(ki, kiclone) { + t.Errorf("#%d: ki = %+v, want %+v", i, ki, kiclone) + } + if !reflect.DeepEqual(am, tt.wam) { + t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam) + } + am = make(map[revision]struct{}) ki.compact(tt.compact, am) if !reflect.DeepEqual(ki, tt.wki) { t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki) @@ -469,10 +487,19 @@ func TestKeyIndexCompact(t *testing.T) { } } - // Once Compaction + kiClone := newTestKeyIndex() + // Once Compaction and finding Keep for i, tt := range tests { ki := newTestKeyIndex() am := make(map[revision]struct{}) + ki.keep(tt.compact, am) + if !reflect.DeepEqual(ki, kiClone) { + t.Errorf("#%d: ki = %+v, want %+v", i, ki, kiClone) + } + if !reflect.DeepEqual(am, tt.wam) { + t.Errorf("#%d: am = %+v, want %+v", i, am, tt.wam) + } + am = make(map[revision]struct{}) ki.compact(tt.compact, am) if !reflect.DeepEqual(ki, tt.wki) { t.Errorf("#%d: ki = %+v, want %+v", i, ki, tt.wki) @@ -483,6 +510,22 @@ func TestKeyIndexCompact(t *testing.T) { } } +func cloneKeyIndex(ki *keyIndex) *keyIndex { + generations := make([]generation, len(ki.generations)) + for i, gen := range ki.generations { + generations[i] = *cloneGeneration(&gen) + } + return &keyIndex{ki.key, ki.modified, generations} +} + +func cloneGeneration(g *generation) *generation { + var tmp []revision + for _, rev := range g.revs { + tmp = append(tmp, revision{rev.main, rev.sub}) + } + return &generation{g.ver, g.created, tmp} +} + // test that compact on version that higher than last modified version works well func TestKeyIndexCompactOnFurtherRev(t *testing.T) { ki := &keyIndex{key: []byte("foo")} diff --git a/mvcc/kvstore_test.go b/mvcc/kvstore_test.go index f60ee2eb2ab8..f2f8cd851d3d 100644 --- a/mvcc/kvstore_test.go +++ b/mvcc/kvstore_test.go @@ -767,6 +767,10 @@ func (i *fakeIndex) Compact(rev int64) map[revision]struct{} { i.Recorder.Record(testutil.Action{Name: "compact", Params: []interface{}{rev}}) return <-i.indexCompactRespc } +func (i *fakeIndex) Keep(rev int64) map[revision]struct{} { + i.Recorder.Record(testutil.Action{Name: "keep", Params: []interface{}{rev}}) + return <-i.indexCompactRespc +} func (i *fakeIndex) Equal(b index) bool { return false } func (i *fakeIndex) Insert(ki *keyIndex) {