Files
dolt/go/store/prolly/commit_closure.go
2022-09-08 14:35:43 -07:00

164 lines
4.5 KiB
Go

// Copyright 2022 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 (
"bytes"
"context"
"encoding/binary"
"github.com/dolthub/dolt/go/store/hash"
"github.com/dolthub/dolt/go/store/pool"
"github.com/dolthub/dolt/go/store/prolly/message"
"github.com/dolthub/dolt/go/store/prolly/tree"
"github.com/dolthub/dolt/go/store/types"
)
type CommitClosureValue []byte
type CommitClosure struct {
closure tree.StaticMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering]
}
type commitClosureKeyOrdering struct{}
var _ tree.Ordering[CommitClosureKey] = commitClosureKeyOrdering{}
func (o commitClosureKeyOrdering) Compare(left, right CommitClosureKey) int {
lh, rh := left.Height(), right.Height()
if lh == rh {
return bytes.Compare(left[8:], right[8:])
} else if lh < rh {
return -1
}
return 1
}
func NewEmptyCommitClosure(ns tree.NodeStore) (CommitClosure, error) {
serializer := message.NewCommitClosureSerializer(ns.Pool())
msg := serializer.Serialize(nil, nil, nil, 0)
node, err := tree.NodeFromBytes(msg)
if err != nil {
return CommitClosure{}, err
}
return NewCommitClosure(node, ns)
}
func NewCommitClosure(node tree.Node, ns tree.NodeStore) (CommitClosure, error) {
return CommitClosure{
closure: tree.StaticMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering]{
Root: node,
NodeStore: ns,
Order: commitClosureKeyOrdering{},
},
}, nil
}
func (c CommitClosure) Count() (int, error) {
return c.closure.Count()
}
func (c CommitClosure) Height() (int, error) {
return c.closure.Height()
}
func (c CommitClosure) Node() tree.Node {
return c.closure.Root
}
func (c CommitClosure) HashOf() hash.Hash {
return c.closure.HashOf()
}
func (c CommitClosure) Format() *types.NomsBinFormat {
return c.closure.NodeStore.Format()
}
func (c CommitClosure) Editor() CommitClosureEditor {
return CommitClosureEditor{
closure: c.closure.Mutate(),
}
}
func (c CommitClosure) IterAllReverse(ctx context.Context) (CommitClosureIter, error) {
return c.closure.IterAllReverse(ctx)
}
func DecodeCommitClosureKey(key []byte) (height uint64, addr hash.Hash) {
height = binary.LittleEndian.Uint64(key)
addr = hash.New(key[8:])
return
}
type CommitClosureEditor struct {
closure tree.MutableMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering]
}
type CommitClosureKey []byte
type CommitClosureIter tree.KvIter[CommitClosureKey, CommitClosureValue]
func NewCommitClosureKey(p pool.BuffPool, height uint64, addr hash.Hash) CommitClosureKey {
r := p.Get(8 + 20)
binary.LittleEndian.PutUint64(r, height)
copy(r[8:], addr[:])
return CommitClosureKey(r)
}
func (k CommitClosureKey) Height() uint64 {
return binary.LittleEndian.Uint64(k)
}
func (k CommitClosureKey) Addr() hash.Hash {
return hash.New(k[8:])
}
func (k CommitClosureKey) Less(other CommitClosureKey) bool {
return commitClosureKeyOrdering{}.Compare(k, other) < 0
}
var emptyCommitClosureValue CommitClosureValue = CommitClosureValue(make([]byte, 1))
func (wr CommitClosureEditor) Add(ctx context.Context, key CommitClosureKey) error {
return wr.closure.Put(ctx, key, emptyCommitClosureValue)
}
func (wr CommitClosureEditor) Delete(ctx context.Context, key CommitClosureKey) error {
return wr.closure.Delete(ctx, key)
}
func (wr CommitClosureEditor) Flush(ctx context.Context) (CommitClosure, error) {
sm := wr.closure.StaticMap
serializer := message.NewCommitClosureSerializer(sm.NodeStore.Pool())
fn := tree.ApplyMutations[CommitClosureKey, commitClosureKeyOrdering, message.CommitClosureSerializer]
root, err := fn(ctx, sm.NodeStore, sm.Root, commitClosureKeyOrdering{}, serializer, wr.closure.Mutations())
if err != nil {
return CommitClosure{}, err
}
return CommitClosure{
closure: tree.StaticMap[CommitClosureKey, CommitClosureValue, commitClosureKeyOrdering]{
Root: root,
NodeStore: sm.NodeStore,
Order: sm.Order,
},
}, nil
}
func DiffCommitClosures(ctx context.Context, from, to CommitClosure, cb tree.DiffFn) error {
return tree.DiffOrderedTrees(ctx, from.closure, to.closure, cb)
}