go/store/prolly/tree: make node cursor pkg private

This commit is contained in:
Andy Arthur
2023-03-09 17:27:18 -08:00
parent 14d12e3500
commit d3e0c4d378
8 changed files with 275 additions and 310 deletions
@@ -153,11 +153,10 @@ func prollyChildSecDiffFkConstraintViolations(
parentSecIdx := durable.ProllyMapFromIndex(postParent.IndexData)
parentSecIdxDesc, _ := parentSecIdx.Descriptors()
partialDesc := parentSecIdxDesc.PrefixDesc(len(foreignKey.TableColumns))
prefixDesc := parentSecIdxDesc.PrefixDesc(len(foreignKey.TableColumns))
childPriKD, _ := postChildRowData.Descriptors()
childPriKB := val.NewTupleBuilder(childPriKD)
var parentSecIdxCur *tree.Cursor
err := prolly.DiffMaps(ctx, preChildSecIdx, postChildSecIdx, func(ctx context.Context, diff tree.Diff) error {
switch diff.Type {
case tree.AddedDiff, tree.ModifiedDiff:
@@ -169,31 +168,14 @@ func prollyChildSecDiffFkConstraintViolations(
}
}
if parentSecIdxCur == nil {
newCur, err := tree.NewCursorAtKey(ctx, parentSecIdx.NodeStore(), parentSecIdx.Node(), k, partialDesc)
if err != nil {
return err
}
if !newCur.Valid() {
return createCVForSecIdx(ctx, k, childPriKD, childPriKB, postChildRowData, postChildRowData.Pool(), receiver)
}
parentSecIdxCur = newCur
}
err := tree.Seek(ctx, parentSecIdxCur, k, partialDesc)
ok, err := parentSecIdx.HasRange(ctx, prolly.PrefixRange(k, prefixDesc))
if err != nil {
return err
}
if !parentSecIdxCur.Valid() {
return createCVForSecIdx(ctx, k, childPriKD, childPriKB, postChildRowData, postChildRowData.Pool(), receiver)
}
// possible that k is less than the smallest key in parentSecIdxCur, so still should compare
key := val.Tuple(parentSecIdxCur.CurrentKey())
if partialDesc.Compare(k, key) != 0 {
} else if !ok {
return createCVForSecIdx(ctx, k, childPriKD, childPriKB, postChildRowData, postChildRowData.Pool(), receiver)
}
return nil
case tree.RemovedDiff:
default:
panic("unhandled diff type")
@@ -203,7 +185,6 @@ func prollyChildSecDiffFkConstraintViolations(
if err != nil && err != io.EOF {
return err
}
return nil
}
+1 -5
View File
@@ -108,11 +108,7 @@ func (c CommitClosure) IsEmpty() bool {
func (c CommitClosure) ContainsKey(ctx context.Context, h hash.Hash, height uint64) (bool, error) {
k := NewCommitClosureKey(c.closure.NodeStore.Pool(), height, h)
cur, err := tree.NewCursorAtKey(ctx, c.closure.NodeStore, c.closure.Root, k, c.closure.Order)
if err != nil {
return false, err
}
return cur.Valid(), nil
return c.closure.Has(ctx, k)
}
func DecodeCommitClosureKey(key []byte) (height uint64, addr hash.Hash) {
+24 -24
View File
@@ -33,7 +33,7 @@ type Chunker interface {
}
type chunker[S message.Serializer] struct {
cur *Cursor
cur *cursor
parent *chunker[S]
level int
done bool
@@ -55,7 +55,7 @@ func newEmptyChunker[S message.Serializer](ctx context.Context, ns NodeStore, se
return newChunker(ctx, nil, 0, ns, serializer)
}
func newChunker[S message.Serializer](ctx context.Context, cur *Cursor, level int, ns NodeStore, serializer S) (*chunker[S], error) {
func newChunker[S message.Serializer](ctx context.Context, cur *cursor, level int, ns NodeStore, serializer S) (*chunker[S], error) {
// |cur| will be nil if this is a new Node, implying this is a new tree, or the tree has grown in height relative
// to its original chunked form.
@@ -98,8 +98,8 @@ func (tc *chunker[S]) processPrefix(ctx context.Context) (err error) {
return err
}
_, err = tc.append(ctx,
tc.cur.CurrentKey(),
tc.cur.CurrentValue(),
tc.cur.currentKey(),
tc.cur.currentValue(),
sz)
// todo(andy): seek to correct chunk
@@ -113,7 +113,7 @@ func (tc *chunker[S]) processPrefix(ctx context.Context) (err error) {
return err
}
err = tc.cur.Advance(ctx)
err = tc.cur.advance(ctx)
if err != nil {
return err
}
@@ -142,7 +142,7 @@ func (tc *chunker[S]) DeletePair(ctx context.Context, _, _ Item) error {
return tc.skip(ctx)
}
// AdvanceTo progresses the chunker until its tracking cursor catches up with
// advanceTo progresses the chunker until its tracking cursor catches up with
// |next|, a cursor indicating next key where an edit will be applied.
//
// The method proceeds from the deepest chunker recursively into its
@@ -166,8 +166,8 @@ func (tc *chunker[S]) DeletePair(ctx context.Context, _, _ Item) error {
// anticipation of impending edits that may edit the current chunk. Note that
// processPrefix is only necessary for the "fast forward" case where we
// synchronized the tree level before reaching |next|.
func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
cmp := tc.cur.Compare(next)
func (tc *chunker[S]) advanceTo(ctx context.Context, next *cursor) error {
cmp := tc.cur.compare(next)
if cmp == 0 { // step (1)
return nil
} else if cmp > 0 {
@@ -175,8 +175,8 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
// we navigate to the end of the previous chunk rather than the
// beginning of the next chunk. I think this is basically a one-off
// error.
for tc.cur.Compare(next) > 0 {
if err := next.Advance(ctx); err != nil {
for tc.cur.compare(next) > 0 {
if err := next.advance(ctx); err != nil {
return err
}
}
@@ -187,17 +187,17 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
if err != nil {
return err
}
split, err := tc.append(ctx, tc.cur.CurrentKey(), tc.cur.CurrentValue(), sz)
split, err := tc.append(ctx, tc.cur.currentKey(), tc.cur.currentValue(), sz)
if err != nil {
return err
}
for !(split && tc.cur.atNodeEnd()) { // step (2)
err = tc.cur.Advance(ctx)
err = tc.cur.advance(ctx)
if err != nil {
return err
}
if cmp = tc.cur.Compare(next); cmp >= 0 {
if cmp = tc.cur.compare(next); cmp >= 0 {
// we caught up before synchronizing
return nil
}
@@ -205,7 +205,7 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
if err != nil {
return err
}
split, err = tc.append(ctx, tc.cur.CurrentKey(), tc.cur.CurrentValue(), sz)
split, err = tc.append(ctx, tc.cur.currentKey(), tc.cur.currentValue(), sz)
if err != nil {
return err
}
@@ -217,7 +217,7 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
return nil
}
if tc.cur.parent.Compare(next.parent) == 0 { // step (3)
if tc.cur.parent.compare(next.parent) == 0 { // step (3)
// (rare) new tree synchronized with old tree at the
// same time as the cursor caught up to the next mutation point
tc.cur.copy(next)
@@ -229,7 +229,7 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
// This optimization is logically equivalent to advancing
// current cursor. Because we just wrote a chunk, we are
// at a boundary and can simply increment the parent.
err = tc.cur.parent.Advance(ctx)
err = tc.cur.parent.advance(ctx)
if err != nil {
return err
}
@@ -237,7 +237,7 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
// no more pending chunks at this level, recurse
// into parent
err = tc.parent.AdvanceTo(ctx, next.parent)
err = tc.parent.advanceTo(ctx, next.parent)
if err != nil {
return err
}
@@ -254,7 +254,7 @@ func (tc *chunker[S]) AdvanceTo(ctx context.Context, next *Cursor) error {
}
func (tc *chunker[S]) skip(ctx context.Context) error {
err := tc.cur.Advance(ctx)
err := tc.cur.advance(ctx)
return err
}
@@ -345,7 +345,7 @@ func (tc *chunker[S]) handleChunkBoundary(ctx context.Context) error {
func (tc *chunker[S]) createParentChunker(ctx context.Context) (err error) {
assertTrue(tc.parent == nil, "chunker parent must be nil")
var parent *Cursor
var parent *cursor
if tc.cur != nil && tc.cur.parent != nil {
// todo(andy): does this comment make sense? cloning a pointer?
// Clone the parent cursor because otherwise calling cur.forward() will affect our parent - and vice versa -
@@ -416,7 +416,7 @@ func (tc *chunker[S]) Done(ctx context.Context) (Node, error) {
// If we are mutating an existing Node, appending subsequent items in the Node until we reach a pre-existing chunk
// boundary or the end of the Node.
func (tc *chunker[S]) finalizeCursor(ctx context.Context) (err error) {
for tc.cur.Valid() {
for tc.cur.valid() {
var sz uint64
sz, err = tc.cur.currentSubtreeSize()
if err != nil {
@@ -424,8 +424,8 @@ func (tc *chunker[S]) finalizeCursor(ctx context.Context) (err error) {
}
var ok bool
ok, err = tc.append(ctx,
tc.cur.CurrentKey(),
tc.cur.CurrentValue(),
tc.cur.currentKey(),
tc.cur.currentValue(),
sz)
if err != nil {
return err
@@ -434,14 +434,14 @@ func (tc *chunker[S]) finalizeCursor(ctx context.Context) (err error) {
break // boundary occurred at same place in old & new Node
}
err = tc.cur.Advance(ctx)
err = tc.cur.advance(ctx)
if err != nil {
return err
}
}
if tc.cur.parent != nil {
err := tc.cur.parent.Advance(ctx)
err := tc.cur.parent.advance(ctx)
if err != nil {
return err
+62 -44
View File
@@ -37,8 +37,8 @@ type Diff struct {
type DiffFn func(context.Context, Diff) error
type Differ[K ~[]byte, O Ordering[K]] struct {
from, to *Cursor
fromStop, toStop *Cursor
from, to *cursor
fromStop, toStop *cursor
order O
}
@@ -48,33 +48,33 @@ func DifferFromRoots[K ~[]byte, O Ordering[K]](
from, to Node,
order O,
) (Differ[K, O], error) {
var fc, tc *Cursor
var fc, tc *cursor
var err error
if !from.empty() {
fc, err = NewCursorAtStart(ctx, fromNs, from)
fc, err = newCursorAtStart(ctx, fromNs, from)
if err != nil {
return Differ[K, O]{}, err
}
} else {
fc = &Cursor{}
fc = &cursor{}
}
if !to.empty() {
tc, err = NewCursorAtStart(ctx, toNs, to)
tc, err = newCursorAtStart(ctx, toNs, to)
if err != nil {
return Differ[K, O]{}, err
}
} else {
tc = &Cursor{}
tc = &cursor{}
}
fs, err := NewCursorPastEnd(ctx, fromNs, from)
fs, err := newCursorPastEnd(ctx, fromNs, from)
if err != nil {
return Differ[K, O]{}, err
}
ts, err := NewCursorPastEnd(ctx, toNs, to)
ts, err := newCursorPastEnd(ctx, toNs, to)
if err != nil {
return Differ[K, O]{}, err
}
@@ -89,10 +89,28 @@ func DifferFromRoots[K ~[]byte, O Ordering[K]](
}
func DifferFromCursors[K ~[]byte, O Ordering[K]](
fromStart, toStart,
fromStop, toStop *Cursor,
ctx context.Context,
fromRoot, toRoot Node,
findStart, findStop SearchFn,
fromStore, toStore NodeStore,
order O,
) (Differ[K, O], error) {
fromStart, err := newCursorFromSearchFn(ctx, fromStore, fromRoot, findStart)
if err != nil {
return Differ[K, O]{}, err
}
toStart, err := newCursorFromSearchFn(ctx, toStore, toRoot, findStart)
if err != nil {
return Differ[K, O]{}, err
}
fromStop, err := newCursorFromSearchFn(ctx, fromStore, fromRoot, findStop)
if err != nil {
return Differ[K, O]{}, err
}
toStop, err := newCursorFromSearchFn(ctx, toStore, toRoot, findStop)
if err != nil {
return Differ[K, O]{}, err
}
return Differ[K, O]{
from: fromStart,
to: toStart,
@@ -103,10 +121,10 @@ func DifferFromCursors[K ~[]byte, O Ordering[K]](
}
func (td Differ[K, O]) Next(ctx context.Context) (diff Diff, err error) {
for td.from.Valid() && td.from.Compare(td.fromStop) < 0 && td.to.Valid() && td.to.Compare(td.toStop) < 0 {
for td.from.valid() && td.from.compare(td.fromStop) < 0 && td.to.valid() && td.to.compare(td.toStop) < 0 {
f := td.from.CurrentKey()
t := td.to.CurrentKey()
f := td.from.currentKey()
t := td.to.currentKey()
cmp := td.order.Compare(K(f), K(t))
switch {
@@ -117,7 +135,7 @@ func (td Differ[K, O]) Next(ctx context.Context) (diff Diff, err error) {
return sendAdded(ctx, td.to)
case cmp == 0:
if !equalCursorValues(td.from, td.to) {
if !equalcursorValues(td.from, td.to) {
return sendModified(ctx, td.from, td.to)
}
@@ -128,65 +146,65 @@ func (td Differ[K, O]) Next(ctx context.Context) (diff Diff, err error) {
}
}
if td.from.Valid() && td.from.Compare(td.fromStop) < 0 {
if td.from.valid() && td.from.compare(td.fromStop) < 0 {
return sendRemoved(ctx, td.from)
}
if td.to.Valid() && td.to.Compare(td.toStop) < 0 {
if td.to.valid() && td.to.compare(td.toStop) < 0 {
return sendAdded(ctx, td.to)
}
return Diff{}, io.EOF
}
func sendRemoved(ctx context.Context, from *Cursor) (diff Diff, err error) {
func sendRemoved(ctx context.Context, from *cursor) (diff Diff, err error) {
diff = Diff{
Type: RemovedDiff,
Key: from.CurrentKey(),
From: from.CurrentValue(),
Key: from.currentKey(),
From: from.currentValue(),
}
if err = from.Advance(ctx); err != nil {
if err = from.advance(ctx); err != nil {
return Diff{}, err
}
return
}
func sendAdded(ctx context.Context, to *Cursor) (diff Diff, err error) {
func sendAdded(ctx context.Context, to *cursor) (diff Diff, err error) {
diff = Diff{
Type: AddedDiff,
Key: to.CurrentKey(),
To: to.CurrentValue(),
Key: to.currentKey(),
To: to.currentValue(),
}
if err = to.Advance(ctx); err != nil {
if err = to.advance(ctx); err != nil {
return Diff{}, err
}
return
}
func sendModified(ctx context.Context, from, to *Cursor) (diff Diff, err error) {
func sendModified(ctx context.Context, from, to *cursor) (diff Diff, err error) {
diff = Diff{
Type: ModifiedDiff,
Key: from.CurrentKey(),
From: from.CurrentValue(),
To: to.CurrentValue(),
Key: from.currentKey(),
From: from.currentValue(),
To: to.currentValue(),
}
if err = from.Advance(ctx); err != nil {
if err = from.advance(ctx); err != nil {
return Diff{}, err
}
if err = to.Advance(ctx); err != nil {
if err = to.advance(ctx); err != nil {
return Diff{}, err
}
return
}
func skipCommon(ctx context.Context, from, to *Cursor) (err error) {
func skipCommon(ctx context.Context, from, to *cursor) (err error) {
// track when |from.parent| and |to.parent| change
// to avoid unnecessary comparisons.
parentsAreNew := true
for from.Valid() && to.Valid() {
for from.valid() && to.valid() {
if !equalItems(from, to) {
// found the next difference
return nil
@@ -209,10 +227,10 @@ func skipCommon(ctx context.Context, from, to *Cursor) (err error) {
// case we need to Compare parents again.
parentsAreNew = from.atNodeEnd() || to.atNodeEnd()
if err = from.Advance(ctx); err != nil {
if err = from.advance(ctx); err != nil {
return err
}
if err = to.Advance(ctx); err != nil {
if err = to.advance(ctx); err != nil {
return err
}
}
@@ -220,13 +238,13 @@ func skipCommon(ctx context.Context, from, to *Cursor) (err error) {
return err
}
func skipCommonParents(ctx context.Context, from, to *Cursor) (err error) {
func skipCommonParents(ctx context.Context, from, to *cursor) (err error) {
err = skipCommon(ctx, from.parent, to.parent)
if err != nil {
return err
}
if from.parent.Valid() {
if from.parent.valid() {
if err = from.fetchNode(ctx); err != nil {
return err
}
@@ -235,7 +253,7 @@ func skipCommonParents(ctx context.Context, from, to *Cursor) (err error) {
from.invalidateAtEnd()
}
if to.parent.Valid() {
if to.parent.valid() {
if err = to.fetchNode(ctx); err != nil {
return err
}
@@ -248,18 +266,18 @@ func skipCommonParents(ctx context.Context, from, to *Cursor) (err error) {
}
// todo(andy): assumes equal byte representations
func equalItems(from, to *Cursor) bool {
return bytes.Equal(from.CurrentKey(), to.CurrentKey()) &&
bytes.Equal(from.CurrentValue(), to.CurrentValue())
func equalItems(from, to *cursor) bool {
return bytes.Equal(from.currentKey(), to.currentKey()) &&
bytes.Equal(from.currentValue(), to.currentValue())
}
func equalParents(from, to *Cursor) (eq bool) {
func equalParents(from, to *cursor) (eq bool) {
if from.parent != nil && to.parent != nil {
eq = equalItems(from.parent, to.parent)
}
return
}
func equalCursorValues(from, to *Cursor) bool {
return bytes.Equal(from.CurrentValue(), to.CurrentValue())
func equalcursorValues(from, to *cursor) bool {
return bytes.Equal(from.currentValue(), to.currentValue())
}
+80 -67
View File
@@ -66,56 +66,59 @@ func DiffKeyRangeOrderedTrees[K, V ~[]byte, O Ordering[K]](
start, stop K,
cb DiffFn,
) error {
var fromStart, fromStop, toStart, toStop *Cursor
var fromStart, fromStop, toStart, toStop *cursor
var err error
if len(start) == 0 {
fromStart, err = NewCursorAtStart(ctx, from.NodeStore, from.Root)
fromStart, err = newCursorAtStart(ctx, from.NodeStore, from.Root)
if err != nil {
return err
}
toStart, err = NewCursorAtStart(ctx, to.NodeStore, to.Root)
toStart, err = newCursorAtStart(ctx, to.NodeStore, to.Root)
if err != nil {
return err
}
} else {
fromStart, err = NewCursorAtKey(ctx, from.NodeStore, from.Root, start, from.Order)
fromStart, err = newCursorAtKey(ctx, from.NodeStore, from.Root, start, from.Order)
if err != nil {
return err
}
toStart, err = NewCursorAtKey(ctx, to.NodeStore, to.Root, start, to.Order)
toStart, err = newCursorAtKey(ctx, to.NodeStore, to.Root, start, to.Order)
if err != nil {
return err
}
}
if len(stop) == 0 {
fromStop, err = NewCursorPastEnd(ctx, from.NodeStore, from.Root)
fromStop, err = newCursorPastEnd(ctx, from.NodeStore, from.Root)
if err != nil {
return err
}
toStop, err = NewCursorPastEnd(ctx, to.NodeStore, to.Root)
toStop, err = newCursorPastEnd(ctx, to.NodeStore, to.Root)
if err != nil {
return err
}
} else {
fromStop, err = NewCursorAtKey(ctx, from.NodeStore, from.Root, stop, from.Order)
fromStop, err = newCursorAtKey(ctx, from.NodeStore, from.Root, stop, from.Order)
if err != nil {
return err
}
toStop, err = NewCursorAtKey(ctx, to.NodeStore, to.Root, stop, to.Order)
toStop, err = newCursorAtKey(ctx, to.NodeStore, to.Root, stop, to.Order)
if err != nil {
return err
}
}
differ, err := DifferFromCursors[K](fromStart, toStart, fromStop, toStop, from.Order)
if err != nil {
return err
differ := Differ[K, O]{
from: fromStart,
to: toStart,
fromStop: fromStop,
toStop: toStop,
order: from.Order,
}
for {
@@ -157,28 +160,28 @@ func VisitMapLevelOrder[K, V ~[]byte, O Ordering[K]](
cb func(h hash.Hash) (int64, error),
) error {
// get cursor to leaves
cur, err := NewCursorAtStart(ctx, m.NodeStore, m.Root)
cur, err := newCursorAtStart(ctx, m.NodeStore, m.Root)
if err != nil {
return err
}
first := cur.CurrentKey()
first := cur.currentKey()
// start by iterating level 1 nodes,
// then recurse upwards until we're at the root
for cur.parent != nil {
cur = cur.parent
for cur.Valid() {
_, err = cb(cur.CurrentRef())
for cur.valid() {
_, err = cb(cur.currentRef())
if err != nil {
return err
}
if err = cur.Advance(ctx); err != nil {
if err = cur.advance(ctx); err != nil {
return err
}
}
// return cursor to the start of the map
if err = Seek(ctx, cur, K(first), m.Order); err != nil {
if err = seek(ctx, cur, K(first), m.Order); err != nil {
return err
}
}
@@ -215,7 +218,7 @@ func (t StaticMap[K, V, O]) WalkNodes(ctx context.Context, cb NodeCb) error {
}
func (t StaticMap[K, V, O]) Get(ctx context.Context, query K, cb KeyValueFn[K, V]) (err error) {
cur, err := NewLeafCursorAtKey(ctx, t.NodeStore, t.Root, query, t.Order)
cur, err := newLeafCursorAtKey(ctx, t.NodeStore, t.Root, query, t.Order)
if err != nil {
return err
}
@@ -223,10 +226,10 @@ func (t StaticMap[K, V, O]) Get(ctx context.Context, query K, cb KeyValueFn[K, V
var key K
var value V
if cur.Valid() {
key = K(cur.CurrentKey())
if cur.valid() {
key = K(cur.currentKey())
if t.Order.Compare(query, key) == 0 {
value = V(cur.CurrentValue())
value = V(cur.currentValue())
} else {
key = nil
}
@@ -235,13 +238,13 @@ func (t StaticMap[K, V, O]) Get(ctx context.Context, query K, cb KeyValueFn[K, V
}
func (t StaticMap[K, V, O]) Has(ctx context.Context, query K) (ok bool, err error) {
cur, err := NewLeafCursorAtKey(ctx, t.NodeStore, t.Root, query, t.Order)
cur, err := newLeafCursorAtKey(ctx, t.NodeStore, t.Root, query, t.Order)
if err != nil {
return false, err
}
if cur.Valid() {
ok = t.Order.Compare(query, K(cur.CurrentKey())) == 0
if cur.valid() {
ok = t.Order.Compare(query, K(cur.currentKey())) == 0
}
return
@@ -258,18 +261,18 @@ func (t StaticMap[K, V, O]) LastKey(ctx context.Context) (key K) {
}
func (t StaticMap[K, V, O]) IterAll(ctx context.Context) (*OrderedTreeIter[K, V], error) {
c, err := NewCursorAtStart(ctx, t.NodeStore, t.Root)
c, err := newCursorAtStart(ctx, t.NodeStore, t.Root)
if err != nil {
return nil, err
}
s, err := NewCursorPastEnd(ctx, t.NodeStore, t.Root)
s, err := newCursorPastEnd(ctx, t.NodeStore, t.Root)
if err != nil {
return nil, err
}
stop := func(curr *Cursor) bool {
return curr.Compare(s) >= 0
stop := func(curr *cursor) bool {
return curr.compare(s) >= 0
}
if stop(c) {
@@ -277,26 +280,26 @@ func (t StaticMap[K, V, O]) IterAll(ctx context.Context) (*OrderedTreeIter[K, V]
return &OrderedTreeIter[K, V]{curr: nil}, nil
}
return &OrderedTreeIter[K, V]{curr: c, stop: stop, step: c.Advance}, nil
return &OrderedTreeIter[K, V]{curr: c, stop: stop, step: c.advance}, nil
}
func (t StaticMap[K, V, O]) IterAllReverse(ctx context.Context) (*OrderedTreeIter[K, V], error) {
beginning, err := NewCursorAtStart(ctx, t.NodeStore, t.Root)
beginning, err := newCursorAtStart(ctx, t.NodeStore, t.Root)
if err != nil {
return nil, err
}
err = beginning.Retreat(ctx)
err = beginning.retreat(ctx)
if err != nil {
return nil, err
}
end, err := NewCursorAtEnd(ctx, t.NodeStore, t.Root)
end, err := newCursorAtEnd(ctx, t.NodeStore, t.Root)
if err != nil {
return nil, err
}
stop := func(curr *Cursor) bool {
return curr.Compare(beginning) <= 0
stop := func(curr *cursor) bool {
return curr.compare(beginning) <= 0
}
if stop(end) {
@@ -304,7 +307,7 @@ func (t StaticMap[K, V, O]) IterAllReverse(ctx context.Context) (*OrderedTreeIte
return &OrderedTreeIter[K, V]{curr: nil}, nil
}
return &OrderedTreeIter[K, V]{curr: end, stop: stop, step: end.Retreat}, nil
return &OrderedTreeIter[K, V]{curr: end, stop: stop, step: end.retreat}, nil
}
func (t StaticMap[K, V, O]) IterOrdinalRange(ctx context.Context, start, stop uint64) (*OrderedTreeIter[K, V], error) {
@@ -323,21 +326,21 @@ func (t StaticMap[K, V, O]) IterOrdinalRange(ctx context.Context, start, stop ui
}
}
lo, err := NewCursorAtOrdinal(ctx, t.NodeStore, t.Root, start)
lo, err := newCursorAtOrdinal(ctx, t.NodeStore, t.Root, start)
if err != nil {
return nil, err
}
hi, err := NewCursorAtOrdinal(ctx, t.NodeStore, t.Root, stop)
hi, err := newCursorAtOrdinal(ctx, t.NodeStore, t.Root, stop)
if err != nil {
return nil, err
}
stopF := func(curr *Cursor) bool {
return curr.Compare(hi) >= 0
stopF := func(curr *cursor) bool {
return curr.compare(hi) >= 0
}
return &OrderedTreeIter[K, V]{curr: lo, stop: stopF, step: lo.Advance}, nil
return &OrderedTreeIter[K, V]{curr: lo, stop: stopF, step: lo.advance}, nil
}
func (t StaticMap[K, V, O]) FetchOrdinalRange(ctx context.Context, start, stop uint64) (*orderedLeafSpanIter[K, V], error) {
@@ -355,7 +358,7 @@ func (t StaticMap[K, V, O]) FetchOrdinalRange(ctx context.Context, start, stop u
}
}
span, err := FetchLeafNodeSpan(ctx, t.NodeStore, t.Root, start, stop)
span, err := fetchLeafNodeSpan(ctx, t.NodeStore, t.Root, start, stop)
if err != nil {
return nil, err
}
@@ -381,15 +384,15 @@ func (t StaticMap[K, V, O]) IterKeyRange(ctx context.Context, start, stop K) (*O
return nil, err
}
stopF := func(curr *Cursor) bool {
return curr.Compare(hi) >= 0
stopF := func(curr *cursor) bool {
return curr.compare(hi) >= 0
}
if stopF(lo) {
return &OrderedTreeIter[K, V]{curr: nil}, nil
}
return &OrderedTreeIter[K, V]{curr: lo, stop: stopF, step: lo.Advance}, nil
return &OrderedTreeIter[K, V]{curr: lo, stop: stopF, step: lo.advance}, nil
}
func (t StaticMap[K, V, O]) GetKeyRangeCardinality(ctx context.Context, start, stop K) (uint64, error) {
@@ -398,12 +401,12 @@ func (t StaticMap[K, V, O]) GetKeyRangeCardinality(ctx context.Context, start, s
return 0, err
}
startOrd, err := GetOrdinalOfCursor(lo)
startOrd, err := getOrdinalOfCursor(lo)
if err != nil {
return 0, err
}
endOrd, err := GetOrdinalOfCursor(hi)
endOrd, err := getOrdinalOfCursor(hi)
if err != nil {
return 0, err
}
@@ -411,68 +414,78 @@ func (t StaticMap[K, V, O]) GetKeyRangeCardinality(ctx context.Context, start, s
if startOrd > endOrd {
return 0, nil
}
return endOrd - startOrd, nil
}
func (t StaticMap[K, V, O]) getKeyRangeCursors(ctx context.Context, startInclusive, stopExclusive K) (lo, hi *Cursor, err error) {
func (t StaticMap[K, V, O]) getKeyRangeCursors(ctx context.Context, startInclusive, stopExclusive K) (lo, hi *cursor, err error) {
if len(startInclusive) == 0 {
lo, err = NewCursorAtStart(ctx, t.NodeStore, t.Root)
lo, err = newCursorAtStart(ctx, t.NodeStore, t.Root)
if err != nil {
return nil, nil, err
}
} else {
lo, err = NewCursorAtKey(ctx, t.NodeStore, t.Root, startInclusive, t.Order)
lo, err = newCursorAtKey(ctx, t.NodeStore, t.Root, startInclusive, t.Order)
if err != nil {
return nil, nil, err
}
}
if len(stopExclusive) == 0 {
hi, err = NewCursorPastEnd(ctx, t.NodeStore, t.Root)
hi, err = newCursorPastEnd(ctx, t.NodeStore, t.Root)
if err != nil {
return nil, nil, err
}
} else {
hi, err = NewCursorAtKey(ctx, t.NodeStore, t.Root, stopExclusive, t.Order)
hi, err = newCursorAtKey(ctx, t.NodeStore, t.Root, stopExclusive, t.Order)
if err != nil {
return nil, nil, err
}
}
return
}
// GetOrdinalForKey returns the smallest ordinal position at which the key >= |query|.
func (t StaticMap[K, V, O]) GetOrdinalForKey(ctx context.Context, query K) (uint64, error) {
cur, err := NewCursorAtKey(ctx, t.NodeStore, t.Root, query, t.Order)
cur, err := newCursorAtKey(ctx, t.NodeStore, t.Root, query, t.Order)
if err != nil {
return 0, err
}
return GetOrdinalOfCursor(cur)
return getOrdinalOfCursor(cur)
}
type OrderedTreeIter[K, V ~[]byte] struct {
// current tuple location
curr *Cursor
curr *cursor
// the function called to moved |curr| forward in the direction of iteration.
step func(context.Context) error
// should return |true| if the passed in cursor is past the iteration's stopping point.
stop func(*Cursor) bool
stop func(*cursor) bool
}
func OrderedTreeIterFromCursors[K, V ~[]byte](start, stop *Cursor) *OrderedTreeIter[K, V] {
stopF := func(curr *Cursor) bool {
return curr.Compare(stop) >= 0
func OrderedTreeIterFromCursors[K, V ~[]byte](
ctx context.Context,
root Node, ns NodeStore,
findStart, findStop SearchFn,
) (*OrderedTreeIter[K, V], error) {
start, err := newCursorFromSearchFn(ctx, ns, root, findStart)
if err != nil {
return nil, err
}
stop, err := newCursorFromSearchFn(ctx, ns, root, findStop)
if err != nil {
return nil, err
}
if stopF(start) {
stopFn := func(curr *cursor) bool {
return curr.compare(stop) >= 0
}
if stopFn(start) {
start = nil // empty range
}
return &OrderedTreeIter[K, V]{curr: start, stop: stopF, step: start.Advance}
return &OrderedTreeIter[K, V]{curr: start, stop: stopFn, step: start.advance}, nil
}
func (it *OrderedTreeIter[K, V]) Next(ctx context.Context) (key K, value V, err error) {
@@ -480,7 +493,7 @@ func (it *OrderedTreeIter[K, V]) Next(ctx context.Context) (key K, value V, err
return nil, nil, io.EOF
}
k, v := CurrentCursorItems(it.curr)
k, v := currentCursorItems(it.curr)
key, value = K(k), V(v)
err = it.step(ctx)
@@ -497,8 +510,8 @@ func (it *OrderedTreeIter[K, V]) Next(ctx context.Context) (key K, value V, err
func (it *OrderedTreeIter[K, V]) Current() (key K, value V) {
// |it.curr| is set to nil when its range is exhausted
if it.curr != nil && it.curr.Valid() {
k, v := CurrentCursorItems(it.curr)
if it.curr != nil && it.curr.valid() {
k, v := currentCursorItems(it.curr)
key, value = K(k), V(v)
}
return
+7 -7
View File
@@ -69,12 +69,12 @@ func ApplyMutations[K ~[]byte, O Ordering[K], S message.Serializer](
return root, nil // no mutations
}
cur, err := NewCursorAtKey(ctx, ns, root, K(newKey), order)
cur, err := newCursorAtKey(ctx, ns, root, K(newKey), order)
if err != nil {
return Node{}, err
}
chkr, err := newChunker(ctx, cur.Clone(), 0, ns, serializer)
chkr, err := newChunker(ctx, cur.clone(), 0, ns, serializer)
if err != nil {
return Node{}, err
}
@@ -82,17 +82,17 @@ func ApplyMutations[K ~[]byte, O Ordering[K], S message.Serializer](
for newKey != nil {
// move |cur| to the NextMutation mutation point
err = Seek(ctx, cur, K(newKey), order)
err = seek(ctx, cur, K(newKey), order)
if err != nil {
return Node{}, err
}
var oldValue Item
if cur.Valid() {
if cur.valid() {
// Compare mutations |newKey| and |newValue|
// to the existing pair from the cursor
if order.Compare(K(newKey), K(cur.CurrentKey())) == 0 {
oldValue = cur.CurrentValue()
if order.Compare(K(newKey), K(cur.currentKey())) == 0 {
oldValue = cur.currentValue()
}
}
@@ -103,7 +103,7 @@ func ApplyMutations[K ~[]byte, O Ordering[K], S message.Serializer](
}
// move |chkr| to the NextMutation mutation point
err = chkr.AdvanceTo(ctx, cur)
err = chkr.advanceTo(ctx, cur)
if err != nil {
return Node{}, err
}
+73 -73
View File
@@ -29,11 +29,11 @@ import (
"github.com/dolthub/dolt/go/store/hash"
)
// Cursor explores a tree of Nodes.
type Cursor struct {
// cursor explores a tree of Nodes.
type cursor struct {
nd Node
idx int
parent *Cursor
parent *cursor
nrw NodeStore
}
@@ -43,21 +43,21 @@ type Ordering[K ~[]byte] interface {
Compare(left, right K) int
}
func NewCursorAtStart(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor, err error) {
cur = &Cursor{nd: nd, nrw: ns}
func newCursorAtStart(ctx context.Context, ns NodeStore, nd Node) (cur *cursor, err error) {
cur = &cursor{nd: nd, nrw: ns}
var leaf bool
leaf, err = cur.isLeaf()
if err != nil {
return nil, err
}
for !leaf {
nd, err = fetchChild(ctx, ns, cur.CurrentRef())
nd, err = fetchChild(ctx, ns, cur.currentRef())
if err != nil {
return nil, err
}
parent := cur
cur = &Cursor{nd: nd, parent: parent, nrw: ns}
cur = &cursor{nd: nd, parent: parent, nrw: ns}
leaf, err = cur.isLeaf()
if err != nil {
return nil, err
@@ -66,8 +66,8 @@ func NewCursorAtStart(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor,
return
}
func NewCursorAtEnd(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor, err error) {
cur = &Cursor{nd: nd, nrw: ns}
func newCursorAtEnd(ctx context.Context, ns NodeStore, nd Node) (cur *cursor, err error) {
cur = &cursor{nd: nd, nrw: ns}
cur.skipToNodeEnd()
var leaf bool
@@ -76,13 +76,13 @@ func NewCursorAtEnd(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor, er
return nil, err
}
for !leaf {
nd, err = fetchChild(ctx, ns, cur.CurrentRef())
nd, err = fetchChild(ctx, ns, cur.currentRef())
if err != nil {
return nil, err
}
parent := cur
cur = &Cursor{nd: nd, parent: parent, nrw: ns}
cur = &cursor{nd: nd, parent: parent, nrw: ns}
cur.skipToNodeEnd()
leaf, err = cur.isLeaf()
if err != nil {
@@ -92,14 +92,14 @@ func NewCursorAtEnd(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor, er
return
}
func NewCursorPastEnd(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor, err error) {
cur, err = NewCursorAtEnd(ctx, ns, nd)
func newCursorPastEnd(ctx context.Context, ns NodeStore, nd Node) (cur *cursor, err error) {
cur, err = newCursorAtEnd(ctx, ns, nd)
if err != nil {
return nil, err
}
// Advance |cur| past the end
err = cur.Advance(ctx)
err = cur.advance(ctx)
if err != nil {
return nil, err
}
@@ -110,17 +110,17 @@ func NewCursorPastEnd(ctx context.Context, ns NodeStore, nd Node) (cur *Cursor,
return
}
func NewCursorAtOrdinal(ctx context.Context, ns NodeStore, nd Node, ord uint64) (cur *Cursor, err error) {
func newCursorAtOrdinal(ctx context.Context, ns NodeStore, nd Node, ord uint64) (cur *cursor, err error) {
cnt, err := nd.TreeCount()
if err != nil {
return nil, err
}
if ord >= uint64(cnt) {
return NewCursorPastEnd(ctx, ns, nd)
return newCursorPastEnd(ctx, ns, nd)
}
distance := int64(ord)
return NewCursorFromSearchFn(ctx, ns, nd, func(nd Node) (idx int) {
return newCursorFromSearchFn(ctx, ns, nd, func(nd Node) (idx int) {
if nd.IsLeaf() {
return int(distance)
}
@@ -138,8 +138,8 @@ func NewCursorAtOrdinal(ctx context.Context, ns NodeStore, nd Node, ord uint64)
})
}
// GetOrdinalOfCursor returns the ordinal position of a Cursor.
func GetOrdinalOfCursor(curr *Cursor) (ord uint64, err error) {
// GetOrdinalOfCursor returns the ordinal position of a cursor.
func getOrdinalOfCursor(curr *cursor) (ord uint64, err error) {
leaf, err := curr.isLeaf()
if err != nil {
return 0, err
@@ -178,12 +178,12 @@ func GetOrdinalOfCursor(curr *Cursor) (ord uint64, err error) {
return ord, nil
}
func NewCursorAtKey[K ~[]byte, O Ordering[K]](ctx context.Context, ns NodeStore, nd Node, key K, order O) (cur *Cursor, err error) {
return NewCursorFromSearchFn(ctx, ns, nd, SearchForKey(key, order))
func newCursorAtKey[K ~[]byte, O Ordering[K]](ctx context.Context, ns NodeStore, nd Node, key K, order O) (cur *cursor, err error) {
return newCursorFromSearchFn(ctx, ns, nd, searchForKey(key, order))
}
func NewCursorFromSearchFn(ctx context.Context, ns NodeStore, nd Node, search SearchFn) (cur *Cursor, err error) {
cur = &Cursor{nd: nd, nrw: ns}
func newCursorFromSearchFn(ctx context.Context, ns NodeStore, nd Node, search SearchFn) (cur *cursor, err error) {
cur = &cursor{nd: nd, nrw: ns}
cur.idx = search(cur.nd)
var leaf bool
@@ -196,13 +196,13 @@ func NewCursorFromSearchFn(ctx context.Context, ns NodeStore, nd Node, search Se
// stay in bounds for internal nodes
cur.keepInBounds()
nd, err = fetchChild(ctx, ns, cur.CurrentRef())
nd, err = fetchChild(ctx, ns, cur.currentRef())
if err != nil {
return cur, err
}
parent := cur
cur = &Cursor{nd: nd, parent: parent, nrw: ns}
cur = &cursor{nd: nd, parent: parent, nrw: ns}
cur.idx = search(cur.nd)
leaf, err = cur.isLeaf()
@@ -214,8 +214,8 @@ func NewCursorFromSearchFn(ctx context.Context, ns NodeStore, nd Node, search Se
return
}
func NewLeafCursorAtKey[K ~[]byte, O Ordering[K]](ctx context.Context, ns NodeStore, nd Node, key K, order O) (Cursor, error) {
cur := Cursor{nd: nd, nrw: ns}
func newLeafCursorAtKey[K ~[]byte, O Ordering[K]](ctx context.Context, ns NodeStore, nd Node, key K, order O) (cursor, error) {
cur := cursor{nd: nd, nrw: ns}
for {
// binary search |cur.nd| for |key|
i, j := 0, cur.nd.Count()
@@ -241,7 +241,7 @@ func NewLeafCursorAtKey[K ~[]byte, O Ordering[K]](ctx context.Context, ns NodeSt
cur.keepInBounds()
// reuse |cur| object to keep stack alloc'd
cur.nd, err = fetchChild(ctx, ns, cur.CurrentRef())
cur.nd, err = fetchChild(ctx, ns, cur.currentRef())
if err != nil {
return cur, err
}
@@ -249,8 +249,8 @@ func NewLeafCursorAtKey[K ~[]byte, O Ordering[K]](ctx context.Context, ns NodeSt
return cur, nil
}
// SearchForKey returns a SearchFn for |key|.
func SearchForKey[K ~[]byte, O Ordering[K]](key K, order O) SearchFn {
// searchForKey returns a SearchFn for |key|.
func searchForKey[K ~[]byte, O Ordering[K]](key K, order O) SearchFn {
return func(nd Node) (idx int) {
n := int(nd.Count())
// Define f(-1) == false and f(n) == true.
@@ -280,8 +280,8 @@ type LeafSpan struct {
// FetchLeafNodeSpan returns the leaf Node span for the ordinal range [start, stop). It fetches the span using
// an eager breadth-first search and makes batch read calls to the persistence layer via NodeStore.ReadMany.
func FetchLeafNodeSpan(ctx context.Context, ns NodeStore, root Node, start, stop uint64) (LeafSpan, error) {
leaves, localStart, err := fetchLeafNodeSpan(ctx, ns, []Node{root}, start, stop)
func fetchLeafNodeSpan(ctx context.Context, ns NodeStore, root Node, start, stop uint64) (LeafSpan, error) {
leaves, localStart, err := recursiveFetchLeafNodeSpan(ctx, ns, []Node{root}, start, stop)
if err != nil {
return LeafSpan{}, err
}
@@ -298,7 +298,7 @@ func FetchLeafNodeSpan(ctx context.Context, ns NodeStore, root Node, start, stop
}, nil
}
func fetchLeafNodeSpan(ctx context.Context, ns NodeStore, nodes []Node, start, stop uint64) ([]Node, uint64, error) {
func recursiveFetchLeafNodeSpan(ctx context.Context, ns NodeStore, nodes []Node, start, stop uint64) ([]Node, uint64, error) {
if nodes[0].IsLeaf() {
// verify leaf homogeneity
for i := range nodes {
@@ -342,20 +342,20 @@ func fetchLeafNodeSpan(ctx context.Context, ns NodeStore, nodes []Node, start, s
if err != nil {
return nil, 0, err
}
return fetchLeafNodeSpan(ctx, ns, children, start, stop)
return recursiveFetchLeafNodeSpan(ctx, ns, children, start, stop)
}
func CurrentCursorItems(cur *Cursor) (key, value Item) {
func currentCursorItems(cur *cursor) (key, value Item) {
key = cur.nd.keys.GetItem(cur.idx, cur.nd.msg)
value = cur.nd.values.GetItem(cur.idx, cur.nd.msg)
return
}
// Seek updates the cursor's node to one whose range spans the key's value, or the last
// seek updates the cursor's node to one whose range spans the key's value, or the last
// node if the key is greater than all existing keys.
// If a node does not contain the key, we recurse upwards to the parent cursor. If the
// node contains a key, we recurse downwards into child nodes.
func Seek[K ~[]byte, O Ordering[K]](ctx context.Context, cur *Cursor, key K, order O) (err error) {
func seek[K ~[]byte, O Ordering[K]](ctx context.Context, cur *cursor, key K, order O) (err error) {
inBounds := true
if cur.parent != nil {
inBounds = inBounds && order.Compare(key, K(cur.firstKey())) >= 0
@@ -364,44 +364,44 @@ func Seek[K ~[]byte, O Ordering[K]](ctx context.Context, cur *Cursor, key K, ord
if !inBounds {
// |item| is outside the bounds of |cur.nd|, search up the tree
err = Seek(ctx, cur.parent, key, order)
err = seek(ctx, cur.parent, key, order)
if err != nil {
return err
}
// stay in bounds for internal nodes
cur.parent.keepInBounds()
cur.nd, err = fetchChild(ctx, cur.nrw, cur.parent.CurrentRef())
cur.nd, err = fetchChild(ctx, cur.nrw, cur.parent.currentRef())
if err != nil {
return err
}
}
cur.idx = SearchForKey(key, order)(cur.nd)
cur.idx = searchForKey(key, order)(cur.nd)
return
}
func (cur *Cursor) Valid() bool {
func (cur *cursor) valid() bool {
return cur.nd.count != 0 &&
cur.nd.bytes() != nil &&
cur.idx >= 0 &&
cur.idx < int(cur.nd.count)
}
func (cur *Cursor) CurrentKey() Item {
func (cur *cursor) currentKey() Item {
return cur.nd.GetKey(cur.idx)
}
func (cur *Cursor) CurrentValue() Item {
func (cur *cursor) currentValue() Item {
return cur.nd.GetValue(cur.idx)
}
func (cur *Cursor) CurrentRef() hash.Hash {
func (cur *cursor) currentRef() hash.Hash {
return cur.nd.getAddress(cur.idx)
}
func (cur *Cursor) currentSubtreeSize() (uint64, error) {
func (cur *cursor) currentSubtreeSize() (uint64, error) {
leaf, err := cur.isLeaf()
if err != nil {
return 0, err
@@ -416,25 +416,25 @@ func (cur *Cursor) currentSubtreeSize() (uint64, error) {
return cur.nd.getSubtreeCount(cur.idx)
}
func (cur *Cursor) firstKey() Item {
func (cur *cursor) firstKey() Item {
return cur.nd.GetKey(0)
}
func (cur *Cursor) lastKey() Item {
func (cur *cursor) lastKey() Item {
lastKeyIdx := int(cur.nd.count) - 1
return cur.nd.GetKey(lastKeyIdx)
}
func (cur *Cursor) skipToNodeStart() {
func (cur *cursor) skipToNodeStart() {
cur.idx = 0
}
func (cur *Cursor) skipToNodeEnd() {
func (cur *cursor) skipToNodeEnd() {
lastKeyIdx := int(cur.nd.count) - 1
cur.idx = lastKeyIdx
}
func (cur *Cursor) keepInBounds() {
func (cur *cursor) keepInBounds() {
if cur.idx < 0 {
cur.skipToNodeStart()
}
@@ -444,18 +444,18 @@ func (cur *Cursor) keepInBounds() {
}
}
func (cur *Cursor) atNodeStart() bool {
func (cur *cursor) atNodeStart() bool {
return cur.idx == 0
}
// atNodeEnd returns true if the cursor's current |idx|
// points to the last node item
func (cur *Cursor) atNodeEnd() bool {
func (cur *cursor) atNodeEnd() bool {
lastKeyIdx := int(cur.nd.count) - 1
return cur.idx == lastKeyIdx
}
func (cur *Cursor) isLeaf() (bool, error) {
func (cur *cursor) isLeaf() (bool, error) {
// todo(andy): cache Level
lvl, err := cur.level()
if err != nil {
@@ -464,17 +464,17 @@ func (cur *Cursor) isLeaf() (bool, error) {
return lvl == 0, nil
}
func (cur *Cursor) level() (uint64, error) {
func (cur *cursor) level() (uint64, error) {
return uint64(cur.nd.level), nil
}
// invalidateAtEnd sets the cursor's index to the node count.
func (cur *Cursor) invalidateAtEnd() {
func (cur *cursor) invalidateAtEnd() {
cur.idx = int(cur.nd.count)
}
// invalidateAtStart sets the cursor's index to -1.
func (cur *Cursor) invalidateAtStart() {
func (cur *cursor) invalidateAtStart() {
cur.idx = -1
}
@@ -482,24 +482,24 @@ func (cur *Cursor) invalidateAtStart() {
// check the parent to know that the current cursor
// has more keys. hasNext can be false even if parent
// cursors are not exhausted.
func (cur *Cursor) hasNext() bool {
func (cur *cursor) hasNext() bool {
return cur.idx < int(cur.nd.count)-1
}
// hasPrev returns true if the current node has preceding
// keys. hasPrev can be false even in a parent node has
// preceding keys.
func (cur *Cursor) hasPrev() bool {
func (cur *cursor) hasPrev() bool {
return cur.idx > 0
}
// outOfBounds returns true if the current cursor and
// all parents are exhausted.
func (cur *Cursor) outOfBounds() bool {
func (cur *cursor) outOfBounds() bool {
return cur.idx < 0 || cur.idx >= int(cur.nd.count)
}
// Advance either increments the current key index by one,
// advance either increments the current key index by one,
// or has reached the end of the current node and skips to the next
// child of the parent cursor, recursively if necessary, returning
// either an error or nil.
@@ -516,7 +516,7 @@ func (cur *Cursor) outOfBounds() bool {
//
// 3) We've exhausted the current cursor and every |parent|. Jump
// to an end state (idx = node.count).
func (cur *Cursor) Advance(ctx context.Context) error {
func (cur *cursor) advance(ctx context.Context) error {
if cur.hasNext() {
cur.idx++
return nil
@@ -528,7 +528,7 @@ func (cur *Cursor) Advance(ctx context.Context) error {
}
// recursively increment the parent
err := cur.parent.Advance(ctx)
err := cur.parent.advance(ctx)
if err != nil {
return err
}
@@ -549,9 +549,9 @@ func (cur *Cursor) Advance(ctx context.Context) error {
return nil
}
// Retreat decrements to the previous key, if necessary by
// retreat decrements to the previous key, if necessary by
// recursively decrementing parent nodes.
func (cur *Cursor) Retreat(ctx context.Context) error {
func (cur *cursor) retreat(ctx context.Context) error {
if cur.hasPrev() {
cur.idx--
return nil
@@ -563,7 +563,7 @@ func (cur *Cursor) Retreat(ctx context.Context) error {
}
// recursively decrement the parent
err := cur.parent.Retreat(ctx)
err := cur.parent.retreat(ctx)
if err != nil {
return err
}
@@ -586,9 +586,9 @@ func (cur *Cursor) Retreat(ctx context.Context) error {
// fetchNode loads the Node that the cursor index points to.
// It's called whenever the cursor advances/retreats to a different chunk.
func (cur *Cursor) fetchNode(ctx context.Context) (err error) {
func (cur *cursor) fetchNode(ctx context.Context) (err error) {
assertTrue(cur.parent != nil, "cannot fetch node for cursor with nil parent")
cur.nd, err = fetchChild(ctx, cur.nrw, cur.parent.CurrentRef())
cur.nd, err = fetchChild(ctx, cur.nrw, cur.parent.currentRef())
cur.idx = -1 // caller must set
return err
}
@@ -608,25 +608,25 @@ func (cur *Cursor) fetchNode(ctx context.Context) (err error) {
// other: L3 -> 4, L2 -> 3, L1 -> 5, L0 -> 4
//
// res => +1 (from level 2)
func (cur *Cursor) Compare(other *Cursor) int {
func (cur *cursor) compare(other *cursor) int {
return compareCursors(cur, other)
}
func (cur *Cursor) Clone() *Cursor {
cln := Cursor{
func (cur *cursor) clone() *cursor {
cln := cursor{
nd: cur.nd,
idx: cur.idx,
nrw: cur.nrw,
}
if cur.parent != nil {
cln.parent = cur.parent.Clone()
cln.parent = cur.parent.clone()
}
return &cln
}
func (cur *Cursor) copy(other *Cursor) {
func (cur *cursor) copy(other *cursor) {
cur.nd = other.nd
cur.idx = other.idx
cur.nrw = other.nrw
@@ -639,7 +639,7 @@ func (cur *Cursor) copy(other *Cursor) {
}
}
func compareCursors(left, right *Cursor) (diff int) {
func compareCursors(left, right *cursor) (diff int) {
diff = 0
for {
d := left.idx - right.idx
+24 -67
View File
@@ -118,29 +118,10 @@ func DiffMaps(ctx context.Context, from, to Map, cb tree.DiffFn) error {
// RangeDiffMaps returns diffs within a Range. See Range for which diffs are
// returned.
func RangeDiffMaps(ctx context.Context, from, to Map, rng Range, cb tree.DiffFn) error {
fns, tns := from.tuples.NodeStore, to.tuples.NodeStore
fromStart, err := tree.NewCursorFromSearchFn(ctx, fns, from.tuples.Root, rangeStartSearchFn(rng))
if err != nil {
return err
}
toStart, err := tree.NewCursorFromSearchFn(ctx, tns, to.tuples.Root, rangeStartSearchFn(rng))
if err != nil {
return err
}
fromStop, err := tree.NewCursorFromSearchFn(ctx, fns, from.tuples.Root, rangeStopSearchFn(rng))
if err != nil {
return err
}
toStop, err := tree.NewCursorFromSearchFn(ctx, tns, to.tuples.Root, rangeStopSearchFn(rng))
if err != nil {
return err
}
differ, err := tree.DifferFromCursors[val.Tuple, val.TupleDesc](
fromStart, toStart,
fromStop, toStop,
ctx, from.tuples.Root, to.tuples.Root,
rangeStartSearchFn(rng), rangeStopSearchFn(rng),
from.NodeStore(), to.NodeStore(),
from.tuples.Order,
)
if err != nil {
@@ -287,10 +268,28 @@ func (m Map) FetchOrdinalRange(ctx context.Context, start, stop uint64) (MapIter
return m.tuples.FetchOrdinalRange(ctx, start, stop)
}
// HasRange returns true if the Map contains a key in |rng|.
func (m Map) HasRange(ctx context.Context, rng Range) (bool, error) {
iter, err := m.IterRange(ctx, rng)
if err != nil {
return false, err
}
k, _, err := iter.Next(ctx)
if err != nil {
return false, err
}
return rng.Matches(k), nil
}
// IterRange returns a mutableMapIter that iterates over a Range.
func (m Map) IterRange(ctx context.Context, rng Range) (MapIter, error) {
if rng.IsPointLookup(m.keyDesc) {
return m.pointLookupFromRange(ctx, rng)
var iter MapIter
err := m.Get(ctx, rng.Tup, func(key val.Tuple, value val.Tuple) error {
iter = &pointLookup{k: key, v: value}
return nil
})
return iter, err
}
iter, err := treeIterFromRange(ctx, m.tuples.Root, m.tuples.NodeStore, rng)
@@ -300,13 +299,6 @@ func (m Map) IterRange(ctx context.Context, rng Range) (MapIter, error) {
return filteredIter{iter: iter, rng: rng}, nil
}
// IterKeyRange iterates over a physical key range defined by |start| and
// |stop|. If |startInclusive| and/or |stop| is nil, the range will be open
// towards that end.
func (m Map) IterKeyRange(ctx context.Context, start, stop val.Tuple) (MapIter, error) {
return m.tuples.IterKeyRange(ctx, start, stop)
}
// GetOrdinalForKey returns the smallest ordinal position at which the key >=
// |query|.
func (m Map) GetOrdinalForKey(ctx context.Context, query val.Tuple) (uint64, error) {
@@ -332,49 +324,14 @@ func (m Map) CompareItems(left, right tree.Item) int {
return m.keyDesc.Compare(val.Tuple(left), val.Tuple(right))
}
func (m Map) pointLookupFromRange(ctx context.Context, rng Range) (*pointLookup, error) {
cur, err := tree.NewCursorFromSearchFn(ctx, m.tuples.NodeStore, m.tuples.Root, rangeStartSearchFn(rng))
if err != nil {
return nil, err
}
if !cur.Valid() {
// map does not contain |rng|
return &pointLookup{}, nil
}
key := val.Tuple(cur.CurrentKey())
value := val.Tuple(cur.CurrentValue())
if !rng.Matches(key) {
return &pointLookup{}, nil
}
return &pointLookup{k: key, v: value}, nil
}
func treeIterFromRange(
ctx context.Context,
root tree.Node,
ns tree.NodeStore,
rng Range,
) (*tree.OrderedTreeIter[val.Tuple, val.Tuple], error) {
var (
err error
start *tree.Cursor
stop *tree.Cursor
)
start, err = tree.NewCursorFromSearchFn(ctx, ns, root, rangeStartSearchFn(rng))
if err != nil {
return nil, err
}
stop, err = tree.NewCursorFromSearchFn(ctx, ns, root, rangeStopSearchFn(rng))
if err != nil {
return nil, err
}
return tree.OrderedTreeIterFromCursors[val.Tuple, val.Tuple](start, stop), nil
findStart, findStop := rangeStartSearchFn(rng), rangeStopSearchFn(rng)
return tree.OrderedTreeIterFromCursors[val.Tuple, val.Tuple](ctx, root, ns, findStart, findStop)
}
func NewPointLookup(k, v val.Tuple) *pointLookup {