github.com/alanchchen/go-ethereum@v1.6.6-0.20170601190819-6171d01b1195/swarm/storage/netstore.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package storage 18 19 import ( 20 "fmt" 21 "path/filepath" 22 "sync" 23 "time" 24 25 "github.com/ethereum/go-ethereum/log" 26 ) 27 28 /* 29 NetStore is a cloud storage access abstaction layer for swarm 30 it contains the shared logic of network served chunk store/retrieval requests 31 both local (coming from DPA api) and remote (coming from peers via bzz protocol) 32 it implements the ChunkStore interface and embeds LocalStore 33 34 It is called by the bzz protocol instances via Depo (the store/retrieve request handler) 35 a protocol instance is running on each peer, so this is heavily parallelised. 36 NetStore falls back to a backend (CloudStorage interface) 37 implemented by bzz/network/forwarder. forwarder or IPFS or IPΞS 38 */ 39 type NetStore struct { 40 hashfunc Hasher 41 localStore *LocalStore 42 cloud CloudStore 43 lock sync.Mutex 44 } 45 46 // backend engine for cloud store 47 // It can be aggregate dispatching to several parallel implementations: 48 // bzz/network/forwarder. forwarder or IPFS or IPΞS 49 type CloudStore interface { 50 Store(*Chunk) 51 Deliver(*Chunk) 52 Retrieve(*Chunk) 53 } 54 55 type StoreParams struct { 56 ChunkDbPath string 57 DbCapacity uint64 58 CacheCapacity uint 59 Radius int 60 } 61 62 func NewStoreParams(path string) (self *StoreParams) { 63 return &StoreParams{ 64 ChunkDbPath: filepath.Join(path, "chunks"), 65 DbCapacity: defaultDbCapacity, 66 CacheCapacity: defaultCacheCapacity, 67 Radius: defaultRadius, 68 } 69 } 70 71 // netstore contructor, takes path argument that is used to initialise dbStore, 72 // the persistent (disk) storage component of LocalStore 73 // the second argument is the hive, the connection/logistics manager for the node 74 func NewNetStore(hash Hasher, lstore *LocalStore, cloud CloudStore, params *StoreParams) *NetStore { 75 return &NetStore{ 76 hashfunc: hash, 77 localStore: lstore, 78 cloud: cloud, 79 } 80 } 81 82 const ( 83 // maximum number of peers that a retrieved message is delivered to 84 requesterCount = 3 85 ) 86 87 var ( 88 // timeout interval before retrieval is timed out 89 searchTimeout = 3 * time.Second 90 ) 91 92 // store logic common to local and network chunk store requests 93 // ~ unsafe put in localdb no check if exists no extra copy no hash validation 94 // the chunk is forced to propagate (Cloud.Store) even if locally found! 95 // caller needs to make sure if that is wanted 96 func (self *NetStore) Put(entry *Chunk) { 97 self.localStore.Put(entry) 98 99 // handle deliveries 100 if entry.Req != nil { 101 log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v hit existing request...delivering", entry.Key.Log())) 102 // closing C signals to other routines (local requests) 103 // that the chunk is has been retrieved 104 close(entry.Req.C) 105 // deliver the chunk to requesters upstream 106 go self.cloud.Deliver(entry) 107 } else { 108 log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v stored locally", entry.Key.Log())) 109 // handle propagating store requests 110 // go self.cloud.Store(entry) 111 go self.cloud.Store(entry) 112 } 113 } 114 115 // retrieve logic common for local and network chunk retrieval requests 116 func (self *NetStore) Get(key Key) (*Chunk, error) { 117 var err error 118 chunk, err := self.localStore.Get(key) 119 if err == nil { 120 if chunk.Req == nil { 121 log.Trace(fmt.Sprintf("NetStore.Get: %v found locally", key)) 122 } else { 123 log.Trace(fmt.Sprintf("NetStore.Get: %v hit on an existing request", key)) 124 // no need to launch again 125 } 126 return chunk, err 127 } 128 // no data and no request status 129 log.Trace(fmt.Sprintf("NetStore.Get: %v not found locally. open new request", key)) 130 chunk = NewChunk(key, newRequestStatus(key)) 131 self.localStore.memStore.Put(chunk) 132 go self.cloud.Retrieve(chunk) 133 return chunk, nil 134 } 135 136 // Close netstore 137 func (self *NetStore) Close() { 138 return 139 }