github.com/ethersphere/bee/v2@v2.2.0/pkg/manifest/mantaray/persist.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package mantaray
     6  
     7  import (
     8  	"context"
     9  	"errors"
    10  
    11  	"golang.org/x/sync/errgroup"
    12  )
    13  
    14  var (
    15  	// ErrNoSaver saver interface not given
    16  	ErrNoSaver = errors.New("Node is not persisted but no saver")
    17  	// ErrNoLoader saver interface not given
    18  	ErrNoLoader = errors.New("Node is reference but no loader")
    19  )
    20  
    21  // Loader defines a generic interface to retrieve nodes
    22  // from a persistent storage
    23  // for read only operations only
    24  type Loader interface {
    25  	Load(ctx context.Context, reference []byte) (data []byte, err error)
    26  }
    27  
    28  // Saver defines a generic interface to persist nodes
    29  // for write operations
    30  type Saver interface {
    31  	Save(ctx context.Context, data []byte) (reference []byte, err error)
    32  }
    33  
    34  // LoadSaver is a composite interface of Loader and Saver
    35  // it is meant to be implemented as thin wrappers around persistent storage like Swarm
    36  type LoadSaver interface {
    37  	Loader
    38  	Saver
    39  }
    40  
    41  func (n *Node) load(ctx context.Context, l Loader) error {
    42  	if n == nil || n.ref == nil {
    43  		return nil
    44  	}
    45  	if l == nil {
    46  		return ErrNoLoader
    47  	}
    48  	b, err := l.Load(ctx, n.ref)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	return n.UnmarshalBinary(b)
    53  }
    54  
    55  // Save persists a trie recursively  traversing the nodes
    56  func (n *Node) Save(ctx context.Context, s Saver) error {
    57  	if s == nil {
    58  		return ErrNoSaver
    59  	}
    60  	return n.save(ctx, s)
    61  }
    62  
    63  func (n *Node) save(ctx context.Context, s Saver) error {
    64  	if n != nil && n.ref != nil {
    65  		return nil
    66  	}
    67  	select {
    68  	case <-ctx.Done():
    69  		return ctx.Err()
    70  	default:
    71  	}
    72  	eg, ectx := errgroup.WithContext(ctx)
    73  	for _, f := range n.forks {
    74  		f := f
    75  		eg.Go(func() error {
    76  			return f.Node.save(ectx, s)
    77  		})
    78  	}
    79  	if err := eg.Wait(); err != nil {
    80  		return err
    81  	}
    82  	bytes, err := n.MarshalBinary()
    83  	if err != nil {
    84  		return err
    85  	}
    86  	n.ref, err = s.Save(ctx, bytes)
    87  	if err != nil {
    88  		return err
    89  	}
    90  	n.forks = nil
    91  	return nil
    92  }