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  }