| 406 | |
| 407 | |
| 408 | void Sort::sort(thread_db* tdbb) |
| 409 | { |
| 410 | /************************************** |
| 411 | * |
| 412 | * Perform any intermediate computing before giving records |
| 413 | * back. If there weren't any runs, run sort the buffer. |
| 414 | * If there were runs, sort and write out the last run_control and |
| 415 | * build a merge tree. |
| 416 | * |
| 417 | **************************************/ |
| 418 | run_control* run; |
| 419 | merge_control* merge; |
| 420 | merge_control* merge_pool; |
| 421 | |
| 422 | try |
| 423 | { |
| 424 | if (m_last_record != (SR*) m_end_memory) |
| 425 | { |
| 426 | diddleKey((UCHAR*) KEYOF(m_last_record), true, false); |
| 427 | } |
| 428 | |
| 429 | // If there aren't any runs, things fit nicely in memory. Just sort the mess |
| 430 | // and we're ready for output. |
| 431 | if (!m_runs) |
| 432 | { |
| 433 | sortBuffer(tdbb); |
| 434 | m_next_pointer = m_first_pointer + 1; |
| 435 | m_flags |= scb_sorted; |
| 436 | return; |
| 437 | } |
| 438 | |
| 439 | // Write the last records as a run_control |
| 440 | |
| 441 | putRun(tdbb); |
| 442 | |
| 443 | CHECK_FILE(NULL); |
| 444 | |
| 445 | // Merge runs of low depth to free memory part of temp space |
| 446 | // they use and to make total runs count lower. This is fast |
| 447 | // because low depth runs usually sit in memory |
| 448 | ULONG run_count = 0, low_depth_cnt = 0; |
| 449 | for (run = m_runs; run; run = run->run_next) |
| 450 | { |
| 451 | ++run_count; |
| 452 | if (run->run_depth < MAX_MERGE_LEVEL) |
| 453 | low_depth_cnt++; |
| 454 | } |
| 455 | |
| 456 | if (low_depth_cnt > 1 && low_depth_cnt < run_count) |
| 457 | { |
| 458 | mergeRuns(low_depth_cnt); |
| 459 | CHECK_FILE(NULL); |
| 460 | } |
| 461 | |
| 462 | // Build a merge tree for the run_control blocks. Start by laying them all out |
| 463 | // in a vector. This is done to allow us to build a merge tree from the |
| 464 | // bottom up, ensuring that a balanced tree is built. |
| 465 | |