github.com/scottcagno/storage@v1.8.0/pkg/lsmt/trees/bptree/bptree.go (about) 1 /* 2 * // Copyright (c) 2021. Scott Cagno. All rights reserved. 3 * // The license can be found in the root of this project; see LICENSE. 4 */ 5 6 package bptree 7 8 import ( 9 "encoding/binary" 10 "log" 11 "strconv" 12 "strings" 13 "unsafe" 14 ) 15 16 var stringZero = *new(string) 17 var ValTypeZero = *new([]byte) 18 19 func Compare(a, b string) int { 20 return strings.Compare(a, b) 21 } 22 23 func Equal(a, b string) bool { 24 return a == b 25 } 26 27 const ( 28 defaultOrder = orderSize32 29 orderSize4 = 4 30 orderSize8 = 8 31 orderSize16 = 16 32 orderSize32 = 32 33 orderSize64 = 64 34 orderSize128 = 128 35 orderSize256 = 256 36 orderSize512 = 512 37 ) 38 39 // bpNode represents a bpNode of the BPTree 40 type bpNode struct { 41 numKeys int 42 keys [defaultOrder - 1]string 43 pointers [defaultOrder]unsafe.Pointer 44 parent *bpNode 45 isLeaf bool 46 } 47 48 func (n *bpNode) hasKey(key string) bool { 49 if n.isLeaf { 50 for i := 0; i < n.numKeys; i++ { 51 if Equal(key, n.keys[i]) { 52 return true 53 } 54 } 55 } 56 return false 57 } 58 59 func (n *bpNode) closest(key string) (*entry, bool) { 60 if n.isLeaf { 61 i := 0 62 for ; i < n.numKeys; i++ { 63 if Compare(key, n.keys[i]) < 0 { 64 break 65 } 66 } 67 if i > 0 { 68 i-- 69 } 70 return (*entry)(n.pointers[i]), true 71 } 72 return nil, false 73 } 74 75 func (n *bpNode) record(key string) (*entry, bool) { 76 if n.isLeaf { 77 for i := 0; i < n.numKeys; i++ { 78 if Equal(key, n.keys[i]) { 79 return (*entry)(n.pointers[i]), true 80 } 81 } 82 } 83 return nil, false 84 } 85 86 // entry represents an entry pointed to by a leaf bpNode 87 type entry struct { 88 Key string 89 Value []byte 90 } 91 92 // BPTree represents the root of a b+tree 93 type BPTree struct { 94 root *bpNode 95 } 96 97 // NewBPTree creates and returns a new tree 98 func NewBPTree() *BPTree { 99 return new(BPTree) 100 } 101 102 // Has returns a boolean indicating weather or not 103 // the provided key and associated record exists. 104 func (t *BPTree) Has(key string) bool { 105 return t.findEntry(key) != nil 106 } 107 108 // HasInt tests and returns a boolean value if the 109 // provided key exists in the tree 110 func (t *BPTree) HasInt(key int64) bool { 111 return t.findEntry(IntToKey(key)) != nil 112 } 113 114 // Add inserts a new record using the provided key. It 115 // only inserts an entry if the key does not already exist. 116 func (t *BPTree) Add(key string, value []byte) { 117 // master insertUnique method only inserts if the key 118 // does not currently exist in the tree 119 t.insertUnique(key, value) 120 } 121 122 // AddInt inserts a new record using the provided integer key 123 // and value. It only inserts an entry if the key does not 124 // already exist. 125 func (t *BPTree) AddInt(key int64, value int64) { 126 // master insertUnique method only inserts if the key 127 // does not currently exist in the tree 128 t.insertUnique(IntToKey(key), IntToVal(value)) 129 } 130 131 // insertUnique inserts a new record using the provided key. It 132 // only inserts an entry if the key does not already exist. 133 func (t *BPTree) insertUnique(key string, value []byte) { 134 // If the tree is empty, start a new one and return. 135 if t.root == nil { 136 t.root = startNewTree(key, &entry{key, value}) 137 return 138 } 139 // If the tree already exists, let's see what we 140 // get when we try to find the correct leaf. 141 leaf := findLeaf(t.root, key) 142 // check to ensure the leaf node does already contain the key 143 if leaf.hasKey(key) { 144 return // Key already exists! So lets just return. 145 } 146 // If the tree already exists and the key has not been 147 // found, then let's insert it into the tree and return! 148 if leaf.numKeys < defaultOrder-1 { 149 insertIntoLeaf(leaf, key, &entry{key, value}) 150 return 151 } 152 // Otherwise, insert, split and balance returning the updated root. 153 t.root = insertIntoLeafAfterSplitting(t.root, leaf, key, &entry{key, value}) 154 } 155 156 // Put is mainly used when you wish to upsert as it assumes the 157 // data to already be contained the tree. It will overwrite 158 // duplicate keys, as it does not check to see if the key exists 159 func (t *BPTree) Put(key string, value []byte) bool { 160 // master insert method treats insertion much like 161 // "setting" in a hashmap (an upsert) by default 162 return t.insert(key, value) 163 } 164 165 // PutInt is mainly used when you wish to upsert as it assumes the 166 // data to already be contained the tree. It will overwrite 167 // duplicate keys, as it does not check to see if the key exists 168 func (t *BPTree) PutInt(key int64, value int64) bool { 169 // master insert method treats insertion much like 170 // "setting" in a hashmap (an upsert) by default 171 return t.insert(IntToKey(key), IntToVal(value)) 172 } 173 174 func (t *BPTree) GetClosest(key string) (string, []byte) { 175 l := findLeaf(t.root, key) 176 if l == nil { 177 return "", nil 178 } 179 e, ok := l.closest(key) 180 if !ok { 181 return "", nil 182 } 183 return e.Key, e.Value 184 } 185 186 // Get returns the record for a given key if it exists 187 func (t *BPTree) Get(key string) (string, []byte) { 188 e := t.findEntry(key) 189 if e == nil { 190 return "", nil 191 } 192 return e.Key, e.Value 193 } 194 195 // GetInt returns the record for a given key if it exists 196 func (t *BPTree) GetInt(key int64) (int64, int64) { 197 e := t.findEntry(IntToKey(key)) 198 if e == nil { 199 return -1, -1 200 } 201 return KeyToInt(e.Key), ValToInt(e.Value) 202 } 203 204 func (t *BPTree) Del(key string) (string, []byte) { 205 e := t.delete(key) 206 if e == nil { 207 return "", nil 208 } 209 return e.Key, e.Value 210 } 211 212 func (t *BPTree) DelInt(key int64) (int64, int64) { 213 e := t.delete(IntToKey(key)) 214 if e == nil { 215 return -1, -1 216 } 217 return KeyToInt(e.Key), ValToInt(e.Value) 218 } 219 220 func (t *BPTree) Range(iter func(k string, v []byte) bool) { 221 c := findFirstLeaf(t.root) 222 if c == nil { 223 return 224 } 225 var e *entry 226 for { 227 for i := 0; i < c.numKeys; i++ { 228 e = (*entry)(c.pointers[i]) 229 if e != nil && !iter(e.Key, e.Value) { 230 continue 231 } 232 } 233 if c.pointers[defaultOrder-1] != nil { 234 c = (*bpNode)(c.pointers[defaultOrder-1]) 235 } else { 236 break 237 } 238 } 239 } 240 241 func (t *BPTree) Min() (string, []byte) { 242 c := findFirstLeaf(t.root) 243 if c == nil { 244 return "", nil 245 } 246 e := (*entry)(c.pointers[0]) 247 return e.Key, e.Value 248 } 249 250 func (t *BPTree) Max() (string, []byte) { 251 c := findLastLeaf(t.root) 252 if c == nil { 253 return "", nil 254 } 255 e := (*entry)(c.pointers[c.numKeys-1]) 256 return e.Key, e.Value 257 } 258 259 func (t *BPTree) Len() int { 260 var count int 261 for n := findFirstLeaf(t.root); n != nil; n = n.nextLeaf() { 262 count += n.numKeys 263 } 264 return count 265 } 266 267 func (t *BPTree) Size() int64 { 268 c := findFirstLeaf(t.root) 269 if c == nil { 270 return 0 271 } 272 var s int64 273 var e *entry 274 for { 275 for i := 0; i < c.numKeys; i++ { 276 e = (*entry)(c.pointers[i]) 277 if e != nil { 278 s += int64(len(e.Key) + len(e.Value)) 279 } 280 } 281 if c.pointers[defaultOrder-1] != nil { 282 c = (*bpNode)(c.pointers[defaultOrder-1]) 283 } else { 284 break 285 } 286 } 287 return s 288 } 289 290 func (t *BPTree) Close() { 291 //t.destroyTree() 292 t.root = nil 293 } 294 295 // insert is the "master" insertion function. 296 // Inserts a key and an associated Value into 297 // the B+ tree, causing the tree to be adjusted 298 // however necessary to maintain the B+ tree 299 // properties 300 func (t *BPTree) insert(key string, value []byte) bool { 301 302 // CASE: BPTree does not exist yet, start a new tree 303 if t.root == nil { 304 t.root = startNewTree(key, &entry{key, value}) 305 return false 306 } 307 308 // The current implementation ignores duplicates (will treat it kind of like a set operation) 309 leaf, recordPointer := t.find(key) 310 if recordPointer != nil { 311 312 // If the key already exists in this tree then proceed to update Value and return 313 recordPointer.Value = value 314 return true 315 } 316 317 // No Record found, so create a new Record for the Value. NOTE: Normally t.find would not return 318 // a record pointer in which case we would need the line below this. 319 //recordPointer = makeRecord(Value) 320 321 // CASE: BPTree already exists (continue through the rest of the function) 322 323 // Leaf has room for the key and recordPointer--insert into leaf and return 324 if leaf.numKeys < defaultOrder-1 { 325 insertIntoLeaf(leaf, key, &entry{key, value}) 326 return false 327 } 328 329 // Leaf does not have enough room and needs to be split 330 t.root = insertIntoLeafAfterSplitting(t.root, leaf, key, &entry{key, value}) 331 return false 332 } 333 334 // startNewTree first insertion case: starts a new tree 335 func startNewTree(key string, pointer *entry) *bpNode { 336 root := &bpNode{isLeaf: true} // makeLeaf() 337 root.keys[0] = key 338 root.pointers[0] = unsafe.Pointer(pointer) 339 root.pointers[defaultOrder-1] = nil 340 root.parent = nil 341 root.numKeys++ 342 return root 343 } 344 345 // insertIntoNewRoot creates a new root for two subtrees and inserts the appropriate key into the new root 346 func insertIntoNewRoot(left *bpNode, key string, right *bpNode) *bpNode { 347 root := &bpNode{} // makeNode() 348 root.keys[0] = key 349 root.pointers[0] = unsafe.Pointer(left) 350 root.pointers[1] = unsafe.Pointer(right) 351 root.numKeys++ 352 root.parent = nil 353 left.parent = root 354 right.parent = root 355 return root 356 } 357 358 /* 359 * insertIntoParent inserts a new bpNode (leaf or internal bpNode) into the tree--returns the root of 360 * the tree after insertion is complete 361 */ 362 func insertIntoParent(root *bpNode, left *bpNode, key string, right *bpNode) *bpNode { 363 364 /* 365 * Case: new root 366 */ 367 if left.parent == nil { 368 return insertIntoNewRoot(left, key, right) 369 } 370 371 /* 372 * Case: leaf or bpNode. (Remainder of function body.) 373 * Find the parents pointer to the left bpNode 374 */ 375 leftIndex := getLeftIndex(left.parent, left) 376 377 /* 378 * Simple case: the new key fits into the bpNode. 379 */ 380 if left.parent.numKeys < defaultOrder-1 { 381 return insertIntoNode(root, left.parent, leftIndex, key, right) 382 } 383 384 /* Harder case: split a bpNode in order 385 * to preserve the B+ tree properties. 386 */ 387 return insertIntoNodeAfterSplitting(root, left.parent, leftIndex, key, right) 388 } 389 390 /* 391 * getLeftIndex helper function used in insertIntoParent to find the index of the parents 392 * pointer to the bpNode to the left of the key to be inserted 393 */ 394 func getLeftIndex(parent, left *bpNode) int { 395 var leftIndex int 396 for leftIndex <= parent.numKeys && (*bpNode)(parent.pointers[leftIndex]) != left { 397 leftIndex++ 398 } 399 return leftIndex 400 } 401 402 /* 403 * insertIntoNode inserts a new key and pointer to a bpNode into a bpNode into which these can fit without violating the 404 * tree's properties 405 */ 406 func insertIntoNode(root, n *bpNode, leftIndex int, key string, right *bpNode) *bpNode { 407 // Consider using copy, it might be better 408 copy(n.pointers[leftIndex+2:], n.pointers[leftIndex+1:]) 409 copy(n.keys[leftIndex+1:], n.keys[leftIndex:]) 410 411 /* // ORIG 412 for i := n.numKeys; i > leftIndex; i-- { 413 n.pointers[i+1] = n.pointers[i] 414 n.keys[i] = n.keys[i-1] 415 } 416 */ 417 418 n.pointers[leftIndex+1] = unsafe.Pointer(right) 419 n.keys[leftIndex] = key 420 n.numKeys++ 421 return root 422 } 423 424 // insertIntoNodeAfterSplitting inserts a new key and pointer to a bpNode into a bpNode, causing 425 // the nodes size to exceed the ORDER, and causing the bpNode to split 426 func insertIntoNodeAfterSplitting(root, oldNode *bpNode, leftIndex int, key string, right *bpNode) *bpNode { 427 428 // first create a temp set of keys and pointers to hold everything in ORDER, including 429 // the new key and pointer, inserted in their correct places--then create a new bpNode 430 // and copy half of the keys and pointers to the old bpNode and the other half to the new 431 432 var i, j int 433 var tempKeys [defaultOrder]string //tempKeys := make([]int, ORDER) 434 var tempPointers [defaultOrder + 1]unsafe.Pointer //tempPointers := make([]interface{}, ORDER+1) 435 436 for i, j = 0, 0; i < oldNode.numKeys+1; i, j = i+1, j+1 { 437 if j == leftIndex+1 { 438 j++ 439 } 440 tempPointers[j] = oldNode.pointers[i] 441 } 442 443 for i, j = 0, 0; i < oldNode.numKeys; i, j = i+1, j+1 { 444 if j == leftIndex { 445 j++ 446 } 447 tempKeys[j] = oldNode.keys[i] 448 } 449 450 tempPointers[leftIndex+1] = unsafe.Pointer(right) 451 tempKeys[leftIndex] = key 452 453 /* 454 * copy half the keys and pointers to the old bpNode... 455 */ 456 split := cut(defaultOrder) 457 458 oldNode.numKeys = 0 459 460 for i = 0; i < split-1; i++ { 461 oldNode.pointers[i] = tempPointers[i] 462 oldNode.keys[i] = tempKeys[i] 463 oldNode.numKeys++ 464 } 465 oldNode.pointers[i] = tempPointers[i] 466 kPrime := tempKeys[split-1] 467 468 /* 469 * ...create the new bpNode and copy the other half the keys and pointers 470 */ 471 newNode := &bpNode{} // makeNode() 472 473 for i, j = i+1, 0; i < defaultOrder; i, j = i+1, j+1 { 474 newNode.pointers[j] = tempPointers[i] 475 newNode.keys[j] = tempKeys[i] 476 newNode.numKeys++ 477 } 478 newNode.pointers[j] = tempPointers[i] 479 newNode.parent = oldNode.parent 480 481 /* 482 * Free up tempPointers and tempKeys 483 */ 484 for i = 0; i < defaultOrder; i++ { 485 tempKeys[i] = *new(string) // zero values 486 tempPointers[i] = nil // zero values 487 } 488 tempPointers[defaultOrder] = nil 489 490 var child *bpNode 491 for i = 0; i <= newNode.numKeys; i++ { 492 child = (*bpNode)(newNode.pointers[i]) 493 child.parent = newNode 494 } 495 496 /* Insert a new key into the parent of the two 497 * nodes resulting from the split, with 498 * the old bpNode to the left and the new to the right. 499 */ 500 return insertIntoParent(root, oldNode, kPrime, newNode) 501 } 502 503 // insertIntoLeaf inserts a new pointer to a Record and its 504 // corresponding key into a leaf. 505 func insertIntoLeaf(leaf *bpNode, key string, pointer *entry) /* *bpNode */ { 506 var i, insertionPoint int 507 for insertionPoint < leaf.numKeys && Compare(leaf.keys[insertionPoint], key) == -1 { 508 insertionPoint++ 509 } 510 for i = leaf.numKeys; i > insertionPoint; i-- { 511 leaf.keys[i] = leaf.keys[i-1] 512 leaf.pointers[i] = leaf.pointers[i-1] 513 } 514 leaf.keys[insertionPoint] = key 515 leaf.pointers[insertionPoint] = unsafe.Pointer(pointer) 516 leaf.numKeys++ 517 //return leaf // might not need to return this leaf 518 } 519 520 // insertIntoLeafAfterSplitting inserts a new key and pointer to a new Record into a leaf 521 // so as to exceed the tree's ORDER, causing the leaf to be split in half 522 func insertIntoLeafAfterSplitting(root, leaf *bpNode, key string, pointer *entry) *bpNode { 523 524 // perform linear search to find index to insert new record 525 var insertionIndex int 526 for insertionIndex < defaultOrder-1 && Compare(leaf.keys[insertionIndex], key) == -1 { 527 insertionIndex++ 528 } 529 530 var i, j int 531 var tempKeys [defaultOrder]string 532 var tempPointers [defaultOrder]unsafe.Pointer 533 534 // copy leaf keys and pointers to temp sets 535 // reserve space at insertion index for new record 536 for i, j = 0, 0; i < leaf.numKeys; i, j = i+1, j+1 { 537 if j == insertionIndex { 538 j++ 539 } 540 tempKeys[j] = leaf.keys[i] 541 tempPointers[j] = leaf.pointers[i] 542 } 543 544 tempKeys[insertionIndex] = key 545 tempPointers[insertionIndex] = unsafe.Pointer(pointer) 546 547 leaf.numKeys = 0 548 549 // find pivot index where to split leaf 550 split := cut(defaultOrder - 1) 551 552 // overwrite original leaf up to the split point 553 for i = 0; i < split; i++ { 554 leaf.keys[i] = tempKeys[i] 555 leaf.pointers[i] = tempPointers[i] 556 leaf.numKeys++ 557 } 558 559 // create new leaf 560 newLeaf := &bpNode{isLeaf: true} // makeLeaf() 561 562 // writing to new leaf from split point to end of original leaf pre split 563 for i, j = split, 0; i < defaultOrder; i, j = i+1, j+1 { 564 newLeaf.keys[j] = tempKeys[i] 565 newLeaf.pointers[j] = tempPointers[i] 566 newLeaf.numKeys++ 567 } 568 569 // free temps 570 for i = 0; i < defaultOrder; i++ { 571 tempKeys[i] = *new(string) // zero Value 572 tempPointers[i] = nil // zero Value 573 } 574 575 newLeaf.pointers[defaultOrder-1] = leaf.pointers[defaultOrder-1] 576 leaf.pointers[defaultOrder-1] = unsafe.Pointer(newLeaf) 577 578 for i = leaf.numKeys; i < defaultOrder-1; i++ { 579 leaf.pointers[i] = nil 580 } 581 for i = newLeaf.numKeys; i < defaultOrder-1; i++ { 582 newLeaf.pointers[i] = nil 583 } 584 585 newLeaf.parent = leaf.parent 586 newKey := newLeaf.keys[0] 587 588 return insertIntoParent(root, leaf, newKey, newLeaf) 589 } 590 591 /* 592 * findRecord finds and returns the Record to which a key refers 593 */ 594 func (t *BPTree) find(key string) (*bpNode, *entry) { 595 leaf := findLeaf(t.root, key) 596 if leaf == nil { 597 return nil, nil 598 } 599 /* 600 * If root/leaf != nil, leaf must have a Value, even if it does not contain the desired key. 601 * The leaf holds the range of keys that would include the desired key 602 */ 603 var i int 604 for i = 0; i < leaf.numKeys; i++ { 605 if Equal(leaf.keys[i], key) { 606 break 607 } 608 } 609 if i == leaf.numKeys { 610 return leaf, nil 611 } 612 return leaf, (*entry)(leaf.pointers[i]) 613 } 614 615 /* 616 * findEntry finds and returns the entry to which a key refers 617 */ 618 func (t *BPTree) findEntry(key string) *entry { 619 leaf := findLeaf(t.root, key) 620 if leaf == nil { 621 return nil 622 } 623 /* 624 * If root/leaf != nil, leaf must have a Value, even if it does not contain the desired key. 625 * The leaf holds the range of keys that would include the desired key 626 */ 627 var i int 628 for i = 0; i < leaf.numKeys; i++ { 629 if Equal(leaf.keys[i], key) { 630 break 631 } 632 } 633 if i == leaf.numKeys { 634 return nil 635 } 636 return (*entry)(leaf.pointers[i]) 637 } 638 639 /* 640 * findLeaf traces the path from the root to a leaf, searching by key and displaying information about the path if the 641 * verbose flag is set--findLeaf returns the leaf containing the given key 642 */ 643 func findLeaf(root *bpNode, key string) *bpNode { 644 if root == nil { 645 return root 646 } 647 i, c := 0, root 648 for !c.isLeaf { 649 i = 0 650 for i < c.numKeys { 651 if Compare(key, c.keys[i]) >= 0 { 652 i++ 653 } else { 654 break 655 } 656 } 657 c = (*bpNode)(c.pointers[i]) 658 } 659 // c is the found leaf bpNode 660 return c 661 } 662 663 /* 664 * findFirstLeaf traces the path from the root to the leftmost leaf in the tree 665 */ 666 func findFirstLeaf(root *bpNode) *bpNode { 667 if root == nil { 668 return root 669 } 670 c := root 671 for !c.isLeaf { 672 c = (*bpNode)(c.pointers[0]) 673 } 674 return c 675 } 676 677 func findLastLeaf(root *bpNode) *bpNode { 678 if root == nil { 679 return root 680 } 681 c := root 682 for !c.isLeaf { 683 c = (*bpNode)(c.pointers[c.numKeys]) 684 } 685 return c 686 } 687 688 /* 689 * nextLeaf returns the next non-nil leaf in the chain (to the right) of the current leaf 690 */ 691 func (n *bpNode) nextLeaf() *bpNode { 692 if p := (*bpNode)(n.pointers[defaultOrder-1]); p != nil && p.isLeaf { 693 return p 694 } 695 return nil 696 } 697 698 /* 699 * delete is the master delete function 700 */ 701 func (t *BPTree) delete(key string) *entry { 702 var old *entry 703 keyLeaf, keyEntry := t.find(key) 704 if keyEntry != nil && keyLeaf != nil { 705 t.root = deleteEntry(t.root, keyLeaf, key, unsafe.Pointer(keyEntry)) 706 old = keyEntry 707 keyEntry = nil 708 } 709 return old // return the old entry we just deleted 710 } 711 712 /* 713 * getNeighborIndex is a utility function for deletion. It gets the index of a bpNode's nearest 714 * sibling (that exists) to the left. If not then bpNode is already the leftmost child and (in 715 * such a case the bpNode) will return -1 716 */ 717 func getNeighborIndex(n *bpNode) int { 718 var i int 719 for i = 0; i <= n.parent.numKeys; i++ { 720 if (*bpNode)(n.parent.pointers[i]) == n { 721 return i - 1 722 } 723 } 724 log.Panicf("getNeighborIndex: Search for nonexistent pointer to bpNode in parent.\nNode: %#v\n", n) 725 return i 726 } 727 728 /* 729 * removeEntryFromNode does just that 730 */ 731 func removeEntryFromNode(n *bpNode, key string, pointer unsafe.Pointer) *bpNode { 732 733 /* 734 * Remove the key and shift the other keys accordingly 735 */ 736 var i, numPointers int 737 for !Equal(n.keys[i], key) { 738 i++ 739 } 740 for i++; i < n.numKeys; i++ { // was for i+=1; 741 n.keys[i-1] = n.keys[i] 742 } 743 744 /* 745 * Remove the pointer and shift other pointers accordingly 746 */ 747 if n.isLeaf { 748 numPointers = n.numKeys 749 } else { 750 numPointers = n.numKeys + 1 751 } 752 753 i = 0 754 for n.pointers[i] != pointer { 755 i++ 756 } 757 for i++; i < numPointers; i++ { // was for i+=1; 758 n.pointers[i-1] = n.pointers[i] 759 } 760 761 /* 762 * One key fewer 763 */ 764 n.numKeys-- 765 766 /* 767 * Set the other pointers to nil for tidiness. A leaf uses 768 * the last pointer to point to the next leaf 769 */ 770 if n.isLeaf { 771 for i = n.numKeys; i < defaultOrder-1; i++ { 772 n.pointers[i] = nil 773 } 774 } else { 775 for i = n.numKeys + 1; i < defaultOrder; i++ { 776 n.pointers[i] = nil 777 } 778 } 779 return n 780 } 781 782 /* 783 * deleteEntry deletes and entry from the tree. Removes the Record and it's key and pointer from 784 * the leaf, and then makes all appropriate changes to preserve the tree's properties 785 */ 786 func deleteEntry(root, n *bpNode, key string, pointer unsafe.Pointer) *bpNode { 787 788 var minKeys, kPrimeIndex, capacity int 789 790 /* 791 * Remove key and pointer from bpNode 792 */ 793 n = removeEntryFromNode(n, key, pointer) 794 795 /* 796 * CASE: deletion from the root bpNode 797 */ 798 if n == root { 799 return adjustRoot(root) 800 } 801 802 /* 803 * CASE: deletion from a bpNode below the root (continue rest of function) 804 * 805 * Determine minimum allowable size of bpNode to be preserved after deletion 806 */ 807 if n.isLeaf { 808 minKeys = cut(defaultOrder - 1) 809 } else { 810 minKeys = cut(defaultOrder) - 1 811 } 812 813 /* 814 * CASE: bpNode stays at or above minimum (simple case) 815 */ 816 if n.numKeys >= minKeys { 817 return root 818 } 819 820 /* 821 * CASE: bpNode falls below minimum. Either coalescence or redistribution is needed 822 * 823 * Find the appropriate neighbor bpNode with which to coalesce. Also find the key (kPrime) 824 * in the parent between the pointer to bpNode n and the pointer to the neighbor 825 */ 826 neighborIndex := getNeighborIndex(n) 827 if neighborIndex == -1 { 828 kPrimeIndex = 0 829 } else { 830 kPrimeIndex = neighborIndex 831 } 832 833 kPrime := n.parent.keys[kPrimeIndex] 834 835 var neighbor *bpNode 836 if neighborIndex == -1 { 837 neighbor = (*bpNode)(n.parent.pointers[1]) 838 } else { 839 neighbor = (*bpNode)(n.parent.pointers[neighborIndex]) 840 } 841 842 if n.isLeaf { 843 capacity = defaultOrder 844 } else { 845 capacity = defaultOrder - 1 846 } 847 848 /* 849 * Coalescence 850 */ 851 if neighbor.numKeys+n.numKeys < capacity { 852 return coalesceNodes(root, n, neighbor, neighborIndex, kPrime) 853 } 854 855 /*S 856 * Redistribution 857 */ 858 return redistributeNodes(root, n, neighbor, neighborIndex, kPrimeIndex, kPrime) 859 } 860 861 /* 862 * adjustRoot does some magic in the root bpNode (not really) 863 */ 864 func adjustRoot(root *bpNode) *bpNode { 865 /* 866 * CASE: nonempty root. key and pointer have already been deleted, so nothing to be done 867 */ 868 if root.numKeys > 0 { 869 return root 870 } 871 872 /* 873 * CASE: empty root. If it has a child, promote the first (only) child as the new root 874 */ 875 var newRoot *bpNode 876 if !root.isLeaf { 877 newRoot = (*bpNode)(root.pointers[0]) 878 newRoot.parent = nil 879 } else { 880 /* 881 * If it is a leaf (has no children), then the whole tree is in fact empty 882 */ 883 newRoot = nil // free 884 } 885 root = nil 886 return newRoot 887 } 888 889 /* 890 * coalesceNodes coalesces a bpNode that has become too small after deletion with a 891 * neighboring bpNode that can accept the additional entries without exceeing the maximum 892 */ 893 func coalesceNodes(root, n, neighbor *bpNode, neighborIndex int, kPrime string) *bpNode { 894 895 var tmp *bpNode 896 897 /* 898 * Swap neighbor with bpNode if bpNode is on the extreme left and neighbor is to it's right 899 */ 900 if neighborIndex == -1 { 901 tmp = n 902 n = neighbor 903 neighbor = tmp 904 } 905 906 /* 907 * Starting point in the neighbor for copying keys and pointers from n. Recall that n and 908 * neighbor have swapped places in the special case of n being a leftmost child 909 */ 910 neighborInsertionIndex := neighbor.numKeys 911 var i, j, nEnd int 912 913 /* 914 * CASE: Nonleaf bpNode. Append kPrime and the following pointer and append all pointers and keys from the neighbor 915 */ 916 if !n.isLeaf { 917 /* 918 * Append kPrime 919 */ 920 neighbor.keys[neighborInsertionIndex] = kPrime 921 neighbor.numKeys++ 922 nEnd = n.numKeys 923 924 for i, j = neighborInsertionIndex+1, 0; j < nEnd; i, j = i+1, j+1 { 925 neighbor.keys[i] = n.keys[j] 926 neighbor.pointers[i] = n.pointers[j] 927 neighbor.numKeys++ 928 n.numKeys-- 929 } 930 931 /* 932 * The number of pointers is always one more than the number of keys 933 */ 934 neighbor.pointers[i] = n.pointers[j] 935 936 /* 937 * All children must now point up to the same parent 938 */ 939 for i = 0; i < neighbor.numKeys+1; i++ { 940 tmp = (*bpNode)(neighbor.pointers[i]) 941 tmp.parent = neighbor 942 } 943 /* 944 * CASE: In a leaf, append the keys and pointers of n to the neighbor. 945 * Set the neighbor's last pointer to point to what had been n's right neighbor. 946 */ 947 } else { 948 for i, j = neighborInsertionIndex, 0; j < n.numKeys; i, j = i+1, j+1 { 949 neighbor.keys[i] = n.keys[j] 950 neighbor.pointers[i] = n.pointers[j] 951 neighbor.numKeys++ 952 } 953 neighbor.pointers[defaultOrder-1] = n.pointers[defaultOrder-1] 954 } 955 root = deleteEntry(root, n.parent, kPrime, unsafe.Pointer(n)) 956 n = nil // free 957 return root 958 } 959 960 /* 961 * redistributeNodes redistributes entries between two nodes when one has become too small 962 * after deletion but its neighbor is too big to append the small bpNode's entries without 963 * exceeding the maximum 964 */ 965 func redistributeNodes(root, n, neighbor *bpNode, neighborIndex, kPrimeIndex int, kPrime string) *bpNode { 966 967 var i int 968 var tmp *bpNode 969 970 /* 971 * CASE: n has a neighbor to the left. Pull the neighbor's last key-pointer pair over 972 * from the neighbor's right end to n's lef end 973 */ 974 if neighborIndex != -1 { 975 if !n.isLeaf { 976 n.pointers[n.numKeys+1] = n.pointers[n.numKeys] 977 } 978 for i = n.numKeys; i > 0; i-- { 979 n.keys[i] = n.keys[i-1] 980 n.pointers[i] = n.pointers[i-1] 981 } 982 if !n.isLeaf { 983 n.pointers[0] = neighbor.pointers[neighbor.numKeys] 984 tmp = (*bpNode)(n.pointers[0]) 985 tmp.parent = n 986 neighbor.pointers[neighbor.numKeys] = nil 987 n.keys[0] = kPrime 988 n.parent.keys[kPrimeIndex] = neighbor.keys[neighbor.numKeys-1] 989 } else { 990 n.pointers[0] = neighbor.pointers[neighbor.numKeys-1] 991 neighbor.pointers[neighbor.numKeys-1] = nil 992 n.keys[0] = neighbor.keys[neighbor.numKeys-1] 993 n.parent.keys[kPrimeIndex] = n.keys[0] 994 } 995 996 /* 997 * CASE: n is the leftmost child. Take a key-pointer pair from the neighbor 998 * to the right. Move the neighbor's leftmost key-pointer pair to n's rightmost position 999 */ 1000 } else { 1001 if n.isLeaf { 1002 n.keys[n.numKeys] = neighbor.keys[0] 1003 n.pointers[n.numKeys] = neighbor.pointers[0] 1004 n.parent.keys[kPrimeIndex] = neighbor.keys[1] 1005 } else { 1006 n.keys[n.numKeys] = kPrime 1007 n.pointers[n.numKeys+1] = neighbor.pointers[0] 1008 tmp = (*bpNode)(n.pointers[n.numKeys+1]) 1009 tmp.parent = n 1010 n.parent.keys[kPrimeIndex] = neighbor.keys[0] 1011 } 1012 for i = 0; i < neighbor.numKeys-1; i++ { 1013 neighbor.keys[i] = neighbor.keys[i+1] 1014 neighbor.pointers[i] = neighbor.pointers[i+1] 1015 } 1016 if !n.isLeaf { 1017 neighbor.pointers[i] = neighbor.pointers[i+1] 1018 } 1019 } 1020 1021 /* 1022 * n now has one more key and one more pointer; the neighbor has one fewer of each 1023 */ 1024 n.numKeys++ 1025 neighbor.numKeys-- 1026 return root 1027 } 1028 1029 func destroyTreeNodes(n *bpNode) { 1030 if n == nil { 1031 return 1032 } 1033 if n.isLeaf { 1034 for i := 0; i < n.numKeys; i++ { 1035 n.pointers[i] = nil 1036 } 1037 } else { 1038 for i := 0; i < n.numKeys+1; i++ { 1039 destroyTreeNodes((*bpNode)(n.pointers[i])) 1040 } 1041 } 1042 n = nil 1043 } 1044 1045 func (t *BPTree) destroyTree() { 1046 destroyTreeNodes(t.root) 1047 } 1048 1049 /* 1050 * cut finds the appropriate place to split a bpNode that is too big 1051 */ 1052 func cut(length int) int { 1053 if length%2 == 0 { 1054 return length / 2 1055 } 1056 return length/2 + 1 1057 } 1058 1059 // makeRecord create a new Record to hold the Value to which a key refers 1060 func makeRecord(value []byte) *entry { 1061 return &entry{ 1062 Value: value, 1063 } 1064 } 1065 1066 // makeNode creates a new general bpNode, which can be adapted to serve as either a leaf or internal bpNode 1067 func makeNode() *bpNode { 1068 return &bpNode{} 1069 } 1070 1071 // makeLeaf creates a new leaf by creating a bpNode and then adapting it appropriately 1072 func makeLeaf() *bpNode { 1073 leaf := &bpNode{} // makeNode() 1074 leaf.isLeaf = true 1075 return leaf 1076 } 1077 1078 func Btoi(b []byte) int64 { 1079 return int64(b[7]) | 1080 int64(b[6])<<8 | 1081 int64(b[5])<<16 | 1082 int64(b[4])<<24 | 1083 int64(b[3])<<32 | 1084 int64(b[2])<<40 | 1085 int64(b[1])<<48 | 1086 int64(b[0])<<56 1087 } 1088 1089 func Itob(i int64) []byte { 1090 return []byte{ 1091 byte(i >> 56), 1092 byte(i >> 48), 1093 byte(i >> 40), 1094 byte(i >> 32), 1095 byte(i >> 24), 1096 byte(i >> 16), 1097 byte(i >> 8), 1098 byte(i), 1099 } 1100 } 1101 1102 func IntToKey(key int64) string { 1103 return "i" + strconv.FormatInt(key, 10) 1104 } 1105 1106 func KeyToInt(key string) int64 { 1107 if len(key) != 11 || key[0] != 'i' { 1108 return -1 1109 } 1110 ikey, err := strconv.ParseInt(key[1:], 10, 0) 1111 if err != nil { 1112 return -1 1113 } 1114 return ikey 1115 } 1116 1117 func IntToVal(val int64) []byte { 1118 buf := make([]byte, 1+binary.MaxVarintLen64) 1119 buf[0] = 'i' 1120 _ = binary.PutVarint(buf[1:], val) 1121 return buf 1122 } 1123 1124 func ValToInt(val []byte) int64 { 1125 if len(val) != 11 || val[0] != 'i' { 1126 return -1 1127 } 1128 ival, n := binary.Varint(val[1:]) 1129 if ival == 0 && n <= 0 { 1130 return -1 1131 } 1132 return ival 1133 }