github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/mock/db/db.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 // 26 package db 27 28 import ( 29 "archive/tar" 30 "bytes" 31 "encoding/json" 32 "io" 33 "io/ioutil" 34 35 "github.com/syndtr/goleveldb/leveldb" 36 "github.com/syndtr/goleveldb/leveldb/util" 37 38 "github.com/ethereum/go-ethereum/common" 39 "github.com/ethereum/go-ethereum/swarm/storage/mock" 40 ) 41 42 // 43 // 44 // 45 // 46 type GlobalStore struct { 47 db *leveldb.DB 48 } 49 50 // 51 func NewGlobalStore(path string) (s *GlobalStore, err error) { 52 db, err := leveldb.OpenFile(path, nil) 53 if err != nil { 54 return nil, err 55 } 56 return &GlobalStore{ 57 db: db, 58 }, nil 59 } 60 61 // 62 func (s *GlobalStore) Close() error { 63 return s.db.Close() 64 } 65 66 // 67 // 68 func (s *GlobalStore) NewNodeStore(addr common.Address) *mock.NodeStore { 69 return mock.NewNodeStore(addr, s) 70 } 71 72 // 73 // 74 func (s *GlobalStore) Get(addr common.Address, key []byte) (data []byte, err error) { 75 has, err := s.db.Has(nodeDBKey(addr, key), nil) 76 if err != nil { 77 return nil, mock.ErrNotFound 78 } 79 if !has { 80 return nil, mock.ErrNotFound 81 } 82 data, err = s.db.Get(dataDBKey(key), nil) 83 if err == leveldb.ErrNotFound { 84 err = mock.ErrNotFound 85 } 86 return 87 } 88 89 // 90 func (s *GlobalStore) Put(addr common.Address, key []byte, data []byte) error { 91 batch := new(leveldb.Batch) 92 batch.Put(nodeDBKey(addr, key), nil) 93 batch.Put(dataDBKey(key), data) 94 return s.db.Write(batch, nil) 95 } 96 97 // 98 func (s *GlobalStore) HasKey(addr common.Address, key []byte) bool { 99 has, err := s.db.Has(nodeDBKey(addr, key), nil) 100 if err != nil { 101 has = false 102 } 103 return has 104 } 105 106 // 107 // 108 func (s *GlobalStore) Import(r io.Reader) (n int, err error) { 109 tr := tar.NewReader(r) 110 111 for { 112 hdr, err := tr.Next() 113 if err != nil { 114 if err == io.EOF { 115 break 116 } 117 return n, err 118 } 119 120 data, err := ioutil.ReadAll(tr) 121 if err != nil { 122 return n, err 123 } 124 125 var c mock.ExportedChunk 126 if err = json.Unmarshal(data, &c); err != nil { 127 return n, err 128 } 129 130 batch := new(leveldb.Batch) 131 for _, addr := range c.Addrs { 132 batch.Put(nodeDBKeyHex(addr, hdr.Name), nil) 133 } 134 135 batch.Put(dataDBKey(common.Hex2Bytes(hdr.Name)), c.Data) 136 if err = s.db.Write(batch, nil); err != nil { 137 return n, err 138 } 139 140 n++ 141 } 142 return n, err 143 } 144 145 // 146 // 147 func (s *GlobalStore) Export(w io.Writer) (n int, err error) { 148 tw := tar.NewWriter(w) 149 defer tw.Close() 150 151 buf := bytes.NewBuffer(make([]byte, 0, 1024)) 152 encoder := json.NewEncoder(buf) 153 154 iter := s.db.NewIterator(util.BytesPrefix(nodeKeyPrefix), nil) 155 defer iter.Release() 156 157 var currentKey string 158 var addrs []common.Address 159 160 saveChunk := func(hexKey string) error { 161 key := common.Hex2Bytes(hexKey) 162 163 data, err := s.db.Get(dataDBKey(key), nil) 164 if err != nil { 165 return err 166 } 167 168 buf.Reset() 169 if err = encoder.Encode(mock.ExportedChunk{ 170 Addrs: addrs, 171 Data: data, 172 }); err != nil { 173 return err 174 } 175 176 d := buf.Bytes() 177 hdr := &tar.Header{ 178 Name: hexKey, 179 Mode: 0644, 180 Size: int64(len(d)), 181 } 182 if err := tw.WriteHeader(hdr); err != nil { 183 return err 184 } 185 if _, err := tw.Write(d); err != nil { 186 return err 187 } 188 n++ 189 return nil 190 } 191 192 for iter.Next() { 193 k := bytes.TrimPrefix(iter.Key(), nodeKeyPrefix) 194 i := bytes.Index(k, []byte("-")) 195 if i < 0 { 196 continue 197 } 198 hexKey := string(k[:i]) 199 200 if currentKey == "" { 201 currentKey = hexKey 202 } 203 204 if hexKey != currentKey { 205 if err = saveChunk(currentKey); err != nil { 206 return n, err 207 } 208 209 addrs = addrs[:0] 210 } 211 212 currentKey = hexKey 213 addrs = append(addrs, common.BytesToAddress(k[i:])) 214 } 215 216 if len(addrs) > 0 { 217 if err = saveChunk(currentKey); err != nil { 218 return n, err 219 } 220 } 221 222 return n, err 223 } 224 225 var ( 226 nodeKeyPrefix = []byte("node-") 227 dataKeyPrefix = []byte("data-") 228 ) 229 230 // 231 func nodeDBKey(addr common.Address, key []byte) []byte { 232 return nodeDBKeyHex(addr, common.Bytes2Hex(key)) 233 } 234 235 // 236 // 237 func nodeDBKeyHex(addr common.Address, hexKey string) []byte { 238 return append(append(nodeKeyPrefix, []byte(hexKey+"-")...), addr[:]...) 239 } 240 241 // 242 func dataDBKey(key []byte) []byte { 243 return append(dataKeyPrefix, key...) 244 }