Skip to content

Commit 9fd5cfc

Browse files
Update readme and some minor code rearranging.
1 parent 6436270 commit 9fd5cfc

File tree

3 files changed

+117
-24
lines changed

3 files changed

+117
-24
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ interface and the most expensive operation in CPU profiling is the interface
146146
method which in turn calls into runtime.assertI2T. We need generics.
147147

148148
#### Immutable B Tree
149-
A btree based on two principals, immutablability and concurrency. Somewhat slow for single value lookups and puts, it is very fast for bulk operations. A persister can be injected to make this index persistent.
149+
A btree based on two principals, immutablability and concurrency.
150+
Somewhat slow for single value lookups and puts, it is very fast for bulk operations.
151+
A persister can be injected to make this index persistent.
150152

151153
#### Ctrie
152154

btree/immutable/cacher.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import (
77
"github.com/Workiva/go-datastructures/futures"
88
)
99

10-
// cacher provides a convenient interface for retrieving,
11-
// storing, and caching nodes. This ensures that we don't have to constantly
10+
// cacher provides a convenient construct for retrieving,
11+
// storing, and caching nodes; basically wrapper persister with a caching layer.
12+
// This ensures that we don't have to constantly
1213
// run to the persister to fetch nodes we are using over and over again.
1314
// TODO: this should probably evict items from the cache if the cache gets
1415
// too full.
@@ -18,6 +19,21 @@ type cacher struct {
1819
persister Persister
1920
}
2021

22+
func (c *cacher) asyncLoadNode(t *Tr, key ID, completer chan interface{}) {
23+
n, err := c.loadNode(t, key)
24+
if err != nil {
25+
completer <- err
26+
return
27+
}
28+
29+
if n == nil {
30+
completer <- ErrNodeNotFound
31+
return
32+
}
33+
34+
completer <- n
35+
}
36+
2137
// clear deletes all items from the cache.
2238
func (c *cacher) clear() {
2339
c.lock.Lock()
@@ -53,7 +69,7 @@ func (c *cacher) loadNode(t *Tr, key ID) (*Node, error) {
5369
// if the cacher could not go to the persister or the node could not be found.
5470
// All found nodes are cached so subsequent calls should be faster than
5571
// the initial. This blocks until the node is loaded, but is also threadsafe.
56-
func (c *cacher) getNode(t *Tr, key ID, cache bool) (*Node, error) {
72+
func (c *cacher) getNode(t *Tr, key ID, useCache bool) (*Node, error) {
5773
if !cache {
5874
return c.loadNode(t, key)
5975
}
@@ -75,20 +91,7 @@ func (c *cacher) getNode(t *Tr, key ID, cache bool) (*Node, error) {
7591
c.cache[string(key)] = future
7692
c.lock.Unlock()
7793

78-
go func() {
79-
n, err := c.loadNode(t, key)
80-
if err != nil {
81-
completer <- err
82-
return
83-
}
84-
85-
if n == nil {
86-
completer <- ErrNodeNotFound
87-
return
88-
}
89-
90-
completer <- n
91-
}()
94+
go c.asyncLoadNode(t, key, completer)
9295

9396
ifc, err := future.GetResult()
9497
if err != nil {

btree/immutable/node_gen.go

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,19 @@ func (z Keys) MarshalMsg(b []byte) (o []byte, err error) {
112112
if z[xvk] == nil {
113113
o = msgp.AppendNil(o)
114114
} else {
115-
o, err = z[xvk].MarshalMsg(o)
115+
// map header, size 3
116+
// string "u"
117+
o = append(o, 0x83, 0xa1, 0x75)
118+
o = msgp.AppendBytes(o, []byte(z[xvk].UUID))
119+
// string "v"
120+
o = append(o, 0xa1, 0x76)
121+
o, err = msgp.AppendIntf(o, z[xvk].Value)
116122
if err != nil {
117123
return
118124
}
125+
// string "p"
126+
o = append(o, 0xa1, 0x70)
127+
o = msgp.AppendBytes(o, z[xvk].Payload)
119128
}
120129
}
121130
return
@@ -144,10 +153,46 @@ func (z *Keys) UnmarshalMsg(bts []byte) (o []byte, err error) {
144153
if (*z)[bzg] == nil {
145154
(*z)[bzg] = new(Key)
146155
}
147-
bts, err = (*z)[bzg].UnmarshalMsg(bts)
156+
var field []byte
157+
_ = field
158+
var isz uint32
159+
isz, bts, err = msgp.ReadMapHeaderBytes(bts)
148160
if err != nil {
149161
return
150162
}
163+
for isz > 0 {
164+
isz--
165+
field, bts, err = msgp.ReadMapKeyZC(bts)
166+
if err != nil {
167+
return
168+
}
169+
switch msgp.UnsafeString(field) {
170+
case "u":
171+
{
172+
var tmp []byte
173+
tmp, bts, err = msgp.ReadBytesBytes(bts, []byte((*z)[bzg].UUID))
174+
(*z)[bzg].UUID = ID(tmp)
175+
}
176+
if err != nil {
177+
return
178+
}
179+
case "v":
180+
(*z)[bzg].Value, bts, err = msgp.ReadIntfBytes(bts)
181+
if err != nil {
182+
return
183+
}
184+
case "p":
185+
(*z)[bzg].Payload, bts, err = msgp.ReadBytesBytes(bts, (*z)[bzg].Payload)
186+
if err != nil {
187+
return
188+
}
189+
default:
190+
bts, err = msgp.Skip(bts)
191+
if err != nil {
192+
return
193+
}
194+
}
195+
}
151196
}
152197
}
153198
o = bts
@@ -160,7 +205,7 @@ func (z Keys) Msgsize() (s int) {
160205
if z[bai] == nil {
161206
s += msgp.NilSize
162207
} else {
163-
s += z[bai].Msgsize()
208+
s += 1 + 2 + msgp.BytesPrefixSize + len([]byte(z[bai].UUID)) + 2 + msgp.GuessSize(z[bai].Value) + 2 + msgp.BytesPrefixSize + len(z[bai].Payload)
164209
}
165210
}
166211
return
@@ -192,10 +237,19 @@ func (z *Node) MarshalMsg(b []byte) (o []byte, err error) {
192237
if z.ChildKeys[ajw] == nil {
193238
o = msgp.AppendNil(o)
194239
} else {
195-
o, err = z.ChildKeys[ajw].MarshalMsg(o)
240+
// map header, size 3
241+
// string "u"
242+
o = append(o, 0x83, 0xa1, 0x75)
243+
o = msgp.AppendBytes(o, []byte(z.ChildKeys[ajw].UUID))
244+
// string "v"
245+
o = append(o, 0xa1, 0x76)
246+
o, err = msgp.AppendIntf(o, z.ChildKeys[ajw].Value)
196247
if err != nil {
197248
return
198249
}
250+
// string "p"
251+
o = append(o, 0xa1, 0x70)
252+
o = msgp.AppendBytes(o, z.ChildKeys[ajw].Payload)
199253
}
200254
}
201255
return
@@ -270,10 +324,44 @@ func (z *Node) UnmarshalMsg(bts []byte) (o []byte, err error) {
270324
if z.ChildKeys[ajw] == nil {
271325
z.ChildKeys[ajw] = new(Key)
272326
}
273-
bts, err = z.ChildKeys[ajw].UnmarshalMsg(bts)
327+
var isz uint32
328+
isz, bts, err = msgp.ReadMapHeaderBytes(bts)
274329
if err != nil {
275330
return
276331
}
332+
for isz > 0 {
333+
isz--
334+
field, bts, err = msgp.ReadMapKeyZC(bts)
335+
if err != nil {
336+
return
337+
}
338+
switch msgp.UnsafeString(field) {
339+
case "u":
340+
{
341+
var tmp []byte
342+
tmp, bts, err = msgp.ReadBytesBytes(bts, []byte(z.ChildKeys[ajw].UUID))
343+
z.ChildKeys[ajw].UUID = ID(tmp)
344+
}
345+
if err != nil {
346+
return
347+
}
348+
case "v":
349+
z.ChildKeys[ajw].Value, bts, err = msgp.ReadIntfBytes(bts)
350+
if err != nil {
351+
return
352+
}
353+
case "p":
354+
z.ChildKeys[ajw].Payload, bts, err = msgp.ReadBytesBytes(bts, z.ChildKeys[ajw].Payload)
355+
if err != nil {
356+
return
357+
}
358+
default:
359+
bts, err = msgp.Skip(bts)
360+
if err != nil {
361+
return
362+
}
363+
}
364+
}
277365
}
278366
}
279367
default:
@@ -297,7 +385,7 @@ func (z *Node) Msgsize() (s int) {
297385
if z.ChildKeys[ajw] == nil {
298386
s += msgp.NilSize
299387
} else {
300-
s += z.ChildKeys[ajw].Msgsize()
388+
s += 1 + 2 + msgp.BytesPrefixSize + len([]byte(z.ChildKeys[ajw].UUID)) + 2 + msgp.GuessSize(z.ChildKeys[ajw].Value) + 2 + msgp.BytesPrefixSize + len(z.ChildKeys[ajw].Payload)
301389
}
302390
}
303391
return

0 commit comments

Comments
 (0)