go/store/datas: FindCommonAncestor uses heap.

This commit is contained in:
Aaron Son
2021-07-16 08:46:42 -07:00
parent 8d971dcd35
commit 0013dd4b53

View File

@@ -22,9 +22,9 @@
package datas
import (
"container/heap"
"context"
"fmt"
"sort"
"github.com/dolthub/dolt/go/store/d"
"github.com/dolthub/dolt/go/store/hash"
@@ -101,7 +101,7 @@ func FindCommonAncestor(ctx context.Context, c1, c2 types.Ref, vr1, vr2 types.Va
d.Panic("second reference is not a commit")
}
c1Q, c2Q := &types.RefByHeight{c1}, &types.RefByHeight{c2}
c1Q, c2Q := RefByHeightHeap{c1}, RefByHeightHeap{c2}
for !c1Q.Empty() && !c2Q.Empty() {
c1Ht, c2Ht := c1Q.MaxHeight(), c2Q.MaxHeight()
if c1Ht == c2Ht {
@@ -109,21 +109,21 @@ func FindCommonAncestor(ctx context.Context, c1, c2 types.Ref, vr1, vr2 types.Va
if common, ok := findCommonRef(c1Parents, c2Parents); ok {
return common, true, nil
}
err = parentsToQueue(ctx, c1Parents, c1Q, vr1)
err = parentsToQueue(ctx, c1Parents, &c1Q, vr1)
if err != nil {
return types.Ref{}, false, err
}
err = parentsToQueue(ctx, c2Parents, c2Q, vr2)
err = parentsToQueue(ctx, c2Parents, &c2Q, vr2)
if err != nil {
return types.Ref{}, false, err
}
} else if c1Ht > c2Ht {
err = parentsToQueue(ctx, c1Q.PopRefsOfHeight(c1Ht), c1Q, vr1)
err = parentsToQueue(ctx, c1Q.PopRefsOfHeight(c1Ht), &c1Q, vr1)
if err != nil {
return types.Ref{}, false, err
}
} else {
err = parentsToQueue(ctx, c2Q.PopRefsOfHeight(c2Ht), c2Q, vr2)
err = parentsToQueue(ctx, c2Q.PopRefsOfHeight(c2Ht), &c2Q, vr2)
if err != nil {
return types.Ref{}, false, err
}
@@ -133,7 +133,7 @@ func FindCommonAncestor(ctx context.Context, c1, c2 types.Ref, vr1, vr2 types.Va
return a, ok, nil
}
func parentsToQueue(ctx context.Context, refs types.RefSlice, q *types.RefByHeight, vr types.ValueReader) error {
func parentsToQueue(ctx context.Context, refs types.RefSlice, q *RefByHeightHeap, vr types.ValueReader) error {
seen := make(map[hash.Hash]bool)
for _, r := range refs {
if _, ok := seen[r.TargetHash()]; ok {
@@ -160,7 +160,7 @@ func parentsToQueue(ctx context.Context, refs types.RefSlice, q *types.RefByHeig
if ok {
p := ps.(types.List)
err = p.Iter(ctx, func(v types.Value, _ uint64) (stop bool, err error) {
q.PushBack(v.(types.Ref))
heap.Push(q, v)
return
})
if err != nil {
@@ -174,7 +174,7 @@ func parentsToQueue(ctx context.Context, refs types.RefSlice, q *types.RefByHeig
if ok {
p := ps.(types.Set)
err = p.Iter(ctx, func(v types.Value) (stop bool, err error) {
q.PushBack(v.(types.Ref))
heap.Push(q, v)
return
})
if err != nil {
@@ -184,7 +184,6 @@ func parentsToQueue(ctx context.Context, refs types.RefSlice, q *types.RefByHeig
}
}
sort.Sort(q)
return nil
}
@@ -249,3 +248,44 @@ func IsCommit(v types.Value) (bool, error) {
func IsRefOfCommitType(nbf *types.NomsBinFormat, t *types.Type) bool {
return t.TargetKind() == types.RefKind && IsCommitType(nbf, getRefElementType(t))
}
type RefByHeightHeap []types.Ref
func (r RefByHeightHeap) Less(i, j int) bool {
return types.HeightOrder(r[i], r[j])
}
func (r RefByHeightHeap) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
func (r RefByHeightHeap) Len() int {
return len(r)
}
func (r *RefByHeightHeap) Push(x interface{}) {
*r = append(*r, x.(types.Ref))
}
func (r *RefByHeightHeap) Pop() interface{} {
old := *r
ret := old[len(old)-1]
*r = old[:len(old)-1]
return ret
}
func (r RefByHeightHeap) Empty() bool {
return len(r) == 0
}
func (r RefByHeightHeap) MaxHeight() uint64 {
return r[0].Height()
}
func (r *RefByHeightHeap) PopRefsOfHeight(h uint64) types.RefSlice {
var ret types.RefSlice
for !r.Empty() && r.MaxHeight() == h {
ret = append(ret, heap.Pop(r).(types.Ref))
}
return ret
}