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