github.com/lbryio/lbcd@v0.22.119/database/internal/treap/immutable.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package treap 6 7 import ( 8 "bytes" 9 "math/rand" 10 ) 11 12 // cloneTreapNode returns a shallow copy of the passed node. 13 func cloneTreapNode(node *treapNode) *treapNode { 14 return &treapNode{ 15 key: node.key, 16 value: node.value, 17 priority: node.priority, 18 left: node.left, 19 right: node.right, 20 } 21 } 22 23 // Immutable represents a treap data structure which is used to hold ordered 24 // key/value pairs using a combination of binary search tree and heap semantics. 25 // It is a self-organizing and randomized data structure that doesn't require 26 // complex operations to maintain balance. Search, insert, and delete 27 // operations are all O(log n). In addition, it provides O(1) snapshots for 28 // multi-version concurrency control (MVCC). 29 // 30 // All operations which result in modifying the treap return a new version of 31 // the treap with only the modified nodes updated. All unmodified nodes are 32 // shared with the previous version. This is extremely useful in concurrent 33 // applications since the caller only has to atomically replace the treap 34 // pointer with the newly returned version after performing any mutations. All 35 // readers can simply use their existing pointer as a snapshot since the treap 36 // it points to is immutable. This effectively provides O(1) snapshot 37 // capability with efficient memory usage characteristics since the old nodes 38 // only remain allocated until there are no longer any references to them. 39 type Immutable struct { 40 root *treapNode 41 count int 42 43 // totalSize is the best estimate of the total size of of all data in 44 // the treap including the keys, values, and node sizes. 45 totalSize uint64 46 } 47 48 // newImmutable returns a new immutable treap given the passed parameters. 49 func newImmutable(root *treapNode, count int, totalSize uint64) *Immutable { 50 return &Immutable{root: root, count: count, totalSize: totalSize} 51 } 52 53 // Len returns the number of items stored in the treap. 54 func (t *Immutable) Len() int { 55 return t.count 56 } 57 58 // Size returns a best estimate of the total number of bytes the treap is 59 // consuming including all of the fields used to represent the nodes as well as 60 // the size of the keys and values. Shared values are not detected, so the 61 // returned size assumes each value is pointing to different memory. 62 func (t *Immutable) Size() uint64 { 63 return t.totalSize 64 } 65 66 // get returns the treap node that contains the passed key. It will return nil 67 // when the key does not exist. 68 func (t *Immutable) get(key []byte) *treapNode { 69 for node := t.root; node != nil; { 70 // Traverse left or right depending on the result of the 71 // comparison. 72 compareResult := bytes.Compare(key, node.key) 73 if compareResult < 0 { 74 node = node.left 75 continue 76 } 77 if compareResult > 0 { 78 node = node.right 79 continue 80 } 81 82 // The key exists. 83 return node 84 } 85 86 // A nil node was reached which means the key does not exist. 87 return nil 88 } 89 90 // Has returns whether or not the passed key exists. 91 func (t *Immutable) Has(key []byte) bool { 92 if node := t.get(key); node != nil { 93 return true 94 } 95 return false 96 } 97 98 // Get returns the value for the passed key. The function will return nil when 99 // the key does not exist. 100 func (t *Immutable) Get(key []byte) []byte { 101 if node := t.get(key); node != nil { 102 return node.value 103 } 104 return nil 105 } 106 107 // Put inserts the passed key/value pair. 108 func (t *Immutable) Put(key, value []byte) *Immutable { 109 // Use an empty byte slice for the value when none was provided. This 110 // ultimately allows key existence to be determined from the value since 111 // an empty byte slice is distinguishable from nil. 112 if value == nil { 113 value = emptySlice 114 } 115 116 // The node is the root of the tree if there isn't already one. 117 if t.root == nil { 118 root := newTreapNode(key, value, rand.Int()) 119 return newImmutable(root, 1, nodeSize(root)) 120 } 121 122 // Find the binary tree insertion point and construct a replaced list of 123 // parents while doing so. This is done because this is an immutable 124 // data structure so regardless of where in the treap the new key/value 125 // pair ends up, all ancestors up to and including the root need to be 126 // replaced. 127 // 128 // When the key matches an entry already in the treap, replace the node 129 // with a new one that has the new value set and return. 130 var parents parentStack 131 var compareResult int 132 for node := t.root; node != nil; { 133 // Clone the node and link its parent to it if needed. 134 nodeCopy := cloneTreapNode(node) 135 if oldParent := parents.At(0); oldParent != nil { 136 if oldParent.left == node { 137 oldParent.left = nodeCopy 138 } else { 139 oldParent.right = nodeCopy 140 } 141 } 142 parents.Push(nodeCopy) 143 144 // Traverse left or right depending on the result of comparing 145 // the keys. 146 compareResult = bytes.Compare(key, node.key) 147 if compareResult < 0 { 148 node = node.left 149 continue 150 } 151 if compareResult > 0 { 152 node = node.right 153 continue 154 } 155 156 // The key already exists, so update its value. 157 nodeCopy.value = value 158 159 // Return new immutable treap with the replaced node and 160 // ancestors up to and including the root of the tree. 161 newRoot := parents.At(parents.Len() - 1) 162 newTotalSize := t.totalSize - uint64(len(node.value)) + 163 uint64(len(value)) 164 return newImmutable(newRoot, t.count, newTotalSize) 165 } 166 167 // Link the new node into the binary tree in the correct position. 168 node := newTreapNode(key, value, rand.Int()) 169 parent := parents.At(0) 170 if compareResult < 0 { 171 parent.left = node 172 } else { 173 parent.right = node 174 } 175 176 // Perform any rotations needed to maintain the min-heap and replace 177 // the ancestors up to and including the tree root. 178 newRoot := parents.At(parents.Len() - 1) 179 for parents.Len() > 0 { 180 // There is nothing left to do when the node's priority is 181 // greater than or equal to its parent's priority. 182 parent = parents.Pop() 183 if node.priority >= parent.priority { 184 break 185 } 186 187 // Perform a right rotation if the node is on the left side or 188 // a left rotation if the node is on the right side. 189 if parent.left == node { 190 node.right, parent.left = parent, node.right 191 } else { 192 node.left, parent.right = parent, node.left 193 } 194 195 // Either set the new root of the tree when there is no 196 // grandparent or relink the grandparent to the node based on 197 // which side the old parent the node is replacing was on. 198 grandparent := parents.At(0) 199 if grandparent == nil { 200 newRoot = node 201 } else if grandparent.left == parent { 202 grandparent.left = node 203 } else { 204 grandparent.right = node 205 } 206 } 207 208 return newImmutable(newRoot, t.count+1, t.totalSize+nodeSize(node)) 209 } 210 211 // Delete removes the passed key from the treap and returns the resulting treap 212 // if it exists. The original immutable treap is returned if the key does not 213 // exist. 214 func (t *Immutable) Delete(key []byte) *Immutable { 215 // Find the node for the key while constructing a list of parents while 216 // doing so. 217 var parents parentStack 218 var delNode *treapNode 219 for node := t.root; node != nil; { 220 parents.Push(node) 221 222 // Traverse left or right depending on the result of the 223 // comparison. 224 compareResult := bytes.Compare(key, node.key) 225 if compareResult < 0 { 226 node = node.left 227 continue 228 } 229 if compareResult > 0 { 230 node = node.right 231 continue 232 } 233 234 // The key exists. 235 delNode = node 236 break 237 } 238 239 // There is nothing to do if the key does not exist. 240 if delNode == nil { 241 return t 242 } 243 244 // When the only node in the tree is the root node and it is the one 245 // being deleted, there is nothing else to do besides removing it. 246 parent := parents.At(1) 247 if parent == nil && delNode.left == nil && delNode.right == nil { 248 return newImmutable(nil, 0, 0) 249 } 250 251 // Construct a replaced list of parents and the node to delete itself. 252 // This is done because this is an immutable data structure and 253 // therefore all ancestors of the node that will be deleted, up to and 254 // including the root, need to be replaced. 255 var newParents parentStack 256 for i := parents.Len(); i > 0; i-- { 257 node := parents.At(i - 1) 258 nodeCopy := cloneTreapNode(node) 259 if oldParent := newParents.At(0); oldParent != nil { 260 if oldParent.left == node { 261 oldParent.left = nodeCopy 262 } else { 263 oldParent.right = nodeCopy 264 } 265 } 266 newParents.Push(nodeCopy) 267 } 268 delNode = newParents.Pop() 269 parent = newParents.At(0) 270 271 // Perform rotations to move the node to delete to a leaf position while 272 // maintaining the min-heap while replacing the modified children. 273 var child *treapNode 274 newRoot := newParents.At(newParents.Len() - 1) 275 for delNode.left != nil || delNode.right != nil { 276 // Choose the child with the higher priority. 277 var isLeft bool 278 if delNode.left == nil { 279 child = delNode.right 280 } else if delNode.right == nil { 281 child = delNode.left 282 isLeft = true 283 } else if delNode.left.priority >= delNode.right.priority { 284 child = delNode.left 285 isLeft = true 286 } else { 287 child = delNode.right 288 } 289 290 // Rotate left or right depending on which side the child node 291 // is on. This has the effect of moving the node to delete 292 // towards the bottom of the tree while maintaining the 293 // min-heap. 294 child = cloneTreapNode(child) 295 if isLeft { 296 child.right, delNode.left = delNode, child.right 297 } else { 298 child.left, delNode.right = delNode, child.left 299 } 300 301 // Either set the new root of the tree when there is no 302 // grandparent or relink the grandparent to the node based on 303 // which side the old parent the node is replacing was on. 304 // 305 // Since the node to be deleted was just moved down a level, the 306 // new grandparent is now the current parent and the new parent 307 // is the current child. 308 if parent == nil { 309 newRoot = child 310 } else if parent.left == delNode { 311 parent.left = child 312 } else { 313 parent.right = child 314 } 315 316 // The parent for the node to delete is now what was previously 317 // its child. 318 parent = child 319 } 320 321 // Delete the node, which is now a leaf node, by disconnecting it from 322 // its parent. 323 if parent.right == delNode { 324 parent.right = nil 325 } else { 326 parent.left = nil 327 } 328 329 return newImmutable(newRoot, t.count-1, t.totalSize-nodeSize(delNode)) 330 } 331 332 // ForEach invokes the passed function with every key/value pair in the treap 333 // in ascending order. 334 func (t *Immutable) ForEach(fn func(k, v []byte) bool) { 335 // Add the root node and all children to the left of it to the list of 336 // nodes to traverse and loop until they, and all of their child nodes, 337 // have been traversed. 338 var parents parentStack 339 for node := t.root; node != nil; node = node.left { 340 parents.Push(node) 341 } 342 for parents.Len() > 0 { 343 node := parents.Pop() 344 if !fn(node.key, node.value) { 345 return 346 } 347 348 // Extend the nodes to traverse by all children to the left of 349 // the current node's right child. 350 for node := node.right; node != nil; node = node.left { 351 parents.Push(node) 352 } 353 } 354 } 355 356 // NewImmutable returns a new empty immutable treap ready for use. See the 357 // documentation for the Immutable structure for more details. 358 func NewImmutable() *Immutable { 359 return &Immutable{} 360 }