1 21 22 package org.apache.derby.impl.store.access.sort; 23 24 import org.apache.derby.iapi.services.sanity.SanityManager; 25 import org.apache.derby.iapi.error.StandardException; 26 import org.apache.derby.iapi.store.access.SortObserver; 27 28 import org.apache.derby.iapi.types.DataValueDescriptor; 29 30 42 43 class SortBuffer 44 { 45 49 public static final int INSERT_OK = 0; 50 51 56 public static final int INSERT_DUPLICATE = 1; 57 58 62 public static final int INSERT_FULL = 2; 63 64 67 private MergeSort sort; 68 69 72 private NodeAllocator allocator = null; 73 74 78 private Node head = null; 79 80 83 private int height = 0; 84 85 90 private DataValueDescriptor[] deletedKey; 91 92 98 private boolean subtreeShrunk; 99 100 104 private int nextAux; 105 106 110 private int lastAux; 111 112 116 public void setNextAux(int aux) 117 { 118 nextAux = aux; 119 } 120 121 125 public int getLastAux() 126 { 127 return lastAux; 128 } 129 130 134 public SortBuffer(MergeSort sort) 135 { 136 this.sort = sort; 137 } 138 139 143 public boolean init() 144 { 145 allocator = new NodeAllocator(); 146 147 boolean initOK = false; 148 149 if (sort.sortBufferMin > 0) 150 initOK = allocator.init(sort.sortBufferMin, sort.sortBufferMax); 151 else 152 initOK = allocator.init(sort.sortBufferMax); 153 154 if (initOK == false) 155 { 156 allocator = null; 157 return false; 158 } 159 reset(); 160 return true; 161 } 162 163 public void reset() 164 { 165 allocator.reset(); 166 head = allocator.newNode(); 167 height = 0; 168 } 169 170 public void close() 171 { 172 if (allocator != null) 173 allocator.close(); 174 allocator = null; 175 height = 0; 176 head = null; 177 } 178 179 182 public void grow(int percent) 183 { 184 if (percent > 0) 185 allocator.grow(percent); 186 } 187 188 189 194 public int capacity() 195 { 196 if (allocator == null) 197 return 0; 198 return allocator.capacity() - 1; 199 } 200 201 208 public int insert(DataValueDescriptor[] k) 209 throws StandardException 210 { 211 int c; 212 Node p, q, r, s, t; 213 214 if (head.rightLink == null) 215 { 216 if ((sort.sortObserver != null) && 217 ((k = sort.sortObserver.insertNonDuplicateKey(k)) == null)) 218 { 219 return INSERT_DUPLICATE; 220 } 221 222 q = allocator.newNode(); 223 q.key = k; 224 q.aux = nextAux; 225 head.rightLink = q; 226 height = 1; 227 return INSERT_OK; 228 } 229 230 t = head; 232 p = s = head.rightLink; 233 234 while (true) 236 { 237 c = sort.compare(k, p.key); 239 if (c == 0) 240 { 241 244 if ((sort.sortObserver != null) && 247 ((k = sort.sortObserver.insertDuplicateKey(k, p.key)) == null)) 248 { 249 return INSERT_DUPLICATE; 250 } 251 252 q = allocator.newNode(); 255 if (q == null) 256 return INSERT_FULL; 257 q.aux = nextAux; 258 259 q.key = k; 264 q.dupChain = p.dupChain; 265 p.dupChain = q; 266 267 return INSERT_OK; 270 } 271 272 if (c < 0) 273 { 274 q = p.leftLink; 276 if (q == null) 277 { 278 q = allocator.newNode(); 279 if (q == null) 280 return INSERT_FULL; 281 q.aux = nextAux; 282 p.leftLink = q; 283 break; 284 } 285 } 286 else { 288 q = p.rightLink; 290 if (q == null) 291 { 292 q = allocator.newNode(); 293 if (q == null) 294 return INSERT_FULL; 295 q.aux = nextAux; 296 p.rightLink = q; 297 break; 298 } 299 } 300 301 if (q.balance != 0) 302 { 303 t = p; 304 s = q; 305 } 306 p = q; 307 } 308 309 314 315 if ((sort.sortObserver != null) && 316 ((k = sort.sortObserver.insertNonDuplicateKey(k)) == null)) 317 { 318 return INSERT_DUPLICATE; 319 } 320 q.key = k; 321 322 326 327 c = sort.compare(k, s.key); 328 if (c < 0) 329 r = p = s.leftLink; 330 else 331 r = p = s.rightLink; 332 333 while (p != q) 334 { 335 if (sort.compare(k, p.key) < 0) 336 { 337 p.balance = -1; 338 p = p.leftLink; 339 } 340 else { 342 p.balance = 1; 343 p = p.rightLink; 344 } 345 } 346 347 349 int a = (c > 0 ? 1 : ((c == 0) ? 0 : -1)); 350 351 if (s.balance == 0) 352 { 353 s.balance = a; 355 height++; 356 return INSERT_OK; 357 } 358 359 if (s.balance == -a) 360 { 361 s.balance = 0; 363 return INSERT_OK; 364 } 365 366 368 if (r.balance == a) 370 { 371 p = r; 373 s.setLink(a, r.link(-a)); 374 r.setLink(-a, s); 375 s.balance = 0; 376 r.balance = 0; 377 } 378 else { 380 p = r.link(-a); 382 r.setLink(-a, p.link(a)); 383 p.setLink(a, r); 384 s.setLink(a, p.link(-a)); 385 p.setLink(-a, s); 386 387 if (p.balance == a) 388 { 389 s.balance = -a; 390 r.balance = 0; 391 } 392 else if (p.balance == 0) 393 { 394 s.balance = 0; 395 r.balance = 0; 396 } 397 else { 399 s.balance = 0; 400 r.balance = a; 401 } 402 403 p.balance = 0; 404 } 405 406 if (s == t.rightLink) 408 t.rightLink = p; 409 else 410 t.leftLink = p; 411 412 return INSERT_OK; 413 } 414 415 419 public DataValueDescriptor[] removeFirst() 420 { 421 if (head.rightLink == null) 422 return null; 423 head.rightLink = deleteLeftmost(head.rightLink); 424 if (this.subtreeShrunk) 425 height--; 426 return this.deletedKey; 427 } 428 429 437 private Node deleteLeftmost(Node thisNode) 438 { 439 if (thisNode.leftLink == null) 442 { 443 444 if (thisNode.dupChain != null) 447 { 448 Node dupNode = thisNode.dupChain; 449 450 452 this.deletedKey = dupNode.key; 456 lastAux = dupNode.aux; 457 458 thisNode.dupChain = dupNode.dupChain; 460 allocator.freeNode(dupNode); 461 dupNode = null; 462 463 this.subtreeShrunk = false; 466 467 return thisNode; 469 } 470 else { 472 474 this.deletedKey = thisNode.key; 476 lastAux = thisNode.aux; 477 478 this.subtreeShrunk = true; 481 482 Node newRoot = thisNode.rightLink; 485 486 allocator.freeNode(thisNode); 488 489 return newRoot; 492 } 493 } 494 495 thisNode.leftLink = deleteLeftmost(thisNode.leftLink); 501 502 if (this.subtreeShrunk == false) 505 return thisNode; 506 507 510 if (thisNode.balance == 1) 511 { 512 return rotateRight(thisNode); 518 } 519 520 if (thisNode.balance == -1) 521 { 522 thisNode.balance = 0; 524 525 this.subtreeShrunk = true; 528 } 529 else { 531 thisNode.balance = 1; 533 534 this.subtreeShrunk = false; 538 } 539 540 return thisNode; 542 } 543 544 563 private Node rotateRight(Node thisNode) 564 { 565 Node a = thisNode; 566 Node b = thisNode.rightLink; 567 568 if (b.balance >= 0) 569 { 570 572 a.rightLink = b.leftLink; 573 b.leftLink = a; 574 575 if (b.balance == 0) 576 { 577 a.balance = 1; 578 b.balance = -1; 579 this.subtreeShrunk = false; 580 } 581 else { 583 a.balance = 0; 584 b.balance = 0; 585 this.subtreeShrunk = true; 586 } 587 588 return b; 589 } 590 else { 592 594 Node x = b.leftLink; 595 596 a.rightLink = x.leftLink; 597 x.leftLink = a; 598 b.leftLink = x.rightLink; 599 x.rightLink = b; 600 601 if (x.balance == 1) 602 { 603 a.balance = -1; 604 b.balance = 0; 605 } 606 else if (x.balance == -1) 607 { 608 a.balance = 0; 609 b.balance = 1; 610 } 611 else { 613 a.balance = 0; 614 b.balance = 0; 615 } 616 x.balance = 0; 617 618 this.subtreeShrunk = true; 619 620 return x; 621 } 622 } 623 624 public void check() 625 { 626 if (SanityManager.DEBUG) 627 { 628 String error = null; 629 if (head.rightLink == null) 630 { 631 if (height != 0) 632 error = "empty tree with height " + height; 633 } 634 else 635 { 636 if (depth(head.rightLink) != height) 637 error = "tree height " + height + " != depth " + depth(head.rightLink); 638 else 639 error = checkNode(head.rightLink); 640 } 641 if (error != null) 642 { 643 System.out.println("ERROR: " + error); 644 print(); 645 System.exit(1); 646 } 647 } 648 } 649 650 private String checkNode(Node n) 651 { 652 if (SanityManager.DEBUG) 653 { 654 if (n == null) 655 return null; 656 int ld = depth(n.leftLink); 657 int rd = depth(n.rightLink); 658 if (n.balance != (rd - ld)) 659 return "node " + n + ": left height " + ld + " right height " + rd; 660 661 String e; 662 e = checkNode(n.rightLink); 663 if (e == null) 664 e = checkNode(n.leftLink); 665 return e; 666 } 667 else 668 { 669 return(null); 670 } 671 } 672 673 private int depth(Node n) 674 { 675 int ld = 0; 676 int rd = 0; 677 if (n == null) 678 return 0; 679 if (n.leftLink != null) 680 ld = depth(n.leftLink); 681 if (n.rightLink != null) 682 rd = depth(n.rightLink); 683 if (rd > ld) 684 return rd + 1; 685 else 686 return ld + 1; 687 } 688 689 public void print() 690 { 691 Node root = head.rightLink; 692 System.out.println("tree height: " + height 693 + " root: " + ((root == null) ? -1 : root.id)); 694 if (root != null) 695 printRecursive(root, 0); 696 } 697 698 private void printRecursive(Node n, int depth) 699 { 700 if (n.rightLink != null) 701 printRecursive(n.rightLink, depth + 1); 702 for (int i = 0; i < depth; i++) 703 System.out.print(" "); 704 System.out.println(n); 705 if (n.leftLink != null) 706 printRecursive(n.leftLink, depth + 1); 707 } 708 709 private void debug(String s) 710 { 711 if (SanityManager.DEBUG) 712 { 713 System.out.println(" === [" + s + "] ==="); 714 } 715 } 716 } 717 | Popular Tags |