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