github.com/codingfuture/orig-energi3@v0.8.4/swarm/storage/mock/mem/mem.go (about) 1 // Copyright 2018 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 mem implements a mock store that keeps all chunk data in memory. 18 // While it can be used for testing on smaller scales, the main purpose of this 19 // package is to provide the simplest reference implementation of a mock store. 20 package mem 21 22 import ( 23 "archive/tar" 24 "bytes" 25 "encoding/json" 26 "io" 27 "io/ioutil" 28 "sync" 29 30 "github.com/ethereum/go-ethereum/common" 31 "github.com/ethereum/go-ethereum/swarm/storage/mock" 32 ) 33 34 // GlobalStore stores all chunk data and also keys and node addresses relations. 35 // It implements mock.GlobalStore interface. 36 type GlobalStore struct { 37 nodes map[string]map[common.Address]struct{} 38 data map[string][]byte 39 mu sync.Mutex 40 } 41 42 // NewGlobalStore creates a new instance of GlobalStore. 43 func NewGlobalStore() *GlobalStore { 44 return &GlobalStore{ 45 nodes: make(map[string]map[common.Address]struct{}), 46 data: make(map[string][]byte), 47 } 48 } 49 50 // NewNodeStore returns a new instance of NodeStore that retrieves and stores 51 // chunk data only for a node with address addr. 52 func (s *GlobalStore) NewNodeStore(addr common.Address) *mock.NodeStore { 53 return mock.NewNodeStore(addr, s) 54 } 55 56 // Get returns chunk data if the chunk with key exists for node 57 // on address addr. 58 func (s *GlobalStore) Get(addr common.Address, key []byte) (data []byte, err error) { 59 s.mu.Lock() 60 defer s.mu.Unlock() 61 62 if _, ok := s.nodes[string(key)][addr]; !ok { 63 return nil, mock.ErrNotFound 64 } 65 66 data, ok := s.data[string(key)] 67 if !ok { 68 return nil, mock.ErrNotFound 69 } 70 return data, nil 71 } 72 73 // Put saves the chunk data for node with address addr. 74 func (s *GlobalStore) Put(addr common.Address, key []byte, data []byte) error { 75 s.mu.Lock() 76 defer s.mu.Unlock() 77 78 if _, ok := s.nodes[string(key)]; !ok { 79 s.nodes[string(key)] = make(map[common.Address]struct{}) 80 } 81 s.nodes[string(key)][addr] = struct{}{} 82 s.data[string(key)] = data 83 return nil 84 } 85 86 // Delete removes the chunk data for node with address addr. 87 func (s *GlobalStore) Delete(addr common.Address, key []byte) error { 88 s.mu.Lock() 89 defer s.mu.Unlock() 90 91 var count int 92 if _, ok := s.nodes[string(key)]; ok { 93 delete(s.nodes[string(key)], addr) 94 count = len(s.nodes[string(key)]) 95 } 96 if count == 0 { 97 delete(s.data, string(key)) 98 } 99 return nil 100 } 101 102 // HasKey returns whether a node with addr contains the key. 103 func (s *GlobalStore) HasKey(addr common.Address, key []byte) bool { 104 s.mu.Lock() 105 defer s.mu.Unlock() 106 107 _, ok := s.nodes[string(key)][addr] 108 return ok 109 } 110 111 // Import reads tar archive from a reader that contains exported chunk data. 112 // It returns the number of chunks imported and an error. 113 func (s *GlobalStore) Import(r io.Reader) (n int, err error) { 114 s.mu.Lock() 115 defer s.mu.Unlock() 116 117 tr := tar.NewReader(r) 118 119 for { 120 hdr, err := tr.Next() 121 if err != nil { 122 if err == io.EOF { 123 break 124 } 125 return n, err 126 } 127 128 data, err := ioutil.ReadAll(tr) 129 if err != nil { 130 return n, err 131 } 132 133 var c mock.ExportedChunk 134 if err = json.Unmarshal(data, &c); err != nil { 135 return n, err 136 } 137 138 addrs := make(map[common.Address]struct{}) 139 for _, a := range c.Addrs { 140 addrs[a] = struct{}{} 141 } 142 143 key := string(common.Hex2Bytes(hdr.Name)) 144 s.nodes[key] = addrs 145 s.data[key] = c.Data 146 n++ 147 } 148 return n, err 149 } 150 151 // Export writes to a writer a tar archive with all chunk data from 152 // the store. It returns the number of chunks exported and an error. 153 func (s *GlobalStore) Export(w io.Writer) (n int, err error) { 154 s.mu.Lock() 155 defer s.mu.Unlock() 156 157 tw := tar.NewWriter(w) 158 defer tw.Close() 159 160 buf := bytes.NewBuffer(make([]byte, 0, 1024)) 161 encoder := json.NewEncoder(buf) 162 for key, addrs := range s.nodes { 163 al := make([]common.Address, 0, len(addrs)) 164 for a := range addrs { 165 al = append(al, a) 166 } 167 168 buf.Reset() 169 if err = encoder.Encode(mock.ExportedChunk{ 170 Addrs: al, 171 Data: s.data[key], 172 }); err != nil { 173 return n, err 174 } 175 176 data := buf.Bytes() 177 hdr := &tar.Header{ 178 Name: common.Bytes2Hex([]byte(key)), 179 Mode: 0644, 180 Size: int64(len(data)), 181 } 182 if err := tw.WriteHeader(hdr); err != nil { 183 return n, err 184 } 185 if _, err := tw.Write(data); err != nil { 186 return n, err 187 } 188 n++ 189 } 190 return n, err 191 }