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 }