github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/mock/mem/mem.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:45</date> 10 //</624450120540229632> 11 12 13 //package mem实现了一个模拟存储,将所有块数据保存在内存中。 14 //虽然它可以用于小规模的测试,但其主要目的是 15 //包是提供模拟存储的最简单的参考实现。 16 package mem 17 18 import ( 19 "archive/tar" 20 "bytes" 21 "encoding/json" 22 "io" 23 "io/ioutil" 24 "sync" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/swarm/storage/mock" 28 ) 29 30 //GlobalStore存储所有块数据以及键和节点地址关系。 31 //它实现mock.globalStore接口。 32 type GlobalStore struct { 33 nodes map[string]map[common.Address]struct{} 34 data map[string][]byte 35 mu sync.Mutex 36 } 37 38 //NewGlobalStore创建了一个新的GlobalStore实例。 39 func NewGlobalStore() *GlobalStore { 40 return &GlobalStore{ 41 nodes: make(map[string]map[common.Address]struct{}), 42 data: make(map[string][]byte), 43 } 44 } 45 46 //new nodestore返回一个新的nodestore实例,用于检索和存储 47 //仅对地址为的节点进行数据块处理。 48 func (s *GlobalStore) NewNodeStore(addr common.Address) *mock.NodeStore { 49 return mock.NewNodeStore(addr, s) 50 } 51 52 //如果节点存在键为的块,则get返回块数据 53 //地址地址。 54 func (s *GlobalStore) Get(addr common.Address, key []byte) (data []byte, err error) { 55 s.mu.Lock() 56 defer s.mu.Unlock() 57 58 if _, ok := s.nodes[string(key)][addr]; !ok { 59 return nil, mock.ErrNotFound 60 } 61 62 data, ok := s.data[string(key)] 63 if !ok { 64 return nil, mock.ErrNotFound 65 } 66 return data, nil 67 } 68 69 //Put保存带有地址addr的节点的块数据。 70 func (s *GlobalStore) Put(addr common.Address, key []byte, data []byte) error { 71 s.mu.Lock() 72 defer s.mu.Unlock() 73 74 if _, ok := s.nodes[string(key)]; !ok { 75 s.nodes[string(key)] = make(map[common.Address]struct{}) 76 } 77 s.nodes[string(key)][addr] = struct{}{} 78 s.data[string(key)] = data 79 return nil 80 } 81 82 //删除删除地址为的节点的块数据。 83 func (s *GlobalStore) Delete(addr common.Address, key []byte) error { 84 s.mu.Lock() 85 defer s.mu.Unlock() 86 87 var count int 88 if _, ok := s.nodes[string(key)]; ok { 89 delete(s.nodes[string(key)], addr) 90 count = len(s.nodes[string(key)]) 91 } 92 if count == 0 { 93 delete(s.data, string(key)) 94 } 95 return nil 96 } 97 98 //haskey返回带有addr的节点是否包含键。 99 func (s *GlobalStore) HasKey(addr common.Address, key []byte) bool { 100 s.mu.Lock() 101 defer s.mu.Unlock() 102 103 _, ok := s.nodes[string(key)][addr] 104 return ok 105 } 106 107 //import从包含导出块数据的读卡器读取tar存档。 108 //它返回导入的块的数量和错误。 109 func (s *GlobalStore) Import(r io.Reader) (n int, err error) { 110 s.mu.Lock() 111 defer s.mu.Unlock() 112 113 tr := tar.NewReader(r) 114 115 for { 116 hdr, err := tr.Next() 117 if err != nil { 118 if err == io.EOF { 119 break 120 } 121 return n, err 122 } 123 124 data, err := ioutil.ReadAll(tr) 125 if err != nil { 126 return n, err 127 } 128 129 var c mock.ExportedChunk 130 if err = json.Unmarshal(data, &c); err != nil { 131 return n, err 132 } 133 134 addrs := make(map[common.Address]struct{}) 135 for _, a := range c.Addrs { 136 addrs[a] = struct{}{} 137 } 138 139 key := string(common.Hex2Bytes(hdr.Name)) 140 s.nodes[key] = addrs 141 s.data[key] = c.Data 142 n++ 143 } 144 return n, err 145 } 146 147 //将包含所有块数据的tar存档导出到写入程序 148 //商店。它返回导出的块数和错误。 149 func (s *GlobalStore) Export(w io.Writer) (n int, err error) { 150 s.mu.Lock() 151 defer s.mu.Unlock() 152 153 tw := tar.NewWriter(w) 154 defer tw.Close() 155 156 buf := bytes.NewBuffer(make([]byte, 0, 1024)) 157 encoder := json.NewEncoder(buf) 158 for key, addrs := range s.nodes { 159 al := make([]common.Address, 0, len(addrs)) 160 for a := range addrs { 161 al = append(al, a) 162 } 163 164 buf.Reset() 165 if err = encoder.Encode(mock.ExportedChunk{ 166 Addrs: al, 167 Data: s.data[key], 168 }); err != nil { 169 return n, err 170 } 171 172 data := buf.Bytes() 173 hdr := &tar.Header{ 174 Name: common.Bytes2Hex([]byte(key)), 175 Mode: 0644, 176 Size: int64(len(data)), 177 } 178 if err := tw.WriteHeader(hdr); err != nil { 179 return n, err 180 } 181 if _, err := tw.Write(data); err != nil { 182 return n, err 183 } 184 n++ 185 } 186 return n, err 187 } 188