github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/swarm/storage/netstore.go (about)

     1  // Copyright 2016 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package storage
    18  
    19  import (
    20  	"fmt"
    21  	"path/filepath"
    22  	"time"
    23  
    24  	"github.com/SmartMeshFoundation/Spectrum/log"
    25  )
    26  
    27  /*
    28  NetStore is a cloud storage access abstaction layer for swarm
    29  it contains the shared logic of network served chunk store/retrieval requests
    30  both local (coming from DPA api) and remote (coming from peers via bzz protocol)
    31  it implements the ChunkStore interface and embeds LocalStore
    32  
    33  It is called by the bzz protocol instances via Depo (the store/retrieve request handler)
    34  a protocol instance is running on each peer, so this is heavily parallelised.
    35  NetStore falls back to a backend (CloudStorage interface)
    36  implemented by bzz/network/forwarder. forwarder or IPFS or IPΞS
    37  */
    38  type NetStore struct {
    39  	hashfunc   SwarmHasher
    40  	localStore *LocalStore
    41  	cloud      CloudStore
    42  }
    43  
    44  // backend engine for cloud store
    45  // It can be aggregate dispatching to several parallel implementations:
    46  // bzz/network/forwarder. forwarder or IPFS or IPΞS
    47  type CloudStore interface {
    48  	Store(*Chunk)
    49  	Deliver(*Chunk)
    50  	Retrieve(*Chunk)
    51  }
    52  
    53  type StoreParams struct {
    54  	ChunkDbPath   string
    55  	DbCapacity    uint64
    56  	CacheCapacity uint
    57  	Radius        int
    58  }
    59  
    60  //create params with default values
    61  func NewDefaultStoreParams() (self *StoreParams) {
    62  	return &StoreParams{
    63  		DbCapacity:    defaultDbCapacity,
    64  		CacheCapacity: defaultCacheCapacity,
    65  		Radius:        defaultRadius,
    66  	}
    67  }
    68  
    69  //this can only finally be set after all config options (file, cmd line, env vars)
    70  //have been evaluated
    71  func (self *StoreParams) Init(path string) {
    72  	self.ChunkDbPath = filepath.Join(path, "chunks")
    73  }
    74  
    75  // netstore contructor, takes path argument that is used to initialise dbStore,
    76  // the persistent (disk) storage component of LocalStore
    77  // the second argument is the hive, the connection/logistics manager for the node
    78  func NewNetStore(hash SwarmHasher, lstore *LocalStore, cloud CloudStore, params *StoreParams) *NetStore {
    79  	return &NetStore{
    80  		hashfunc:   hash,
    81  		localStore: lstore,
    82  		cloud:      cloud,
    83  	}
    84  }
    85  
    86  const (
    87  	// maximum number of peers that a retrieved message is delivered to
    88  	requesterCount = 3
    89  )
    90  
    91  var (
    92  	// timeout interval before retrieval is timed out
    93  	searchTimeout = 3 * time.Second
    94  )
    95  
    96  // store logic common to local and network chunk store requests
    97  // ~ unsafe put in localdb no check if exists no extra copy no hash validation
    98  // the chunk is forced to propagate (Cloud.Store) even if locally found!
    99  // caller needs to make sure if that is wanted
   100  func (self *NetStore) Put(entry *Chunk) {
   101  	self.localStore.Put(entry)
   102  
   103  	// handle deliveries
   104  	if entry.Req != nil {
   105  		log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v hit existing request...delivering", entry.Key.Log()))
   106  		// closing C signals to other routines (local requests)
   107  		// that the chunk is has been retrieved
   108  		close(entry.Req.C)
   109  		// deliver the chunk to requesters upstream
   110  		go self.cloud.Deliver(entry)
   111  	} else {
   112  		log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v stored locally", entry.Key.Log()))
   113  		// handle propagating store requests
   114  		// go self.cloud.Store(entry)
   115  		go self.cloud.Store(entry)
   116  	}
   117  }
   118  
   119  // retrieve logic common for local and network chunk retrieval requests
   120  func (self *NetStore) Get(key Key) (*Chunk, error) {
   121  	var err error
   122  	chunk, err := self.localStore.Get(key)
   123  	if err == nil {
   124  		if chunk.Req == nil {
   125  			log.Trace(fmt.Sprintf("NetStore.Get: %v found locally", key))
   126  		} else {
   127  			log.Trace(fmt.Sprintf("NetStore.Get: %v hit on an existing request", key))
   128  			// no need to launch again
   129  		}
   130  		return chunk, err
   131  	}
   132  	// no data and no request status
   133  	log.Trace(fmt.Sprintf("NetStore.Get: %v not found locally. open new request", key))
   134  	chunk = NewChunk(key, newRequestStatus(key))
   135  	self.localStore.memStore.Put(chunk)
   136  	go self.cloud.Retrieve(chunk)
   137  	return chunk, nil
   138  }
   139  
   140  // Close netstore
   141  func (self *NetStore) Close() {}