@@ -39,13 +39,28 @@ const (
39
39
HashMurmur3 uint64 = 0x22
40
40
)
41
41
42
+ type nodeType int
43
+
44
+ const (
45
+ invalidNode nodeType = iota
46
+ shardNode
47
+ shardValueNode
48
+ )
49
+
50
+ func (ds * Shard ) nodeType () nodeType {
51
+ if ds .key != "" && ds .val != nil {
52
+ return shardValueNode
53
+ }
54
+ return shardNode
55
+ }
56
+
42
57
// A Shard represents the HAMT. It should be initialized with NewShard().
43
58
type Shard struct {
44
59
nd * dag.ProtoNode
45
60
46
61
bitfield bitfield.Bitfield
47
62
48
- children []child
63
+ children []* Shard
49
64
50
65
tableSize int
51
66
tableSizeLg2 int
@@ -57,12 +72,10 @@ type Shard struct {
57
72
maxpadlen int
58
73
59
74
dserv ipld.DAGService
60
- }
61
75
62
- // child can either be another shard, or a leaf node value
63
- type child interface {
64
- Link () (* ipld.Link , error )
65
- Label () string
76
+ // leaf node
77
+ key string
78
+ val * ipld.Link
66
79
}
67
80
68
81
// NewShard creates a new, empty HAMT shard with the given size.
@@ -119,7 +132,7 @@ func NewHamtFromDag(dserv ipld.DAGService, nd ipld.Node) (*Shard, error) {
119
132
}
120
133
121
134
ds .nd = pbnd .Copy ().(* dag.ProtoNode )
122
- ds .children = make ([]child , len (pbnd .Links ()))
135
+ ds .children = make ([]* Shard , len (pbnd .Links ()))
123
136
ds .bitfield .SetBytes (fsn .Data ())
124
137
ds .hashFunc = fsn .HashType ()
125
138
ds .builder = ds .nd .CidBuilder ()
@@ -188,23 +201,9 @@ func (ds *Shard) Node() (ipld.Node, error) {
188
201
return out , nil
189
202
}
190
203
191
- type shardValue struct {
192
- key string
193
- val * ipld.Link
194
- }
195
-
196
- // Link returns a link to this node
197
- func (sv * shardValue ) Link () (* ipld.Link , error ) {
198
- return sv .val , nil
199
- }
200
-
201
- func (sv * shardValue ) Label () string {
202
- return sv .key
203
- }
204
-
205
- func (ds * Shard ) makeShardValue (lnk * ipld.Link ) * shardValue {
204
+ func (ds * Shard ) makeShardValue (lnk * ipld.Link ) * Shard {
206
205
lnk2 := * lnk
207
- return & shardValue {
206
+ return & Shard {
208
207
key : lnk .Name [ds .maxpadlen :],
209
208
val : & lnk2 ,
210
209
}
@@ -219,6 +218,10 @@ func hash(val []byte) []byte {
219
218
// Label for Shards is the empty string, this is used to differentiate them from
220
219
// value entries
221
220
func (ds * Shard ) Label () string {
221
+ nodeType := ds .nodeType ()
222
+ if nodeType == shardValueNode {
223
+ return ds .key
224
+ }
222
225
return ""
223
226
}
224
227
@@ -250,7 +253,7 @@ func (ds *Shard) Find(ctx context.Context, name string) (*ipld.Link, error) {
250
253
hv := & hashBits {b : hash ([]byte (name ))}
251
254
252
255
var out * ipld.Link
253
- err := ds .getValue (ctx , hv , name , func (sv * shardValue ) error {
256
+ err := ds .getValue (ctx , hv , name , func (sv * Shard ) error {
254
257
out = sv .val
255
258
return nil
256
259
})
@@ -282,7 +285,7 @@ func (ds *Shard) childLinkType(lnk *ipld.Link) (linkType, error) {
282
285
// getChild returns the i'th child of this shard. If it is cached in the
283
286
// children array, it will return it from there. Otherwise, it loads the child
284
287
// node from disk.
285
- func (ds * Shard ) getChild (ctx context.Context , i int ) (child , error ) {
288
+ func (ds * Shard ) getChild (ctx context.Context , i int ) (* Shard , error ) {
286
289
if i >= len (ds .children ) || i < 0 {
287
290
return nil , fmt .Errorf ("invalid index passed to getChild (likely corrupt bitfield)" )
288
291
}
@@ -301,14 +304,14 @@ func (ds *Shard) getChild(ctx context.Context, i int) (child, error) {
301
304
302
305
// loadChild reads the i'th child node of this shard from disk and returns it
303
306
// as a 'child' interface
304
- func (ds * Shard ) loadChild (ctx context.Context , i int ) (child , error ) {
307
+ func (ds * Shard ) loadChild (ctx context.Context , i int ) (* Shard , error ) {
305
308
lnk := ds .nd .Links ()[i ]
306
309
lnkLinkType , err := ds .childLinkType (lnk )
307
310
if err != nil {
308
311
return nil , err
309
312
}
310
313
311
- var c child
314
+ var c * Shard
312
315
if lnkLinkType == shardLink {
313
316
nd , err := lnk .GetNode (ctx , ds .dserv )
314
317
if err != nil {
@@ -328,12 +331,17 @@ func (ds *Shard) loadChild(ctx context.Context, i int) (child, error) {
328
331
return c , nil
329
332
}
330
333
331
- func (ds * Shard ) setChild (i int , c child ) {
334
+ func (ds * Shard ) setChild (i int , c * Shard ) {
332
335
ds .children [i ] = c
333
336
}
334
337
335
338
// Link returns a merklelink to this shard node
336
339
func (ds * Shard ) Link () (* ipld.Link , error ) {
340
+ nodeType := ds .nodeType ()
341
+ if nodeType == shardValueNode {
342
+ return ds .val , nil
343
+ }
344
+
337
345
nd , err := ds .Node ()
338
346
if err != nil {
339
347
return nil , err
@@ -356,13 +364,13 @@ func (ds *Shard) insertChild(idx int, key string, lnk *ipld.Link) error {
356
364
ds .bitfield .SetBit (idx )
357
365
358
366
lnk .Name = ds .linkNamePrefix (idx ) + key
359
- sv := & shardValue {
367
+ sv := & Shard {
360
368
key : key ,
361
369
val : lnk ,
362
370
}
363
371
364
- ds .children = append (ds .children [:i ], append ([]child {sv }, ds .children [i :]... )... )
365
- ds .nd .SetLinks (append (ds .nd .Links ()[:i ], append ([]* ipld.Link {nil }, ds .nd .Links ()[i :]... )... ))
372
+ ds .children = append (ds .children [:i ], append ([]* Shard {sv }, ds .children [i :]... )... )
373
+ ds .nd .SetLinks (append (ds .nd .Links ()[:i ], append ([]* ipld.Link {lnk }, ds .nd .Links ()[i :]... )... ))
366
374
return nil
367
375
}
368
376
@@ -380,7 +388,7 @@ func (ds *Shard) rmChild(i int) error {
380
388
return nil
381
389
}
382
390
383
- func (ds * Shard ) getValue (ctx context.Context , hv * hashBits , key string , cb func (* shardValue ) error ) error {
391
+ func (ds * Shard ) getValue (ctx context.Context , hv * hashBits , key string , cb func (* Shard ) error ) error {
384
392
idx := hv .Next (ds .tableSizeLg2 )
385
393
if ds .bitfield .Bit (int (idx )) {
386
394
cindex := ds .indexForBitPos (idx )
@@ -390,10 +398,11 @@ func (ds *Shard) getValue(ctx context.Context, hv *hashBits, key string, cb func
390
398
return err
391
399
}
392
400
393
- switch child := child .(type ) {
394
- case * Shard :
401
+ childType := child .nodeType ()
402
+ switch childType {
403
+ case shardNode :
395
404
return child .getValue (ctx , hv , key , cb )
396
- case * shardValue :
405
+ case shardValueNode :
397
406
if child .key == key {
398
407
return cb (child )
399
408
}
@@ -408,7 +417,7 @@ func (ds *Shard) EnumLinks(ctx context.Context) ([]*ipld.Link, error) {
408
417
var links []* ipld.Link
409
418
var setlk sync.Mutex
410
419
411
- getLinks := makeAsyncTrieGetLinks (ds .dserv , func (sv * shardValue ) error {
420
+ getLinks := makeAsyncTrieGetLinks (ds .dserv , func (sv * Shard ) error {
412
421
lnk := sv .val
413
422
lnk .Name = sv .key
414
423
setlk .Lock ()
@@ -425,7 +434,7 @@ func (ds *Shard) EnumLinks(ctx context.Context) ([]*ipld.Link, error) {
425
434
426
435
// ForEachLink walks the Shard and calls the given function.
427
436
func (ds * Shard ) ForEachLink (ctx context.Context , f func (* ipld.Link ) error ) error {
428
- return ds .walkTrie (ctx , func (sv * shardValue ) error {
437
+ return ds .walkTrie (ctx , func (sv * Shard ) error {
429
438
lnk := sv .val
430
439
lnk .Name = sv .key
431
440
@@ -436,7 +445,7 @@ func (ds *Shard) ForEachLink(ctx context.Context, f func(*ipld.Link) error) erro
436
445
// makeAsyncTrieGetLinks builds a getLinks function that can be used with EnumerateChildrenAsync
437
446
// to iterate a HAMT shard. It takes an IPLD Dag Service to fetch nodes, and a call back that will get called
438
447
// on all links to leaf nodes in a HAMT tree, so they can be collected for an EnumLinks operation
439
- func makeAsyncTrieGetLinks (dagService ipld.DAGService , onShardValue func (* shardValue ) error ) dag.GetLinks {
448
+ func makeAsyncTrieGetLinks (dagService ipld.DAGService , onShardValue func (shard * Shard ) error ) dag.GetLinks {
440
449
441
450
return func (ctx context.Context , currentCid cid.Cid ) ([]* ipld.Link , error ) {
442
451
node , err := dagService .Get (ctx , currentCid )
@@ -471,20 +480,22 @@ func makeAsyncTrieGetLinks(dagService ipld.DAGService, onShardValue func(*shardV
471
480
}
472
481
}
473
482
474
- func (ds * Shard ) walkTrie (ctx context.Context , cb func (* shardValue ) error ) error {
483
+ func (ds * Shard ) walkTrie (ctx context.Context , cb func (* Shard ) error ) error {
475
484
for idx := range ds .children {
476
485
c , err := ds .getChild (ctx , idx )
477
486
if err != nil {
478
487
return err
479
488
}
480
489
481
- switch c := c .(type ) {
482
- case * shardValue :
490
+ childType := c .nodeType ()
491
+
492
+ switch childType {
493
+ case shardValueNode :
483
494
if err := cb (c ); err != nil {
484
495
return err
485
496
}
486
497
487
- case * Shard :
498
+ case shardNode :
488
499
if err := c .walkTrie (ctx , cb ); err != nil {
489
500
return err
490
501
}
@@ -509,8 +520,10 @@ func (ds *Shard) modifyValue(ctx context.Context, hv *hashBits, key string, val
509
520
return err
510
521
}
511
522
512
- switch child := child .(type ) {
513
- case * Shard :
523
+ childType := child .nodeType ()
524
+
525
+ switch childType {
526
+ case shardNode :
514
527
err := child .modifyValue (ctx , hv , key , val )
515
528
if err != nil {
516
529
return err
@@ -526,17 +539,15 @@ func (ds *Shard) modifyValue(ctx context.Context, hv *hashBits, key string, val
526
539
ds .bitfield .UnsetBit (idx )
527
540
return ds .rmChild (cindex )
528
541
case 1 :
529
- nchild , ok := child .children [0 ].(* shardValue )
530
- if ok {
531
- // sub-shard with a single value element, collapse it
532
- ds .setChild (cindex , nchild )
533
- }
542
+ nchild := child .children [0 ]
543
+ // sub-shard with a single value element, collapse it
544
+ ds .setChild (cindex , nchild )
534
545
return nil
535
546
}
536
547
}
537
548
538
549
return nil
539
- case * shardValue :
550
+ case shardValueNode :
540
551
if child .key == key {
541
552
// value modification
542
553
if val == nil {
0 commit comments