| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | // Copyright 2016 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package storage | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/log" | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							|  |  |  | NetStore is a cloud storage access abstaction layer for swarm | 
					
						
							|  |  |  | it contains the shared logic of network served chunk store/retrieval requests | 
					
						
							|  |  |  | both local (coming from DPA api) and remote (coming from peers via bzz protocol) | 
					
						
							|  |  |  | it implements the ChunkStore interface and embeds LocalStore | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It is called by the bzz protocol instances via Depo (the store/retrieve request handler) | 
					
						
							|  |  |  | a protocol instance is running on each peer, so this is heavily parallelised. | 
					
						
							|  |  |  | NetStore falls back to a backend (CloudStorage interface) | 
					
						
							|  |  |  | implemented by bzz/network/forwarder. forwarder or IPFS or IPΞS | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | type NetStore struct { | 
					
						
							| 
									
										
										
										
											2017-09-22 01:52:51 +05:30
										 |  |  | 	hashfunc   SwarmHasher | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	localStore *LocalStore | 
					
						
							|  |  |  | 	cloud      CloudStore | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // backend engine for cloud store | 
					
						
							|  |  |  | // It can be aggregate dispatching to several parallel implementations: | 
					
						
							|  |  |  | // bzz/network/forwarder. forwarder or IPFS or IPΞS | 
					
						
							|  |  |  | type CloudStore interface { | 
					
						
							|  |  |  | 	Store(*Chunk) | 
					
						
							|  |  |  | 	Deliver(*Chunk) | 
					
						
							|  |  |  | 	Retrieve(*Chunk) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type StoreParams struct { | 
					
						
							|  |  |  | 	ChunkDbPath   string | 
					
						
							|  |  |  | 	DbCapacity    uint64 | 
					
						
							|  |  |  | 	CacheCapacity uint | 
					
						
							|  |  |  | 	Radius        int | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-11 16:56:06 -05:00
										 |  |  | //create params with default values | 
					
						
							|  |  |  | func NewDefaultStoreParams() (self *StoreParams) { | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	return &StoreParams{ | 
					
						
							|  |  |  | 		DbCapacity:    defaultDbCapacity, | 
					
						
							|  |  |  | 		CacheCapacity: defaultCacheCapacity, | 
					
						
							|  |  |  | 		Radius:        defaultRadius, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-11 16:56:06 -05:00
										 |  |  | //this can only finally be set after all config options (file, cmd line, env vars) | 
					
						
							|  |  |  | //have been evaluated | 
					
						
							|  |  |  | func (self *StoreParams) Init(path string) { | 
					
						
							|  |  |  | 	self.ChunkDbPath = filepath.Join(path, "chunks") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | // netstore contructor, takes path argument that is used to initialise dbStore, | 
					
						
							|  |  |  | // the persistent (disk) storage component of LocalStore | 
					
						
							|  |  |  | // the second argument is the hive, the connection/logistics manager for the node | 
					
						
							| 
									
										
										
										
											2017-09-22 01:52:51 +05:30
										 |  |  | func NewNetStore(hash SwarmHasher, lstore *LocalStore, cloud CloudStore, params *StoreParams) *NetStore { | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	return &NetStore{ | 
					
						
							|  |  |  | 		hashfunc:   hash, | 
					
						
							|  |  |  | 		localStore: lstore, | 
					
						
							|  |  |  | 		cloud:      cloud, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	// timeout interval before retrieval is timed out | 
					
						
							|  |  |  | 	searchTimeout = 3 * time.Second | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // store logic common to local and network chunk store requests | 
					
						
							|  |  |  | // ~ unsafe put in localdb no check if exists no extra copy no hash validation | 
					
						
							|  |  |  | // the chunk is forced to propagate (Cloud.Store) even if locally found! | 
					
						
							|  |  |  | // caller needs to make sure if that is wanted | 
					
						
							|  |  |  | func (self *NetStore) Put(entry *Chunk) { | 
					
						
							|  |  |  | 	self.localStore.Put(entry) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// handle deliveries | 
					
						
							|  |  |  | 	if entry.Req != nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 		log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v hit existing request...delivering", entry.Key.Log())) | 
					
						
							| 
									
										
										
										
											2017-01-06 19:44:35 +02:00
										 |  |  | 		// closing C signals to other routines (local requests) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 		// that the chunk is has been retrieved | 
					
						
							|  |  |  | 		close(entry.Req.C) | 
					
						
							|  |  |  | 		// deliver the chunk to requesters upstream | 
					
						
							|  |  |  | 		go self.cloud.Deliver(entry) | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 		log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v stored locally", entry.Key.Log())) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 		// handle propagating store requests | 
					
						
							|  |  |  | 		// go self.cloud.Store(entry) | 
					
						
							|  |  |  | 		go self.cloud.Store(entry) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // retrieve logic common for local and network chunk retrieval requests | 
					
						
							|  |  |  | func (self *NetStore) Get(key Key) (*Chunk, error) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	chunk, err := self.localStore.Get(key) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		if chunk.Req == nil { | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 			log.Trace(fmt.Sprintf("NetStore.Get: %v found locally", key)) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 			log.Trace(fmt.Sprintf("NetStore.Get: %v hit on an existing request", key)) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 			// no need to launch again | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return chunk, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// no data and no request status | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 	log.Trace(fmt.Sprintf("NetStore.Get: %v not found locally. open new request", key)) | 
					
						
							| 
									
										
										
										
											2016-08-29 21:18:00 +02:00
										 |  |  | 	chunk = NewChunk(key, newRequestStatus(key)) | 
					
						
							|  |  |  | 	self.localStore.memStore.Put(chunk) | 
					
						
							|  |  |  | 	go self.cloud.Retrieve(chunk) | 
					
						
							|  |  |  | 	return chunk, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-09 00:01:12 +07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Close netstore | 
					
						
							| 
									
										
										
										
											2017-08-08 20:34:35 +03:00
										 |  |  | func (self *NetStore) Close() {} |