netstore.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. package storage
  17. import (
  18. "fmt"
  19. "path/filepath"
  20. "time"
  21. "github.com/ethereum/go-ethereum/log"
  22. )
  23. /*
  24. NetStore is a cloud storage access abstaction layer for swarm
  25. it contains the shared logic of network served chunk store/retrieval requests
  26. both local (coming from DPA api) and remote (coming from peers via bzz protocol)
  27. it implements the ChunkStore interface and embeds LocalStore
  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. // backend engine for cloud store
  39. // It can be aggregate dispatching to several parallel implementations:
  40. // bzz/network/forwarder. forwarder or IPFS or IPΞS
  41. type CloudStore interface {
  42. Store(*Chunk)
  43. Deliver(*Chunk)
  44. Retrieve(*Chunk)
  45. }
  46. type StoreParams struct {
  47. ChunkDbPath string
  48. DbCapacity uint64
  49. CacheCapacity uint
  50. Radius int
  51. }
  52. func NewStoreParams(path string) (self *StoreParams) {
  53. return &StoreParams{
  54. ChunkDbPath: filepath.Join(path, "chunks"),
  55. DbCapacity: defaultDbCapacity,
  56. CacheCapacity: defaultCacheCapacity,
  57. Radius: defaultRadius,
  58. }
  59. }
  60. // netstore contructor, takes path argument that is used to initialise dbStore,
  61. // the persistent (disk) storage component of LocalStore
  62. // the second argument is the hive, the connection/logistics manager for the node
  63. func NewNetStore(hash SwarmHasher, lstore *LocalStore, cloud CloudStore, params *StoreParams) *NetStore {
  64. return &NetStore{
  65. hashfunc: hash,
  66. localStore: lstore,
  67. cloud: cloud,
  68. }
  69. }
  70. const (
  71. // maximum number of peers that a retrieved message is delivered to
  72. requesterCount = 3
  73. )
  74. var (
  75. // timeout interval before retrieval is timed out
  76. searchTimeout = 3 * time.Second
  77. )
  78. // store logic common to local and network chunk store requests
  79. // ~ unsafe put in localdb no check if exists no extra copy no hash validation
  80. // the chunk is forced to propagate (Cloud.Store) even if locally found!
  81. // caller needs to make sure if that is wanted
  82. func (self *NetStore) Put(entry *Chunk) {
  83. self.localStore.Put(entry)
  84. // handle deliveries
  85. if entry.Req != nil {
  86. log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v hit existing request...delivering", entry.Key.Log()))
  87. // closing C signals to other routines (local requests)
  88. // that the chunk is has been retrieved
  89. close(entry.Req.C)
  90. // deliver the chunk to requesters upstream
  91. go self.cloud.Deliver(entry)
  92. } else {
  93. log.Trace(fmt.Sprintf("NetStore.Put: localStore.Put %v stored locally", entry.Key.Log()))
  94. // handle propagating store requests
  95. // go self.cloud.Store(entry)
  96. go self.cloud.Store(entry)
  97. }
  98. }
  99. // retrieve logic common for local and network chunk retrieval requests
  100. func (self *NetStore) Get(key Key) (*Chunk, error) {
  101. var err error
  102. chunk, err := self.localStore.Get(key)
  103. if err == nil {
  104. if chunk.Req == nil {
  105. log.Trace(fmt.Sprintf("NetStore.Get: %v found locally", key))
  106. } else {
  107. log.Trace(fmt.Sprintf("NetStore.Get: %v hit on an existing request", key))
  108. // no need to launch again
  109. }
  110. return chunk, err
  111. }
  112. // no data and no request status
  113. log.Trace(fmt.Sprintf("NetStore.Get: %v not found locally. open new request", key))
  114. chunk = NewChunk(key, newRequestStatus(key))
  115. self.localStore.memStore.Put(chunk)
  116. go self.cloud.Retrieve(chunk)
  117. return chunk, nil
  118. }
  119. // Close netstore
  120. func (self *NetStore) Close() {}