| 5104 | |
| 5105 | |
| 5106 | static contents garbage_collect(thread_db* tdbb, WIN* window, ULONG parent_number) |
| 5107 | { |
| 5108 | /************************************** |
| 5109 | * |
| 5110 | * g a r b a g e _ c o l l e c t |
| 5111 | * |
| 5112 | ************************************** |
| 5113 | * |
| 5114 | * Functional description |
| 5115 | * Garbage collect an index page. This requires |
| 5116 | * care so that we don't step on other processes |
| 5117 | * that might be traversing the tree forwards, |
| 5118 | * backwards, or top to bottom. We must also |
| 5119 | * keep in mind that someone might be adding a node |
| 5120 | * at the same time we are deleting. Therefore we |
| 5121 | * must lock all the pages involved to prevent |
| 5122 | * such operations while we are garbage collecting. |
| 5123 | * |
| 5124 | **************************************/ |
| 5125 | |
| 5126 | SET_TDBB(tdbb); |
| 5127 | const Database* dbb = tdbb->getDatabase(); |
| 5128 | CHECK_DBB(dbb); |
| 5129 | |
| 5130 | const USHORT pageSpaceID = window->win_page.getPageSpaceID(); |
| 5131 | btree_page* gc_page = (btree_page*) window->win_buffer; |
| 5132 | contents result = contents_above_threshold; |
| 5133 | |
| 5134 | // check to see if the page was marked not to be garbage collected |
| 5135 | if ( !BtrPageGCLock::isPageGCAllowed(tdbb, window->win_page) ) |
| 5136 | { |
| 5137 | CCH_RELEASE(tdbb, window); |
| 5138 | return contents_above_threshold; |
| 5139 | } |
| 5140 | |
| 5141 | // record the left sibling now since this is the only way to |
| 5142 | // get to it quickly; don't worry if it's not accurate now or |
| 5143 | // is changed after we release the page, since we will fetch |
| 5144 | // it in a fault-tolerant way anyway. |
| 5145 | const ULONG left_number = gc_page->btr_left_sibling; |
| 5146 | |
| 5147 | // if the left sibling is blank, that indicates we are the leftmost page, |
| 5148 | // so don't garbage-collect the page; do this for several reasons: |
| 5149 | // 1. The leftmost page needs a degenerate zero length node as its first node |
| 5150 | // (for a non-leaf, non-top-level page). |
| 5151 | // 2. The parent page would need to be fixed up to have a degenerate node |
| 5152 | // pointing to the right sibling. |
| 5153 | // 3. If we remove all pages on the level, we would need to re-add it next |
| 5154 | // time a record is inserted, so why constantly garbage-collect and re-create |
| 5155 | // this page? |
| 5156 | |
| 5157 | if (!left_number) |
| 5158 | { |
| 5159 | CCH_RELEASE(tdbb, window); |
| 5160 | return contents_above_threshold; |
| 5161 | } |
| 5162 | |
| 5163 | // record some facts for later validation |
no test coverage detected