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