mvcc: add and implement Keep api to index
Keep finds all revisions to be kept for a Compaction at the given rev.release-3.3
parent
ca586147bd
commit
7b8fb3cf0a
|
@ -28,6 +28,7 @@ type index interface {
|
||||||
Tombstone(key []byte, rev revision) error
|
Tombstone(key []byte, rev revision) error
|
||||||
RangeSince(key, end []byte, rev int64) []revision
|
RangeSince(key, end []byte, rev int64) []revision
|
||||||
Compact(rev int64) map[revision]struct{}
|
Compact(rev int64) map[revision]struct{}
|
||||||
|
Keep(rev int64) map[revision]struct{}
|
||||||
Equal(b index) bool
|
Equal(b index) bool
|
||||||
|
|
||||||
Insert(ki *keyIndex)
|
Insert(ki *keyIndex)
|
||||||
|
@ -179,6 +180,19 @@ func (ti *treeIndex) Compact(rev int64) map[revision]struct{} {
|
||||||
return available
|
return available
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep finds all revisions to be kept for a Compaction at the given rev.
|
||||||
|
func (ti *treeIndex) Keep(rev int64) map[revision]struct{} {
|
||||||
|
available := make(map[revision]struct{})
|
||||||
|
ti.RLock()
|
||||||
|
defer ti.RUnlock()
|
||||||
|
ti.tree.Ascend(func(i btree.Item) bool {
|
||||||
|
keyi := i.(*keyIndex)
|
||||||
|
keyi.keep(rev, available)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return available
|
||||||
|
}
|
||||||
|
|
||||||
func compactIndex(rev int64, available map[revision]struct{}, emptyki *[]*keyIndex) func(i btree.Item) bool {
|
func compactIndex(rev int64, available map[revision]struct{}, emptyki *[]*keyIndex) func(i btree.Item) bool {
|
||||||
return func(i btree.Item) bool {
|
return func(i btree.Item) bool {
|
||||||
keyi := i.(*keyIndex)
|
keyi := i.(*keyIndex)
|
||||||
|
|
|
@ -187,6 +187,42 @@ func (ki *keyIndex) compact(atRev int64, available map[revision]struct{}) {
|
||||||
plog.Panicf("store.keyindex: unexpected compact on empty keyIndex %s", string(ki.key))
|
plog.Panicf("store.keyindex: unexpected compact on empty keyIndex %s", string(ki.key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
genIdx, revIndex := ki.doCompact(atRev, available)
|
||||||
|
|
||||||
|
g := ki.generations[genIdx]
|
||||||
|
if !g.isEmpty() {
|
||||||
|
// remove the previous contents.
|
||||||
|
if revIndex != -1 {
|
||||||
|
g.revs = g.revs[revIndex:]
|
||||||
|
}
|
||||||
|
// remove any tombstone
|
||||||
|
if len(g.revs) == 1 && genIdx != len(ki.generations)-1 {
|
||||||
|
delete(available, g.revs[0])
|
||||||
|
genIdx++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the previous generations.
|
||||||
|
ki.generations = ki.generations[genIdx:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep finds the revision to be kept if compact is called at given atRev.
|
||||||
|
func (ki *keyIndex) keep(atRev int64, available map[revision]struct{}) {
|
||||||
|
if ki.isEmpty() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
genIdx, revIndex := ki.doCompact(atRev, available)
|
||||||
|
g := ki.generations[genIdx]
|
||||||
|
if !g.isEmpty() {
|
||||||
|
// remove any tombstone
|
||||||
|
if revIndex == len(g.revs)-1 && genIdx != len(ki.generations)-1 {
|
||||||
|
delete(available, g.revs[revIndex])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ki *keyIndex) doCompact(atRev int64, available map[revision]struct{}) (genIdx int, revIndex int) {
|
||||||
// walk until reaching the first revision that has an revision smaller or equal to
|
// walk until reaching the first revision that has an revision smaller or equal to
|
||||||
// the atRev.
|
// the atRev.
|
||||||
// add it to the available map
|
// add it to the available map
|
||||||
|
@ -198,30 +234,19 @@ func (ki *keyIndex) compact(atRev int64, available map[revision]struct{}) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
i, g := 0, &ki.generations[0]
|
genIdx, g := 0, &ki.generations[0]
|
||||||
// find first generation includes atRev or created after atRev
|
// find first generation includes atRev or created after atRev
|
||||||
for i < len(ki.generations)-1 {
|
for genIdx < len(ki.generations)-1 {
|
||||||
if tomb := g.revs[len(g.revs)-1].main; tomb > atRev {
|
if tomb := g.revs[len(g.revs)-1].main; tomb > atRev {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
i++
|
genIdx++
|
||||||
g = &ki.generations[i]
|
g = &ki.generations[genIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if !g.isEmpty() {
|
revIndex = g.walk(f)
|
||||||
n := g.walk(f)
|
|
||||||
// remove the previous contents.
|
return genIdx, revIndex
|
||||||
if n != -1 {
|
|
||||||
g.revs = g.revs[n:]
|
|
||||||
}
|
|
||||||
// remove any tombstone
|
|
||||||
if len(g.revs) == 1 && i != len(ki.generations)-1 {
|
|
||||||
delete(available, g.revs[0])
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remove the previous generations.
|
|
||||||
ki.generations = ki.generations[i:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ki *keyIndex) isEmpty() bool {
|
func (ki *keyIndex) isEmpty() bool {
|
||||||
|
|
Loading…
Reference in New Issue