Skip to content

Commit

Permalink
rework based on discussions
Browse files Browse the repository at this point in the history
  • Loading branch information
smrz2001 committed Sep 11, 2022
1 parent e3244e8 commit 3d4d63c
Show file tree
Hide file tree
Showing 13 changed files with 445 additions and 1,487 deletions.
13 changes: 13 additions & 0 deletions datamodel/amender.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package datamodel

type Amender interface {
NodeBuilder

// Get returns the node at the specified path. It will not create any intermediate nodes because this is just a
// retrieval and not a modification operation.
Get(path Path) (Node, error)

// Transform will do an in-place transformation of the node at the specified path and return its previous value.
// If `createParents = true`, any missing parents will be created, otherwise this function will return an error.
Transform(path Path, createParents bool) (Node, error)
}
2 changes: 1 addition & 1 deletion datamodel/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ type NodePrototype interface {
// volumes of data, detecting and using this feature can result in significant
// performance savings.
type NodePrototypeSupportingAmend interface {
AmendingBuilder(base Node) NodeBuilder
AmendingBuilder(base Node) Amender
// FUTURE: probably also needs a `AmendingWithout(base Node, filter func(k,v) bool) NodeBuilder`, or similar.
// ("deletion" based APIs are also possible but both more complicated in interfaces added, and prone to accidentally quadratic usage.)
// FUTURE: there should be some stdlib `Copy` (?) methods that automatically look for this feature, and fallback if absent.
Expand Down
44 changes: 24 additions & 20 deletions node/basicnode/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package basicnode
import (
"fmt"

"github.com/emirpasic/gods/maps/linkedhashmap"

"github.com/ipld/go-ipld-prime/datamodel"
"github.com/ipld/go-ipld-prime/node/mixins"
)
Expand All @@ -18,8 +20,7 @@ var (
// It can contain any kind of value.
// plainMap is also embedded in the 'any' struct and usable from there.
type plainMap struct {
m map[string]datamodel.Node // string key -- even if a runtime schema wrapper is using us for storage, we must have a comparable type here, and string is all we know.
t []plainMap__Entry // table for fast iteration, order keeping, and yielding pointers to enable alloc/conv amortization.
m *linkedhashmap.Map
}

type plainMap__Entry struct {
Expand All @@ -34,11 +35,11 @@ func (plainMap) Kind() datamodel.Kind {
return datamodel.Kind_Map
}
func (n *plainMap) LookupByString(key string) (datamodel.Node, error) {
v, exists := n.m[key]
if !exists {
if v, exists := n.m.Get(key); !exists {
return nil, datamodel.ErrNotExists{Segment: datamodel.PathSegmentOfString(key)}
} else {
return v.(*plainMap__Entry).v, nil
}
return v, nil
}
func (n *plainMap) LookupByNode(key datamodel.Node) (datamodel.Node, error) {
ks, err := key.AsString()
Expand All @@ -54,13 +55,14 @@ func (n *plainMap) LookupBySegment(seg datamodel.PathSegment) (datamodel.Node, e
return n.LookupByString(seg.String())
}
func (n *plainMap) MapIterator() datamodel.MapIterator {
return &plainMap_MapIterator{n, 0}
itr := n.m.Iterator()
return &plainMap_MapIterator{n, &itr, 0}
}
func (plainMap) ListIterator() datamodel.ListIterator {
return nil
}
func (n *plainMap) Length() int64 {
return int64(len(n.t))
return int64(n.m.Size())
}
func (plainMap) IsAbsent() bool {
return false
Expand Down Expand Up @@ -92,20 +94,23 @@ func (plainMap) Prototype() datamodel.NodePrototype {

type plainMap_MapIterator struct {
n *plainMap
ni *linkedhashmap.Iterator
idx int
}

func (itr *plainMap_MapIterator) Next() (k datamodel.Node, v datamodel.Node, _ error) {
if itr.Done() {
return nil, nil, datamodel.ErrIteratorOverread{}
}
k = &itr.n.t[itr.idx].k
v = itr.n.t[itr.idx].v
itr.ni.Next()
entry := itr.ni.Value().(*plainMap__Entry)
k = &entry.k
v = entry.v
itr.idx++
return
}
func (itr *plainMap_MapIterator) Done() bool {
return itr.idx >= len(itr.n.t)
return itr.idx >= itr.n.m.Size()
}

// -- NodePrototype -->
Expand Down Expand Up @@ -167,8 +172,7 @@ func (na *plainMap__Assembler) BeginMap(sizeHint int64) (datamodel.MapAssembler,
sizeHint = 0
}
// Allocate storage space.
na.w.t = make([]plainMap__Entry, 0, sizeHint)
na.w.m = make(map[string]datamodel.Node, sizeHint)
na.w.m = linkedhashmap.New()
// That's it; return self as the MapAssembler. We already have all the right methods on this structure.
return na, nil
}
Expand Down Expand Up @@ -247,12 +251,12 @@ func (ma *plainMap__Assembler) AssembleEntry(k string) (datamodel.NodeAssembler,
panic("misuse")
}
// Check for dup keys; error if so.
_, exists := ma.w.m[k]
_, exists := ma.w.m.Get(k)
if exists {
return nil, datamodel.ErrRepeatedMapKey{Key: plainString(k)}
}
ma.state = maState_midValue
ma.w.t = append(ma.w.t, plainMap__Entry{k: plainString(k)})
ma.w.m.Put(k, &plainMap__Entry{k: plainString(k)})
// Make value assembler valid by giving it pointer back to whole 'ma'; yield it.
ma.va.ma = ma
return &ma.va, nil
Expand Down Expand Up @@ -325,7 +329,7 @@ func (plainMap__KeyAssembler) AssignFloat(float64) error {
func (mka *plainMap__KeyAssembler) AssignString(v string) error {
// Check for dup keys; error if so.
// (And, backtrack state to accepting keys again so we don't get eternally wedged here.)
_, exists := mka.ma.w.m[v]
_, exists := mka.ma.w.m.Get(v)
if exists {
mka.ma.state = maState_initial
mka.ma = nil // invalidate self to prevent further incorrect use.
Expand All @@ -335,8 +339,7 @@ func (mka *plainMap__KeyAssembler) AssignString(v string) error {
// we'll be doing map insertions after we get the value in hand.
// (There's no need to delegate to another assembler for the key type,
// because we're just at Data Model level here, which only regards plain strings.)
mka.ma.w.t = append(mka.ma.w.t, plainMap__Entry{})
mka.ma.w.t[len(mka.ma.w.t)-1].k = plainString(v)
mka.ma.w.m.Put(v, &plainMap__Entry{k: plainString(v)})
// Update parent assembler state: clear to proceed.
mka.ma.state = maState_expectValue
mka.ma = nil // invalidate self to prevent further incorrect use.
Expand Down Expand Up @@ -403,9 +406,10 @@ func (mva *plainMap__ValueAssembler) AssignLink(v datamodel.Link) error {
return mva.AssignNode(&vb)
}
func (mva *plainMap__ValueAssembler) AssignNode(v datamodel.Node) error {
l := len(mva.ma.w.t) - 1
mva.ma.w.t[l].v = v
mva.ma.w.m[string(mva.ma.w.t[l].k)] = v
itr := mva.ma.w.m.Iterator()
itr.Last()
val := itr.Value().(*plainMap__Entry)
val.v = v
mva.ma.state = maState_initial
mva.ma = nil // invalidate self to prevent further incorrect use.
return nil
Expand Down
2 changes: 0 additions & 2 deletions storage/benchmarks/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZx
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
Expand Down
129 changes: 0 additions & 129 deletions traversal/amendAny.go

This file was deleted.

Loading

0 comments on commit 3d4d63c

Please sign in to comment.