@@ -39,13 +39,20 @@ const (
39
39
HashMurmur3 uint64 = 0x22
40
40
)
41
41
42
+ func (ds * Shard ) isValueNode () bool {
43
+ if ds .key != "" && ds .val != nil {
44
+ return true
45
+ }
46
+ return false
47
+ }
48
+
42
49
// A Shard represents the HAMT. It should be initialized with NewShard().
43
50
type Shard struct {
44
51
nd * dag.ProtoNode
45
52
46
53
bitfield bitfield.Bitfield
47
54
48
- children []child
55
+ children []* Shard
49
56
50
57
tableSize int
51
58
tableSizeLg2 int
@@ -57,12 +64,10 @@ type Shard struct {
57
64
maxpadlen int
58
65
59
66
dserv ipld.DAGService
60
- }
61
67
62
- // child can either be another shard, or a leaf node value
63
- type child interface {
64
- Link () (* ipld.Link , error )
65
- Label () string
68
+ // leaf node
69
+ key string
70
+ val * ipld.Link
66
71
}
67
72
68
73
// NewShard creates a new, empty HAMT shard with the given size.
@@ -119,7 +124,7 @@ func NewHamtFromDag(dserv ipld.DAGService, nd ipld.Node) (*Shard, error) {
119
124
}
120
125
121
126
ds .nd = pbnd .Copy ().(* dag.ProtoNode )
122
- ds .children = make ([]child , len (pbnd .Links ()))
127
+ ds .children = make ([]* Shard , len (pbnd .Links ()))
123
128
ds .bitfield .SetBytes (fsn .Data ())
124
129
ds .hashFunc = fsn .HashType ()
125
130
ds .builder = ds .nd .CidBuilder ()
@@ -156,7 +161,7 @@ func (ds *Shard) Node() (ipld.Node, error) {
156
161
return nil , err
157
162
}
158
163
159
- err = out .AddRawLink (ds .linkNamePrefix (i )+ ch .Label () , clnk )
164
+ err = out .AddRawLink (ds .linkNamePrefix (i )+ ch .key , clnk )
160
165
if err != nil {
161
166
return nil , err
162
167
}
@@ -188,26 +193,14 @@ func (ds *Shard) Node() (ipld.Node, error) {
188
193
return out , nil
189
194
}
190
195
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
- }
196
+ func (ds * Shard ) makeShardValue (lnk * ipld.Link ) * Shard {
197
+ lnk2 := * lnk
198
+ s , _ := makeShard (ds .dserv , ds .tableSize )
200
199
201
- func (sv * shardValue ) Label () string {
202
- return sv .key
203
- }
200
+ s .key = lnk .Name [ds .maxpadlen :]
201
+ s .val = & lnk2
204
202
205
- func (ds * Shard ) makeShardValue (lnk * ipld.Link ) * shardValue {
206
- lnk2 := * lnk
207
- return & shardValue {
208
- key : lnk .Name [ds .maxpadlen :],
209
- val : & lnk2 ,
210
- }
203
+ return s
211
204
}
212
205
213
206
func hash (val []byte ) []byte {
@@ -216,12 +209,6 @@ func hash(val []byte) []byte {
216
209
return h .Sum (nil )
217
210
}
218
211
219
- // Label for Shards is the empty string, this is used to differentiate them from
220
- // value entries
221
- func (ds * Shard ) Label () string {
222
- return ""
223
- }
224
-
225
212
// Set sets 'name' = nd in the HAMT
226
213
func (ds * Shard ) Set (ctx context.Context , name string , nd ipld.Node ) error {
227
214
hv := & hashBits {b : hash ([]byte (name ))}
@@ -250,7 +237,7 @@ func (ds *Shard) Find(ctx context.Context, name string) (*ipld.Link, error) {
250
237
hv := & hashBits {b : hash ([]byte (name ))}
251
238
252
239
var out * ipld.Link
253
- err := ds .getValue (ctx , hv , name , func (sv * shardValue ) error {
240
+ err := ds .getValue (ctx , hv , name , func (sv * Shard ) error {
254
241
out = sv .val
255
242
return nil
256
243
})
@@ -282,7 +269,7 @@ func (ds *Shard) childLinkType(lnk *ipld.Link) (linkType, error) {
282
269
// getChild returns the i'th child of this shard. If it is cached in the
283
270
// children array, it will return it from there. Otherwise, it loads the child
284
271
// node from disk.
285
- func (ds * Shard ) getChild (ctx context.Context , i int ) (child , error ) {
272
+ func (ds * Shard ) getChild (ctx context.Context , i int ) (* Shard , error ) {
286
273
if i >= len (ds .children ) || i < 0 {
287
274
return nil , fmt .Errorf ("invalid index passed to getChild (likely corrupt bitfield)" )
288
275
}
@@ -301,14 +288,14 @@ func (ds *Shard) getChild(ctx context.Context, i int) (child, error) {
301
288
302
289
// loadChild reads the i'th child node of this shard from disk and returns it
303
290
// as a 'child' interface
304
- func (ds * Shard ) loadChild (ctx context.Context , i int ) (child , error ) {
291
+ func (ds * Shard ) loadChild (ctx context.Context , i int ) (* Shard , error ) {
305
292
lnk := ds .nd .Links ()[i ]
306
293
lnkLinkType , err := ds .childLinkType (lnk )
307
294
if err != nil {
308
295
return nil , err
309
296
}
310
297
311
- var c child
298
+ var c * Shard
312
299
if lnkLinkType == shardLink {
313
300
nd , err := lnk .GetNode (ctx , ds .dserv )
314
301
if err != nil {
@@ -328,12 +315,16 @@ func (ds *Shard) loadChild(ctx context.Context, i int) (child, error) {
328
315
return c , nil
329
316
}
330
317
331
- func (ds * Shard ) setChild (i int , c child ) {
318
+ func (ds * Shard ) setChild (i int , c * Shard ) {
332
319
ds .children [i ] = c
333
320
}
334
321
335
322
// Link returns a merklelink to this shard node
336
323
func (ds * Shard ) Link () (* ipld.Link , error ) {
324
+ if ds .isValueNode () {
325
+ return ds .val , nil
326
+ }
327
+
337
328
nd , err := ds .Node ()
338
329
if err != nil {
339
330
return nil , err
@@ -356,12 +347,12 @@ func (ds *Shard) insertChild(idx int, key string, lnk *ipld.Link) error {
356
347
ds .bitfield .SetBit (idx )
357
348
358
349
lnk .Name = ds .linkNamePrefix (idx ) + key
359
- sv := & shardValue {
350
+ sv := & Shard {
360
351
key : key ,
361
352
val : lnk ,
362
353
}
363
354
364
- ds .children = append (ds .children [:i ], append ([]child {sv }, ds .children [i :]... )... )
355
+ ds .children = append (ds .children [:i ], append ([]* Shard {sv }, ds .children [i :]... )... )
365
356
ds .nd .SetLinks (append (ds .nd .Links ()[:i ], append ([]* ipld.Link {nil }, ds .nd .Links ()[i :]... )... ))
366
357
return nil
367
358
}
@@ -380,7 +371,7 @@ func (ds *Shard) rmChild(i int) error {
380
371
return nil
381
372
}
382
373
383
- func (ds * Shard ) getValue (ctx context.Context , hv * hashBits , key string , cb func (* shardValue ) error ) error {
374
+ func (ds * Shard ) getValue (ctx context.Context , hv * hashBits , key string , cb func (* Shard ) error ) error {
384
375
idx := hv .Next (ds .tableSizeLg2 )
385
376
if ds .bitfield .Bit (int (idx )) {
386
377
cindex := ds .indexForBitPos (idx )
@@ -390,13 +381,12 @@ func (ds *Shard) getValue(ctx context.Context, hv *hashBits, key string, cb func
390
381
return err
391
382
}
392
383
393
- switch child := child .(type ) {
394
- case * Shard :
395
- return child .getValue (ctx , hv , key , cb )
396
- case * shardValue :
384
+ if child .isValueNode () {
397
385
if child .key == key {
398
386
return cb (child )
399
387
}
388
+ } else {
389
+ return child .getValue (ctx , hv , key , cb )
400
390
}
401
391
}
402
392
@@ -408,7 +398,7 @@ func (ds *Shard) EnumLinks(ctx context.Context) ([]*ipld.Link, error) {
408
398
var links []* ipld.Link
409
399
var setlk sync.Mutex
410
400
411
- getLinks := makeAsyncTrieGetLinks (ds .dserv , func (sv * shardValue ) error {
401
+ getLinks := makeAsyncTrieGetLinks (ds .dserv , func (sv * Shard ) error {
412
402
lnk := sv .val
413
403
lnk .Name = sv .key
414
404
setlk .Lock ()
@@ -425,7 +415,7 @@ func (ds *Shard) EnumLinks(ctx context.Context) ([]*ipld.Link, error) {
425
415
426
416
// ForEachLink walks the Shard and calls the given function.
427
417
func (ds * Shard ) ForEachLink (ctx context.Context , f func (* ipld.Link ) error ) error {
428
- return ds .walkTrie (ctx , func (sv * shardValue ) error {
418
+ return ds .walkTrie (ctx , func (sv * Shard ) error {
429
419
lnk := sv .val
430
420
lnk .Name = sv .key
431
421
@@ -436,7 +426,7 @@ func (ds *Shard) ForEachLink(ctx context.Context, f func(*ipld.Link) error) erro
436
426
// makeAsyncTrieGetLinks builds a getLinks function that can be used with EnumerateChildrenAsync
437
427
// to iterate a HAMT shard. It takes an IPLD Dag Service to fetch nodes, and a call back that will get called
438
428
// 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 {
429
+ func makeAsyncTrieGetLinks (dagService ipld.DAGService , onShardValue func (shard * Shard ) error ) dag.GetLinks {
440
430
441
431
return func (ctx context.Context , currentCid cid.Cid ) ([]* ipld.Link , error ) {
442
432
node , err := dagService .Get (ctx , currentCid )
@@ -471,33 +461,28 @@ func makeAsyncTrieGetLinks(dagService ipld.DAGService, onShardValue func(*shardV
471
461
}
472
462
}
473
463
474
- func (ds * Shard ) walkTrie (ctx context.Context , cb func (* shardValue ) error ) error {
464
+ func (ds * Shard ) walkTrie (ctx context.Context , cb func (* Shard ) error ) error {
475
465
for idx := range ds .children {
476
466
c , err := ds .getChild (ctx , idx )
477
467
if err != nil {
478
468
return err
479
469
}
480
470
481
- switch c := c .(type ) {
482
- case * shardValue :
471
+ if c .isValueNode () {
483
472
if err := cb (c ); err != nil {
484
473
return err
485
474
}
486
-
487
- case * Shard :
475
+ } else {
488
476
if err := c .walkTrie (ctx , cb ); err != nil {
489
477
return err
490
478
}
491
- default :
492
- return fmt .Errorf ("unexpected child type: %#v" , c )
493
479
}
494
480
}
495
481
return nil
496
482
}
497
483
498
484
func (ds * Shard ) modifyValue (ctx context.Context , hv * hashBits , key string , val * ipld.Link ) error {
499
485
idx := hv .Next (ds .tableSizeLg2 )
500
-
501
486
if ! ds .bitfield .Bit (idx ) {
502
487
return ds .insertChild (idx , key , val )
503
488
}
@@ -509,34 +494,7 @@ func (ds *Shard) modifyValue(ctx context.Context, hv *hashBits, key string, val
509
494
return err
510
495
}
511
496
512
- switch child := child .(type ) {
513
- case * Shard :
514
- err := child .modifyValue (ctx , hv , key , val )
515
- if err != nil {
516
- return err
517
- }
518
-
519
- if val == nil {
520
- switch len (child .children ) {
521
- case 0 :
522
- // empty sub-shard, prune it
523
- // Note: this shouldnt normally ever happen
524
- // in the event of another implementation creates flawed
525
- // structures, this will help to normalize them.
526
- ds .bitfield .UnsetBit (idx )
527
- return ds .rmChild (cindex )
528
- 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
- }
534
- return nil
535
- }
536
- }
537
-
538
- return nil
539
- case * shardValue :
497
+ if child .isValueNode () {
540
498
if child .key == key {
541
499
// value modification
542
500
if val == nil {
@@ -575,8 +533,30 @@ func (ds *Shard) modifyValue(ctx context.Context, hv *hashBits, key string, val
575
533
576
534
ds .setChild (cindex , ns )
577
535
return nil
578
- default :
579
- return fmt .Errorf ("unexpected type for child: %#v" , child )
536
+ } else {
537
+ err := child .modifyValue (ctx , hv , key , val )
538
+ if err != nil {
539
+ return err
540
+ }
541
+
542
+ if val == nil {
543
+ switch len (child .children ) {
544
+ case 0 :
545
+ // empty sub-shard, prune it
546
+ // Note: this shouldnt normally ever happen
547
+ // in the event of another implementation creates flawed
548
+ // structures, this will help to normalize them.
549
+ ds .bitfield .UnsetBit (idx )
550
+ return ds .rmChild (cindex )
551
+ case 1 :
552
+ nchild := child .children [0 ]
553
+ // sub-shard with a single value element, collapse it
554
+ ds .setChild (cindex , nchild )
555
+ return nil
556
+ }
557
+ }
558
+
559
+ return nil
580
560
}
581
561
}
582
562
0 commit comments