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() {}