github.com/core-coin/go-core/v2@v2.1.9/light/nodeset.go (about)

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