github.com/scottcagno/storage@v1.8.0/pkg/lsmt/trees/rbtree/rbtree.go (about) 1 package rbtree 2 3 import ( 4 "runtime" 5 "strings" 6 "sync" 7 ) 8 9 type RBEntry interface { 10 Compare(that RBEntry) int 11 Size() int 12 String() string 13 } 14 15 var empty = *new(RBEntry) 16 17 func compare(this, that RBEntry) int { 18 return this.Compare(that) 19 } 20 21 const ( 22 RED = 0 23 BLACK = 1 24 ) 25 26 type rbNode struct { 27 left *rbNode 28 right *rbNode 29 parent *rbNode 30 color uint 31 entry RBEntry 32 } 33 34 type RBTree = rbTree 35 36 // rbTree is a struct representing a rbTree 37 type rbTree struct { 38 lock sync.RWMutex 39 NIL *rbNode 40 root *rbNode 41 count int 42 size int64 43 } 44 45 func NewRBTree() *rbTree { 46 return newRBTree() 47 } 48 49 // NewTree creates and returns a new rbTree 50 func newRBTree() *rbTree { 51 n := &rbNode{ 52 left: nil, 53 right: nil, 54 parent: nil, 55 color: BLACK, 56 entry: empty, 57 } 58 return &rbTree{ 59 NIL: n, 60 root: n, 61 count: 0, 62 } 63 } 64 65 func (t *rbTree) GetClone() *rbTree { 66 t.Lock() 67 defer t.Unlock() 68 clone := newRBTree() 69 t.cloneEntries(clone) 70 return clone 71 } 72 73 func (t *rbTree) Lock() { 74 t.lock.Lock() 75 } 76 77 func (t *rbTree) Unlock() { 78 t.lock.Unlock() 79 } 80 81 func (t *rbTree) RLock() { 82 t.lock.RLock() 83 } 84 85 func (t *rbTree) RUnlock() { 86 t.lock.RUnlock() 87 } 88 89 // Has tests and returns a boolean value if the 90 // provided key exists in the tree 91 func (t *rbTree) Has(entry RBEntry) bool { 92 _, ok := t.getInternal(entry) 93 return ok 94 } 95 96 // Add adds the provided key and value only if it does not 97 // already exist in the tree. It returns false if the key and 98 // value was not able to be added, and true if it was added 99 // successfully 100 func (t *rbTree) Add(entry RBEntry) bool { 101 _, ok := t.getInternal(entry) 102 if ok { 103 // key already exists, so we are not adding 104 return false 105 } 106 t.putInternal(entry) 107 return true 108 } 109 110 func (t *rbTree) Put(entry RBEntry) (RBEntry, bool) { 111 return t.putInternal(entry) 112 } 113 114 func (t *rbTree) putInternal(entry RBEntry) (RBEntry, bool) { 115 if entry == nil { 116 return nil, false 117 } 118 // insert returns the node inserted 119 // and if the node returned already 120 // existed and/or was updated 121 ret, ok := t.insert(&rbNode{ 122 left: t.NIL, 123 right: t.NIL, 124 parent: t.NIL, 125 color: RED, 126 entry: entry, 127 }) 128 return ret.entry, ok 129 } 130 131 func (t *rbTree) Get(entry RBEntry) (RBEntry, bool) { 132 return t.getInternal(entry) 133 } 134 135 // GetNearMin performs an approximate search for the specified key 136 // and returns the closest key that is less than (the predecessor) 137 // to the searched key as well as a boolean reporting true if an 138 // exact match was found for the key, and false if it is unknown 139 // or and exact match was not found 140 func (t *rbTree) GetNearMin(entry RBEntry) (RBEntry, bool) { 141 if entry == nil { 142 return nil, false 143 } 144 ret := t.searchApprox(&rbNode{ 145 left: t.NIL, 146 right: t.NIL, 147 parent: t.NIL, 148 color: RED, 149 entry: entry, 150 }) 151 prev := t.predecessor(ret).entry 152 if prev == nil { 153 prev, _ = t.Min() 154 } 155 return prev, ret.entry.Compare(entry) == 0 156 } 157 158 // GetNearMax performs an approximate search for the specified key 159 // and returns the closest key that is greater than (the successor) 160 // to the searched key as well as a boolean reporting true if an 161 // exact match was found for the key, and false if it is unknown or 162 // and exact match was not found 163 func (t *rbTree) GetNearMax(entry RBEntry) (RBEntry, bool) { 164 if entry == nil { 165 return nil, false 166 } 167 ret := t.searchApprox(&rbNode{ 168 left: t.NIL, 169 right: t.NIL, 170 parent: t.NIL, 171 color: RED, 172 entry: entry, 173 }) 174 return t.successor(ret).entry, ret.entry.Compare(entry) == 0 175 } 176 177 // GetApproxPrevNext performs an approximate search for the specified key 178 // and returns the searched key, the predecessor, and the successor and a 179 // boolean reporting true if an exact match was found for the key, and false 180 // if it is unknown or and exact match was not found 181 func (t *rbTree) GetApproxPrevNext(entry RBEntry) (RBEntry, RBEntry, RBEntry, bool) { 182 if entry == nil { 183 return nil, nil, nil, false 184 } 185 ret := t.searchApprox(&rbNode{ 186 left: t.NIL, 187 right: t.NIL, 188 parent: t.NIL, 189 color: RED, 190 entry: entry, 191 }) 192 return ret.entry, t.predecessor(ret).entry, t.successor(ret).entry, 193 ret.entry.Compare(entry) == 0 194 } 195 196 func (t *rbTree) getInternal(entry RBEntry) (RBEntry, bool) { 197 if entry == nil { 198 return nil, false 199 } 200 ret := t.search(&rbNode{ 201 left: t.NIL, 202 right: t.NIL, 203 parent: t.NIL, 204 color: RED, 205 entry: entry, 206 }) 207 return ret.entry, ret.entry != nil 208 } 209 210 func (t *rbTree) Del(entry RBEntry) (RBEntry, bool) { 211 return t.delInternal(entry) 212 } 213 214 func (t *rbTree) delInternal(entry RBEntry) (RBEntry, bool) { 215 if entry == nil { 216 return nil, false 217 } 218 cnt := t.count 219 ret := t.delete(&rbNode{ 220 left: t.NIL, 221 right: t.NIL, 222 parent: t.NIL, 223 color: RED, 224 entry: entry, 225 }) 226 return ret.entry, cnt == t.count+1 227 } 228 229 func (t *rbTree) Len() int { 230 return t.count 231 } 232 233 // Size returns the size in bytes 234 func (t *rbTree) Size() int64 { 235 return t.size 236 } 237 238 func (t *rbTree) Min() (RBEntry, bool) { 239 x := t.min(t.root) 240 if x == t.NIL { 241 return nil, false 242 } 243 return x.entry, true 244 } 245 246 func (t *rbTree) Max() (RBEntry, bool) { 247 x := t.max(t.root) 248 if x == t.NIL { 249 return nil, false 250 } 251 return x.entry, true 252 } 253 254 // helper function for clone 255 func (t *rbTree) cloneEntries(t2 *rbTree) { 256 t.ascend(t.root, t.min(t.root).entry, func(e RBEntry) bool { 257 t2.putInternal(e) 258 return true 259 }) 260 } 261 262 type Iterator func(entry RBEntry) bool 263 264 func (t *rbTree) Scan(iter Iterator) { 265 t.ascend(t.root, t.min(t.root).entry, iter) 266 } 267 268 func (t *rbTree) ScanBack(iter Iterator) { 269 t.descend(t.root, t.max(t.root).entry, iter) 270 } 271 272 func (t *rbTree) ScanRange(start, end RBEntry, iter Iterator) { 273 t.ascendRange(t.root, start, end, iter) 274 } 275 276 func (t *rbTree) String() string { 277 var sb strings.Builder 278 t.ascend(t.root, t.min(t.root).entry, func(entry RBEntry) bool { 279 sb.WriteString(entry.String()) 280 return true 281 }) 282 return sb.String() 283 } 284 285 func (t *rbTree) Close() { 286 t.NIL = nil 287 t.root = nil 288 t.count = 0 289 return 290 } 291 292 func (t *rbTree) Reset() { 293 t.NIL = nil 294 t.root = nil 295 t.count = 0 296 runtime.GC() 297 n := &rbNode{ 298 left: nil, 299 right: nil, 300 parent: nil, 301 color: BLACK, 302 entry: empty, 303 } 304 t.NIL = n 305 t.root = n 306 t.count = 0 307 t.size = 0 308 } 309 310 func (t *rbTree) insert(z *rbNode) (*rbNode, bool) { 311 x := t.root 312 y := t.NIL 313 for x != t.NIL { 314 y = x 315 if compare(z.entry, x.entry) == -1 { 316 x = x.left 317 } else if compare(x.entry, z.entry) == -1 { 318 x = x.right 319 } else { 320 t.size -= int64(x.entry.Size()) 321 t.size += int64(z.entry.Size()) 322 // originally we were just returning x 323 // without updating the RBEntry, but if we 324 // want it to have similar behavior to 325 // a hashmap then we need to update any 326 // entries that already exist in the tree 327 x.entry = z.entry 328 return x, true // true means an existing 329 // value was found and updated. It should 330 // be noted that we don't need to re-balance 331 // the tree because they keys are not changing 332 // and the tree is balance is maintained by 333 // the keys and not their values. 334 } 335 } 336 z.parent = y 337 if y == t.NIL { 338 t.root = z 339 } else if compare(z.entry, y.entry) == -1 { 340 y.left = z 341 } else { 342 y.right = z 343 } 344 t.count++ 345 t.size += int64(z.entry.Size()) 346 t.insertFixup(z) 347 return z, false 348 } 349 350 func (t *rbTree) leftRotate(x *rbNode) { 351 if x.right == t.NIL { 352 return 353 } 354 y := x.right 355 x.right = y.left 356 if y.left != t.NIL { 357 y.left.parent = x 358 } 359 y.parent = x.parent 360 if x.parent == t.NIL { 361 t.root = y 362 } else if x == x.parent.left { 363 x.parent.left = y 364 } else { 365 x.parent.right = y 366 } 367 y.left = x 368 x.parent = y 369 } 370 371 func (t *rbTree) rightRotate(x *rbNode) { 372 if x.left == t.NIL { 373 return 374 } 375 y := x.left 376 x.left = y.right 377 if y.right != t.NIL { 378 y.right.parent = x 379 } 380 y.parent = x.parent 381 382 if x.parent == t.NIL { 383 t.root = y 384 } else if x == x.parent.left { 385 x.parent.left = y 386 } else { 387 x.parent.right = y 388 } 389 390 y.right = x 391 x.parent = y 392 } 393 394 func (t *rbTree) insertFixup(z *rbNode) { 395 for z.parent.color == RED { 396 if z.parent == z.parent.parent.left { 397 y := z.parent.parent.right 398 if y.color == RED { 399 z.parent.color = BLACK 400 y.color = BLACK 401 z.parent.parent.color = RED 402 z = z.parent.parent 403 } else { 404 if z == z.parent.right { 405 z = z.parent 406 t.leftRotate(z) 407 } 408 z.parent.color = BLACK 409 z.parent.parent.color = RED 410 t.rightRotate(z.parent.parent) 411 } 412 } else { 413 y := z.parent.parent.left 414 if y.color == RED { 415 z.parent.color = BLACK 416 y.color = BLACK 417 z.parent.parent.color = RED 418 z = z.parent.parent 419 } else { 420 if z == z.parent.left { 421 z = z.parent 422 t.rightRotate(z) 423 } 424 z.parent.color = BLACK 425 z.parent.parent.color = RED 426 t.leftRotate(z.parent.parent) 427 } 428 } 429 } 430 t.root.color = BLACK 431 } 432 433 // trying out a slightly different search method 434 // that (hopefully) will not return nil values and 435 // instead will return approximate node matches 436 func (t *rbTree) searchApprox(x *rbNode) *rbNode { 437 p := t.root 438 for p != t.NIL { 439 if compare(p.entry, x.entry) == -1 { 440 if p.right == t.NIL { 441 break 442 } 443 p = p.right 444 } else if compare(x.entry, p.entry) == -1 { 445 if p.left == t.NIL { 446 break 447 } 448 p = p.left 449 } else { 450 break 451 } 452 } 453 return p 454 } 455 456 func (t *rbTree) search(x *rbNode) *rbNode { 457 p := t.root 458 for p != t.NIL { 459 if compare(p.entry, x.entry) == -1 { 460 p = p.right 461 } else if compare(x.entry, p.entry) == -1 { 462 p = p.left 463 } else { 464 break 465 } 466 } 467 return p 468 } 469 470 // min traverses from root to left recursively until left is NIL 471 func (t *rbTree) min(x *rbNode) *rbNode { 472 if x == t.NIL { 473 return t.NIL 474 } 475 for x.left != t.NIL { 476 x = x.left 477 } 478 return x 479 } 480 481 // max traverses from root to right recursively until right is NIL 482 func (t *rbTree) max(x *rbNode) *rbNode { 483 if x == t.NIL { 484 return t.NIL 485 } 486 for x.right != t.NIL { 487 x = x.right 488 } 489 return x 490 } 491 492 func (t *rbTree) predecessor(x *rbNode) *rbNode { 493 if x == t.NIL { 494 return t.NIL 495 } 496 if x.left != t.NIL { 497 return t.max(x.left) 498 } 499 y := x.parent 500 for y != t.NIL && x == y.left { 501 x = y 502 y = y.parent 503 } 504 return y 505 } 506 507 func (t *rbTree) successor(x *rbNode) *rbNode { 508 if x == t.NIL { 509 return t.NIL 510 } 511 if x.right != t.NIL { 512 return t.min(x.right) 513 } 514 y := x.parent 515 for y != t.NIL && x == y.right { 516 x = y 517 y = y.parent 518 } 519 return y 520 } 521 522 func (t *rbTree) delete(key *rbNode) *rbNode { 523 z := t.search(key) 524 if z == t.NIL { 525 return t.NIL 526 } 527 ret := &rbNode{t.NIL, t.NIL, t.NIL, z.color, z.entry} 528 var y *rbNode 529 var x *rbNode 530 if z.left == t.NIL || z.right == t.NIL { 531 y = z 532 } else { 533 y = t.successor(z) 534 } 535 if y.left != t.NIL { 536 x = y.left 537 } else { 538 x = y.right 539 } 540 x.parent = y.parent 541 542 if y.parent == t.NIL { 543 t.root = x 544 } else if y == y.parent.left { 545 y.parent.left = x 546 } else { 547 y.parent.right = x 548 } 549 if y != z { 550 z.entry = y.entry 551 } 552 if y.color == BLACK { 553 t.deleteFixup(x) 554 } 555 t.size -= int64(ret.entry.Size()) 556 t.count-- 557 return ret 558 } 559 560 func (t *rbTree) deleteFixup(x *rbNode) { 561 for x != t.root && x.color == BLACK { 562 if x == x.parent.left { 563 w := x.parent.right 564 if w.color == RED { 565 w.color = BLACK 566 x.parent.color = RED 567 t.leftRotate(x.parent) 568 w = x.parent.right 569 } 570 if w.left.color == BLACK && w.right.color == BLACK { 571 w.color = RED 572 x = x.parent 573 } else { 574 if w.right.color == BLACK { 575 w.left.color = BLACK 576 w.color = RED 577 t.rightRotate(w) 578 w = x.parent.right 579 } 580 w.color = x.parent.color 581 x.parent.color = BLACK 582 w.right.color = BLACK 583 t.leftRotate(x.parent) 584 // this is to exit while loop 585 x = t.root 586 } 587 } else { 588 w := x.parent.left 589 if w.color == RED { 590 w.color = BLACK 591 x.parent.color = RED 592 t.rightRotate(x.parent) 593 w = x.parent.left 594 } 595 if w.left.color == BLACK && w.right.color == BLACK { 596 w.color = RED 597 x = x.parent 598 } else { 599 if w.left.color == BLACK { 600 w.right.color = BLACK 601 w.color = RED 602 t.leftRotate(w) 603 w = x.parent.left 604 } 605 w.color = x.parent.color 606 x.parent.color = BLACK 607 w.left.color = BLACK 608 t.rightRotate(x.parent) 609 x = t.root 610 } 611 } 612 } 613 x.color = BLACK 614 } 615 616 func (t *rbTree) ascend(x *rbNode, entry RBEntry, iter Iterator) bool { 617 if x == t.NIL { 618 return true 619 } 620 if !(compare(x.entry, entry) == -1) { 621 if !t.ascend(x.left, entry, iter) { 622 return false 623 } 624 if !iter(x.entry) { 625 return false 626 } 627 } 628 return t.ascend(x.right, entry, iter) 629 } 630 631 func (t *rbTree) __Descend(pivot RBEntry, iter Iterator) { 632 t.descend(t.root, pivot, iter) 633 } 634 635 func (t *rbTree) descend(x *rbNode, pivot RBEntry, iter Iterator) bool { 636 if x == t.NIL { 637 return true 638 } 639 if !(compare(pivot, x.entry) == -1) { 640 if !t.descend(x.right, pivot, iter) { 641 return false 642 } 643 if !iter(x.entry) { 644 return false 645 } 646 } 647 return t.descend(x.left, pivot, iter) 648 } 649 650 func (t *rbTree) ascendRange(x *rbNode, inf, sup RBEntry, iter Iterator) bool { 651 if x == t.NIL { 652 return true 653 } 654 if !(compare(x.entry, sup) == -1) { 655 return t.ascendRange(x.left, inf, sup, iter) 656 } 657 if compare(x.entry, inf) == -1 { 658 return t.ascendRange(x.right, inf, sup, iter) 659 } 660 if !t.ascendRange(x.left, inf, sup, iter) { 661 return false 662 } 663 if !iter(x.entry) { 664 return false 665 } 666 return t.ascendRange(x.right, inf, sup, iter) 667 }