+// return page to free list
+// page must be delete & write locked
+
+void bt_freepage (BtDb *bt, BtPageSet *set)
+{
+ // lock allocation page
+
+ bt_spinwritelock (bt->mgr->latchmgr->lock);
+
+ // store chain in second right
+ bt_putid(set->page->right, bt_getid(bt->mgr->latchmgr->alloc[1].right));
+ bt_putid(bt->mgr->latchmgr->alloc[1].right, set->page_no);
+ set->page->free = 1;
+
+ // unlock released page
+
+ bt_unlockpage (BtLockDelete, set->latch);
+ bt_unlockpage (BtLockWrite, set->latch);
+ bt_unpinlatch (set->latch);
+ bt_unpinpool (set->pool);
+
+ // unlock allocation page
+
+ bt_spinreleasewrite (bt->mgr->latchmgr->lock);
+}
+
+// a fence key was deleted from a page
+// push new fence value upwards
+
+BTERR bt_fixfence (BtDb *bt, BtPageSet *set, uint lvl)
+{
+unsigned char leftkey[256], rightkey[256];
+uid page_no;
+BtKey ptr;
+
+ // remove the old fence value
+
+ ptr = keyptr(set->page, set->page->cnt);
+ memcpy (rightkey, ptr, ptr->len + 1);
+
+ memset (slotptr(set->page, set->page->cnt--), 0, sizeof(BtSlot));
+ set->page->dirty = 1;
+
+ ptr = keyptr(set->page, set->page->cnt);
+ memcpy (leftkey, ptr, ptr->len + 1);
+ page_no = set->page_no;
+
+ bt_lockpage (BtLockParent, set->latch);
+ bt_unlockpage (BtLockWrite, set->latch);
+
+ // insert new (now smaller) fence key
+
+ if( bt_insertkey (bt, leftkey+1, *leftkey, lvl+1, page_no, time(NULL)) )
+ return bt->err;
+
+ // now delete old fence key
+
+ if( bt_deletekey (bt, rightkey+1, *rightkey, lvl+1) )
+ return bt->err;
+
+ bt_unlockpage (BtLockParent, set->latch);
+ bt_unpinlatch(set->latch);
+ bt_unpinpool (set->pool);
+ return 0;
+}
+
+// root has a single child
+// collapse a level from the tree
+
+BTERR bt_collapseroot (BtDb *bt, BtPageSet *root)
+{
+BtPageSet child[1];
+uint idx;
+
+ // find the child entry and promote as new root contents
+
+ do {
+ for( idx = 0; idx++ < root->page->cnt; )
+ if( !slotptr(root->page, idx)->dead )
+ break;
+
+ child->page_no = bt_getid (slotptr(root->page, idx)->id);
+
+ child->latch = bt_pinlatch (bt, child->page_no);
+ bt_lockpage (BtLockDelete, child->latch);
+ bt_lockpage (BtLockWrite, child->latch);
+
+ if( child->pool = bt_pinpool (bt, child->page_no) )
+ child->page = bt_page (bt, child->pool, child->page_no);
+ else
+ return bt->err;
+
+ memcpy (root->page, child->page, bt->mgr->page_size);
+ bt_freepage (bt, child);
+
+ } while( root->page->lvl > 1 && root->page->act == 1 );
+
+ bt_unlockpage (BtLockWrite, root->latch);
+ bt_unpinlatch (root->latch);
+ bt_unpinpool (root->pool);
+ return 0;
+}
+