github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/iavl/nodedb_fnc.go (about) 1 package iavl 2 3 import ( 4 "sync" 5 6 "github.com/tendermint/go-amino" 7 ) 8 9 type fastNodeChanges struct { 10 additions map[string]*FastNode 11 removals map[string]interface{} 12 mtx sync.RWMutex 13 } 14 15 func newFastNodeChanges() *fastNodeChanges { 16 return &fastNodeChanges{ 17 additions: make(map[string]*FastNode), 18 removals: make(map[string]interface{}), 19 } 20 } 21 22 func (fnc *fastNodeChanges) get(key []byte) (*FastNode, bool) { 23 fnc.mtx.RLock() 24 defer fnc.mtx.RUnlock() 25 if node, ok := fnc.additions[string(key)]; ok { 26 return node, true 27 } 28 if _, ok := fnc.removals[string(key)]; ok { 29 return nil, true 30 } 31 32 return nil, false 33 } 34 35 func (fnc *fastNodeChanges) add(key []byte, fastNode *FastNode) { 36 fnc.mtx.Lock() 37 fnc.additions[string(key)] = fastNode 38 delete(fnc.removals, string(key)) 39 fnc.mtx.Unlock() 40 } 41 42 func (fnc *fastNodeChanges) addAdditions(key []byte, fastNode *FastNode) { 43 fnc.mtx.Lock() 44 fnc.additions[string(key)] = fastNode 45 fnc.mtx.Unlock() 46 } 47 48 func (fnc *fastNodeChanges) remove(key []byte, value interface{}) { 49 fnc.mtx.Lock() 50 fnc.removals[string(key)] = value 51 delete(fnc.additions, string(key)) 52 fnc.mtx.Unlock() 53 } 54 55 func (fnc *fastNodeChanges) addRemovals(key []byte) { 56 fnc.mtx.Lock() 57 fnc.removals[string(key)] = true 58 fnc.mtx.Unlock() 59 } 60 61 func (fnc *fastNodeChanges) checkRemovals(key []byte) bool { 62 fnc.mtx.RLock() 63 defer fnc.mtx.RUnlock() 64 65 if _, ok := fnc.removals[string(key)]; ok { 66 return true 67 } 68 return false 69 } 70 71 func (fnc *fastNodeChanges) checkAdditions(key []byte) bool { 72 fnc.mtx.RLock() 73 defer fnc.mtx.RUnlock() 74 if _, ok := fnc.additions[string(key)]; ok { 75 return true 76 } 77 78 return false 79 } 80 81 func (fnc *fastNodeChanges) getAdditions() map[string]*FastNode { 82 return fnc.additions 83 } 84 85 func (fnc *fastNodeChanges) getRemovals() map[string]interface{} { 86 return fnc.removals 87 } 88 89 func (fnc *fastNodeChanges) clone() *fastNodeChanges { 90 if fnc == nil { 91 return nil 92 } 93 fnc.mtx.RLock() 94 defer fnc.mtx.RUnlock() 95 var additions map[string]*FastNode 96 if fnc.additions != nil { 97 additions = make(map[string]*FastNode, len(fnc.additions)) 98 for k, v := range fnc.additions { 99 additions[k] = v 100 } 101 } 102 103 var removals map[string]interface{} 104 if fnc.removals != nil { 105 removals = make(map[string]interface{}, len(fnc.removals)) 106 for k, v := range fnc.removals { 107 removals[k] = v 108 } 109 } 110 return &fastNodeChanges{ 111 additions: additions, 112 removals: removals, 113 } 114 } 115 116 // mergePrev merge previous to fnc, prev is old than fnc 117 func (fnc *fastNodeChanges) mergePrev(prev *fastNodeChanges) *fastNodeChanges { 118 if fnc == nil { 119 return prev 120 } 121 if prev == nil { 122 return fnc 123 } 124 125 for k, v := range prev.additions { 126 if !fnc.checkAdditions(amino.StrToBytes(k)) && !fnc.checkRemovals(amino.StrToBytes(k)) { 127 fnc.add(amino.StrToBytes(k), v) 128 } 129 } 130 for k, v := range prev.removals { 131 if !fnc.checkAdditions(amino.StrToBytes(k)) && !fnc.checkRemovals(amino.StrToBytes(k)) { 132 fnc.remove(amino.StrToBytes(k), v) 133 } 134 } 135 return fnc 136 } 137 138 // mergeLater merge later to fnc, later is new than fnc 139 func (fnc *fastNodeChanges) mergeLater(later *fastNodeChanges) { 140 for k, v := range later.additions { 141 fnc.add(amino.StrToBytes(k), v) 142 } 143 for k, v := range later.removals { 144 fnc.remove(amino.StrToBytes(k), v) 145 } 146 } 147 148 func (fnc *fastNodeChanges) reset() { 149 fnc.mtx.Lock() 150 for k := range fnc.additions { 151 delete(fnc.additions, k) 152 } 153 for k := range fnc.removals { 154 delete(fnc.removals, k) 155 } 156 fnc.mtx.Unlock() 157 } 158 159 type fastNodeChangesWithVersion struct { 160 mtx sync.RWMutex 161 versions []int64 162 fncMap map[int64]*fastNodeChanges 163 } 164 165 func newFastNodeChangesWithVersion() *fastNodeChangesWithVersion { 166 return &fastNodeChangesWithVersion{ 167 fncMap: make(map[int64]*fastNodeChanges), 168 } 169 } 170 171 func (fncv *fastNodeChangesWithVersion) add(version int64, fnc *fastNodeChanges) { 172 fncv.mtx.Lock() 173 defer fncv.mtx.Unlock() 174 fncv.versions = append(fncv.versions, version) 175 fncv.fncMap[version] = fnc 176 } 177 178 func (fncv *fastNodeChangesWithVersion) remove(version int64) { 179 if len(fncv.versions) < 1 || version != fncv.versions[0] { 180 return 181 } 182 fncv.mtx.Lock() 183 defer fncv.mtx.Unlock() 184 fncv.versions = fncv.versions[1:] 185 delete(fncv.fncMap, version) 186 } 187 188 func (fncv *fastNodeChangesWithVersion) get(key []byte) (*FastNode, bool) { 189 fncv.mtx.RLock() 190 defer fncv.mtx.RUnlock() 191 for i := len(fncv.versions) - 1; i >= 0; i-- { 192 if fn, ok := fncv.fncMap[fncv.versions[i]].get(key); ok { 193 return fn, ok 194 } 195 } 196 return nil, false 197 } 198 199 func (fncv *fastNodeChangesWithVersion) expand(changes *fastNodeChanges) *fastNodeChanges { 200 fncv.mtx.RLock() 201 defer fncv.mtx.RUnlock() 202 ret := changes.clone() 203 if ret == nil { 204 ret = newFastNodeChanges() 205 } 206 for i := len(fncv.versions) - 1; i >= 0; i-- { 207 for k, v := range fncv.fncMap[fncv.versions[i]].additions { 208 if !ret.checkAdditions(amino.StrToBytes(k)) && !ret.checkRemovals(amino.StrToBytes(k)) { 209 ret.add(amino.StrToBytes(k), v) 210 } 211 } 212 for k, v := range fncv.fncMap[fncv.versions[i]].removals { 213 if !ret.checkAdditions(amino.StrToBytes(k)) && !ret.checkRemovals(amino.StrToBytes(k)) { 214 ret.remove(amino.StrToBytes(k), v) 215 } 216 } 217 } 218 219 return ret 220 }