github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/swarm/storage/netstore.go (about)

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