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 }