Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit a1107a8

Browse files
committed
fix(directory): add unsharding logic for AddChild case
1 parent 06784ab commit a1107a8

File tree

1 file changed

+48
-17
lines changed

1 file changed

+48
-17
lines changed

io/directory.go

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -430,29 +430,42 @@ func (d *HAMTDirectory) removeFromSizeChange(name string, linkCid cid.Cid) {
430430
d.sizeChange -= estimatedLinkSize(name, linkCid)
431431
}
432432

433-
// FIXME: Will be extended later to the `AddEntry` case.
434-
func (d *HAMTDirectory) needsToSwitchToBasicDir(ctx context.Context, nameToRemove string) (switchToBasic bool, err error) {
433+
// Evaluate a switch from HAMTDirectory to BasicDirectory in case the size will
434+
// go above the threshold when we are adding or removing an entry.
435+
// In both the add/remove operations any old name will be removed, and for the
436+
// add operation in particular a new entry will be added under that name (otherwise
437+
// nodeToAdd is nil). We compute both (potential) future subtraction and
438+
// addition to the size change.
439+
func (d *HAMTDirectory) needsToSwitchToBasicDir(ctx context.Context, name string, nodeToAdd ipld.Node) (switchToBasic bool, err error) {
435440
if HAMTShardingSize == 0 { // Option disabled.
436441
return false, nil
437442
}
438443

439-
entryToRemove, err := d.shard.Find(ctx, nameToRemove)
440-
if err == os.ErrNotExist {
441-
// Nothing to remove, no point in evaluating a switch.
442-
return false, nil
443-
} else if err != nil {
444-
return false, err
444+
operationSizeChange := 0
445+
446+
// Find if there is an old entry under that name that will be overwritten
447+
// (AddEntry) or flat out removed (RemoveEntry).
448+
entryToRemove, err := d.shard.Find(ctx, name)
449+
if err != os.ErrNotExist {
450+
if err != nil {
451+
return false, err
452+
}
453+
operationSizeChange -= estimatedLinkSize(name, entryToRemove.Cid)
454+
}
455+
456+
// For the AddEntry case compute the size addition of the new entry.
457+
if nodeToAdd != nil {
458+
operationSizeChange += estimatedLinkSize(name, nodeToAdd.Cid())
445459
}
446-
sizeToRemove := estimatedLinkSize(nameToRemove, entryToRemove.Cid)
447460

448-
if d.sizeChange-sizeToRemove >= 0 {
461+
if d.sizeChange+operationSizeChange >= 0 {
449462
// We won't have reduced the HAMT net size.
450463
return false, nil
451464
}
452465

453466
// We have reduced the directory size, check if went below the
454467
// HAMTShardingSize threshold to trigger a switch.
455-
belowThreshold, err := d.sizeBelowThreshold(ctx, -sizeToRemove)
468+
belowThreshold, err := d.sizeBelowThreshold(ctx, operationSizeChange)
456469
if err != nil {
457470
return false, err
458471
}
@@ -511,7 +524,29 @@ var _ Directory = (*UpgradeableDirectory)(nil)
511524
// AddChild implements the `Directory` interface. We check when adding new entries
512525
// if we should switch to HAMTDirectory according to global option(s).
513526
func (d *UpgradeableDirectory) AddChild(ctx context.Context, name string, nd ipld.Node) error {
514-
err := d.Directory.AddChild(ctx, name, nd)
527+
hamtDir, ok := d.Directory.(*HAMTDirectory)
528+
if ok {
529+
// We evaluate a switch in the HAMTDirectory case even for an AddChild
530+
// as it may overwrite an existing entry and end up actually reducing
531+
// the directory size.
532+
switchToBasic, err := hamtDir.needsToSwitchToBasicDir(ctx, name, nd)
533+
if err != nil {
534+
return err
535+
}
536+
537+
if switchToBasic {
538+
basicDir, err := hamtDir.switchToBasic(ctx)
539+
if err != nil {
540+
return err
541+
}
542+
d.Directory = basicDir
543+
}
544+
return d.Directory.AddChild(ctx, name, nd)
545+
}
546+
547+
// BasicDirectory
548+
basicDir := d.Directory.(*BasicDirectory)
549+
err := basicDir.AddChild(ctx, name, nd)
515550
if err != nil {
516551
return err
517552
}
@@ -520,10 +555,6 @@ func (d *UpgradeableDirectory) AddChild(ctx context.Context, name string, nd ipl
520555
if HAMTShardingSize == 0 {
521556
return nil
522557
}
523-
basicDir, ok := d.Directory.(*BasicDirectory)
524-
if !ok {
525-
return nil
526-
}
527558
if basicDir.estimatedSize >= HAMTShardingSize {
528559
// Ideally to minimize performance we should check if this last
529560
// `AddChild` call would bring the directory size over the threshold
@@ -562,7 +593,7 @@ func (d *UpgradeableDirectory) getDagService() ipld.DAGService {
562593
func (d *UpgradeableDirectory) RemoveChild(ctx context.Context, name string) error {
563594
hamtDir, ok := d.Directory.(*HAMTDirectory)
564595
if ok {
565-
switchToBasic, err := hamtDir.needsToSwitchToBasicDir(ctx, name)
596+
switchToBasic, err := hamtDir.needsToSwitchToBasicDir(ctx, name, nil)
566597
if err != nil {
567598
return err
568599
}

0 commit comments

Comments
 (0)