github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/light/nodeset.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package light
    13  
    14  import (
    15  	"errors"
    16  	"sync"
    17  
    18  	"github.com/Sberex/go-sberex/common"
    19  	"github.com/Sberex/go-sberex/crypto"
    20  	"github.com/Sberex/go-sberex/ethdb"
    21  	"github.com/Sberex/go-sberex/rlp"
    22  )
    23  
    24  // NodeSet stores a set of trie nodes. It implements trie.Database and can also
    25  // act as a cache for another trie.Database.
    26  type NodeSet struct {
    27  	nodes map[string][]byte
    28  	order []string
    29  
    30  	dataSize int
    31  	lock     sync.RWMutex
    32  }
    33  
    34  // NewNodeSet creates an empty node set
    35  func NewNodeSet() *NodeSet {
    36  	return &NodeSet{
    37  		nodes: make(map[string][]byte),
    38  	}
    39  }
    40  
    41  // Put stores a new node in the set
    42  func (db *NodeSet) Put(key []byte, value []byte) error {
    43  	db.lock.Lock()
    44  	defer db.lock.Unlock()
    45  
    46  	if _, ok := db.nodes[string(key)]; ok {
    47  		return nil
    48  	}
    49  	keystr := string(key)
    50  
    51  	db.nodes[keystr] = common.CopyBytes(value)
    52  	db.order = append(db.order, keystr)
    53  	db.dataSize += len(value)
    54  
    55  	return nil
    56  }
    57  
    58  // Get returns a stored node
    59  func (db *NodeSet) Get(key []byte) ([]byte, error) {
    60  	db.lock.RLock()
    61  	defer db.lock.RUnlock()
    62  
    63  	if entry, ok := db.nodes[string(key)]; ok {
    64  		return entry, nil
    65  	}
    66  	return nil, errors.New("not found")
    67  }
    68  
    69  // Has returns true if the node set contains the given key
    70  func (db *NodeSet) Has(key []byte) (bool, error) {
    71  	_, err := db.Get(key)
    72  	return err == nil, nil
    73  }
    74  
    75  // KeyCount returns the number of nodes in the set
    76  func (db *NodeSet) KeyCount() int {
    77  	db.lock.RLock()
    78  	defer db.lock.RUnlock()
    79  
    80  	return len(db.nodes)
    81  }
    82  
    83  // DataSize returns the aggregated data size of nodes in the set
    84  func (db *NodeSet) DataSize() int {
    85  	db.lock.RLock()
    86  	defer db.lock.RUnlock()
    87  
    88  	return db.dataSize
    89  }
    90  
    91  // NodeList converts the node set to a NodeList
    92  func (db *NodeSet) NodeList() NodeList {
    93  	db.lock.RLock()
    94  	defer db.lock.RUnlock()
    95  
    96  	var values NodeList
    97  	for _, key := range db.order {
    98  		values = append(values, db.nodes[key])
    99  	}
   100  	return values
   101  }
   102  
   103  // Store writes the contents of the set to the given database
   104  func (db *NodeSet) Store(target ethdb.Putter) {
   105  	db.lock.RLock()
   106  	defer db.lock.RUnlock()
   107  
   108  	for key, value := range db.nodes {
   109  		target.Put([]byte(key), value)
   110  	}
   111  }
   112  
   113  // NodeList stores an ordered list of trie nodes. It implements ethdb.Putter.
   114  type NodeList []rlp.RawValue
   115  
   116  // Store writes the contents of the list to the given database
   117  func (n NodeList) Store(db ethdb.Putter) {
   118  	for _, node := range n {
   119  		db.Put(crypto.Keccak256(node), node)
   120  	}
   121  }
   122  
   123  // NodeSet converts the node list to a NodeSet
   124  func (n NodeList) NodeSet() *NodeSet {
   125  	db := NewNodeSet()
   126  	n.Store(db)
   127  	return db
   128  }
   129  
   130  // Put stores a new node at the end of the list
   131  func (n *NodeList) Put(key []byte, value []byte) error {
   132  	*n = append(*n, value)
   133  	return nil
   134  }
   135  
   136  // DataSize returns the aggregated data size of nodes in the list
   137  func (n NodeList) DataSize() int {
   138  	var size int
   139  	for _, node := range n {
   140  		size += len(node)
   141  	}
   142  	return size
   143  }