added prolly tree implementation for conflicts map

This commit is contained in:
Andy Arthur
2022-04-26 16:04:20 -07:00
parent 32381a7ace
commit cd15b81049
8 changed files with 181 additions and 10 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ func runShow(ctx context.Context, args []string) int {
chunk, err := cs.Get(ctx, sp.Path.Hash)
util.CheckErrorNoUsage(err)
value = tree.MapNodeFromBytes(chunk.Data())
value = tree.NodeFromBytes(chunk.Data())
} else {
util.CheckErrorNoUsage(err)
}
+154
View File
@@ -0,0 +1,154 @@
// Copyright 2021 Dolthub, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package prolly
import (
"context"
"github.com/dolthub/dolt/go/store/hash"
"github.com/dolthub/dolt/go/store/prolly/tree"
"github.com/dolthub/dolt/go/store/types"
"github.com/dolthub/dolt/go/store/val"
)
type Conflict val.Triple[val.Tuple]
func (c Conflict) OurValue() val.Tuple {
return val.Tuple(val.Triple(c).First())
}
func (c Conflict) TheirValue() val.Tuple {
return val.Tuple(val.Triple(c).Second())
}
func (c Conflict) BaseValue() val.Tuple {
return val.Tuple(val.Triple(c).Third())
}
type ConflictIter kvIter[val.Tuple, Conflict]
type ConflictMap struct {
conflicts orderedTree[val.Tuple, Conflict, val.TupleDesc]
keyDesc val.TupleDesc
ourDesc val.TupleDesc
theirDesc val.TupleDesc
baseDesc val.TupleDesc
}
func NewConflictMap(ns tree.NodeStore, key, ours, theirs, base val.TupleDesc) ConflictMap {
conflicts := orderedTree[val.Tuple, Conflict, val.TupleDesc]{
root: tree.NewEmptyNode(ns.Pool()),
ns: ns,
order: key,
}
return ConflictMap{
conflicts: conflicts,
keyDesc: key,
ourDesc: ours,
theirDesc: theirs,
baseDesc: base,
}
}
// Count returns the number of key-value pairs in the Map.
func (c ConflictMap) Count() int {
return c.conflicts.count()
}
func (c ConflictMap) Height() int {
return c.conflicts.height()
}
// HashOf returns the Hash of this Map.
func (c ConflictMap) HashOf() hash.Hash {
return c.conflicts.hashOf()
}
// Format returns the NomsBinFormat of this Map.
func (c ConflictMap) Format() *types.NomsBinFormat {
return c.conflicts.ns.Format()
}
// Descriptors returns the TupleDesc's from this Map.
func (c ConflictMap) Descriptors() (key, ours, theirs, base val.TupleDesc) {
return c.keyDesc, c.ourDesc, c.theirDesc, c.baseDesc
}
func (c ConflictMap) WalkAddresses(ctx context.Context, cb tree.AddressCb) error {
return c.conflicts.walkAddresses(ctx, cb)
}
func (c ConflictMap) WalkNodes(ctx context.Context, cb tree.NodeCb) error {
return c.conflicts.walkNodes(ctx, cb)
}
func (c ConflictMap) Get(ctx context.Context, key val.Tuple, cb KeyValueFn[val.Tuple, Conflict]) (err error) {
return c.conflicts.get(ctx, key, cb)
}
func (c ConflictMap) Has(ctx context.Context, key val.Tuple) (ok bool, err error) {
return c.conflicts.has(ctx, key)
}
// IterAll returns a mutableMapIter that iterates over the entire Map.
func (c ConflictMap) IterAll(ctx context.Context) (ConflictIter, error) {
return c.conflicts.iterAll(ctx)
}
// IterOrdinalRange returns a MapIter for the ordinal range beginning at |start| and ending before |stop|.
func (c ConflictMap) IterOrdinalRange(ctx context.Context, start, stop uint64) (ConflictIter, error) {
return c.conflicts.iterOrdinalRange(ctx, start, stop)
}
func (c ConflictMap) Writer() ConflictWriter {
return ConflictWriter{
conflicts: c.conflicts.mutate(),
keyDesc: c.keyDesc,
ourDesc: c.ourDesc,
theirDesc: c.theirDesc,
baseDesc: c.baseDesc,
}
}
type ConflictWriter struct {
conflicts orderedMap[val.Tuple, Conflict, val.TupleDesc]
keyDesc val.TupleDesc
ourDesc val.TupleDesc
theirDesc val.TupleDesc
baseDesc val.TupleDesc
}
func (wr ConflictWriter) AddConflict(ctx context.Context, key, ourVal, theirVal, baseVal val.Tuple) error {
p := wr.conflicts.tree.ns.Pool()
c := val.NewTriple(p, ourVal, theirVal, baseVal)
return wr.conflicts.put(ctx, key, c)
}
func (wr ConflictWriter) DeleteConflict(ctx context.Context, key val.Tuple) error {
return wr.conflicts.delete(ctx, key)
}
func (wr ConflictWriter) Flush(ctx context.Context) (ConflictMap, error) {
root, err := wr.conflicts.makeTree(ctx)
if err != nil {
return ConflictMap{}, err
}
return ConflictMap{
conflicts: root,
keyDesc: wr.keyDesc,
ourDesc: wr.ourDesc,
theirDesc: wr.theirDesc,
baseDesc: wr.baseDesc,
}, nil
}
+1 -1
View File
@@ -28,7 +28,7 @@ import (
)
func NodeFromValue(v types.Value) tree.Node {
return tree.MapNodeFromBytes(v.(types.TupleRowStorage))
return tree.NodeFromBytes(v.(types.TupleRowStorage))
}
func ValueFromMap(m Map) types.Value {
+11 -4
View File
@@ -20,6 +20,8 @@ import (
"io"
"math"
"github.com/dolthub/dolt/go/store/pool"
fb "github.com/google/flatbuffers/go"
"github.com/dolthub/dolt/go/gen/fb/serial"
@@ -82,12 +84,17 @@ func WalkNodes(ctx context.Context, nd Node, ns NodeStore, cb NodeCb) error {
})
}
func MapNodeFromBytes(buf []byte) Node {
msg := serial.GetRootAsProllyTreeNode(buf, 0)
return mapNodeFromFlatbuffer(*msg)
func NewEmptyNode(pool pool.BuffPool) Node {
bld := &nodeBuilder{}
return bld.build(pool)
}
func mapNodeFromFlatbuffer(msg serial.ProllyTreeNode) Node {
func NodeFromBytes(buf []byte) Node {
msg := serial.GetRootAsProllyTreeNode(buf, 0)
return nodeFromFlatbuffer(*msg)
}
func nodeFromFlatbuffer(msg serial.ProllyTreeNode) Node {
keys := val.SlicedBuffer{
Buf: msg.KeyItemsBytes(),
Offs: getKeyOffsetsVector(msg),
+1 -1
View File
@@ -143,7 +143,7 @@ func (nb *nodeBuilder) build(pool pool.BuffPool) (node Node) {
b.Finish(serial.ProllyTreeNodeEnd(b))
buf := b.FinishedBytes()
return MapNodeFromBytes(buf)
return NodeFromBytes(buf)
}
func newSubtreeCounts(count int) subtreeCounts {
+2 -2
View File
@@ -70,7 +70,7 @@ func NewNodeStore(cs chunks.ChunkStore) NodeStore {
func (ns nodeStore) Read(ctx context.Context, ref hash.Hash) (Node, error) {
c, ok := ns.cache.get(ref)
if ok {
return MapNodeFromBytes(c.Data()), nil
return NodeFromBytes(c.Data()), nil
}
c, err := ns.store.Get(ctx, ref)
@@ -81,7 +81,7 @@ func (ns nodeStore) Read(ctx context.Context, ref hash.Hash) (Node, error) {
ns.cache.insert(c)
return MapNodeFromBytes(c.Data()), err
return NodeFromBytes(c.Data()), err
}
// Write implements NodeStore.
+9
View File
@@ -107,6 +107,15 @@ func TestCountArray(t *testing.T) {
}
}
func TestNewEmptyNode(t *testing.T) {
empty := NewEmptyNode(sharedPool)
assert.Equal(t, 0, empty.Level())
assert.Equal(t, 0, empty.Count())
assert.Equal(t, 72, empty.Size())
assert.Equal(t, 0, empty.TreeCount())
assert.True(t, empty.IsLeaf())
}
func randomNodeItemPairs(t *testing.T, count int) (keys, values []Item) {
keys = make([]Item, count)
for i := range keys {
+2 -1
View File
@@ -15,8 +15,9 @@
package val
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewTriple(t *testing.T) {