-BTERR bt_freepage (BtDb *bt, BtPageSet *set)
-{
- // lock & map allocation page
-
- if( bt_lockpage (bt, ALLOC_page, BtLockWrite) )
- return bt->err;
-
- if( bt_mappage (bt, &bt->alloc, ALLOC_page) )
- return bt->err;
-
- // store chain in second right
- bt_putid(set->page->right, bt_getid(bt->alloc[1].right));
- bt_putid(bt->alloc[1].right, set->page_no);
- set->page->free = 1;
-
- if( bt_update(bt, bt->alloc, ALLOC_page) )
- return bt->err;
- if( bt_update(bt, set->page, set->page_no) )
- return bt->err;
-
- // unlock page zero
-
- if( bt_unlockpage(bt, ALLOC_page, BtLockWrite) )
- return bt->err;
-
- // remove write lock on deleted node
-
- if( bt_unlockpage(bt, set->page_no, BtLockWrite) )
- return bt->err;
-
- return bt_unlockpage (bt, set->page_no, BtLockDelete);
-}
-
-// remove the root level by promoting its only child
-
-BTERR bt_removeroot (BtDb *bt, BtPageSet *root, BtPageSet *child)
-{
-uid next = 0;
-
- do {
- if( next ) {
- if( bt_lockpage (bt, next, BtLockDelete) )
- return bt->err;
- if( bt_lockpage (bt, next, BtLockWrite) )
- return bt->err;
-
- if( bt_mappage (bt, &child->page, next) )
- return bt->err;
-
- child->page_no = next;
- }
-
- memcpy (root->page, child->page, bt->page_size);
- next = bt_getid (slotptr(child->page, child->page->cnt)->id);
-
- if( bt_freepage (bt, child) )
- return bt->err;
- } while( root->page->lvl > 1 && root->page->cnt == 1 );
-
- if( bt_update (bt, root->page, ROOT_page) )
- return bt->err;
-
- return bt_unlockpage (bt, ROOT_page, BtLockWrite);
-}
-
-// pull right page over ourselves in simple merge
-
-BTERR bt_mergeright (BtDb *bt, BtPageSet *set, BtPageSet *parent, BtPageSet *right, uint slot, uint idx)
-{
- // install ourselves as child page
- // and delete ourselves from parent
-
- bt_putid (slotptr(parent->page, idx)->id, set->page_no);
- slotptr(parent->page, slot)->dead = 1;
- parent->page->act--;
-
- // collapse any empty slots
-
- while( idx = parent->page->cnt - 1 )
- if( slotptr(parent->page, idx)->dead ) {
- *slotptr(parent->page, idx) = *slotptr(parent->page, idx + 1);
- memset (slotptr(parent->page, parent->page->cnt--), 0, sizeof(BtSlot));
- } else
- break;
-
- memcpy (set->page, right->page, bt->page_size);
-
- if( bt_unlockpage (bt, right->page_no, BtLockParent) )
- return bt->err;
-
- if( bt_freepage (bt, right) )
- return bt->err;
-
- // do we need to remove a btree level?
- // (leave the first page of leaves alone)
-
- if( parent->page_no == ROOT_page && parent->page->cnt == 1 )
- if( set->page->lvl )
- return bt_removeroot (bt, parent, set);
-
- if( bt_update (bt, parent->page, parent->page_no) )
- return bt->err;
-
- if( bt_unlockpage (bt, parent->page_no, BtLockWrite) )
- return bt->err;
-
- if( bt_update (bt, set->page, set->page_no) )
- return bt->err;
-
- if( bt_unlockpage (bt, set->page_no, BtLockWrite) )
- return bt->err;
-
- if( bt_unlockpage (bt, set->page_no, BtLockDelete) )
- return bt->err;
-
- return 0;
-}
-
-// remove both child and parent from the btree
-// from the fence position in the parent
-
-BTERR bt_removeparent (BtDb *bt, BtPageSet *child, BtPageSet *parent, BtPageSet *right, BtPageSet *rparent, uint lvl)
-{
-unsigned char pagefence[256];
-uint idx;
-
- // pull right sibling over ourselves and unlock
-
- memcpy (child->page, right->page, bt->page_size);
-
- if( bt_update(bt, child->page, child->page_no) )
- return bt->err;
-
- if( bt_unlockpage (bt, child->page_no, BtLockWrite) )
- return bt->err;
-
- // install ourselves into right link of old right page
-
- bt_putid (right->page->right, child->page_no);
- right->page->goright = 1; // tell bt_loadpage to go right to us
- right->page->kill = 1;
-
- if( bt_update(bt, right->page, right->page_no) )
- return bt->err;
-
- if( bt_unlockpage (bt, right->page_no, BtLockWrite) )
- return bt->err;
-
- // remove our slot from our parent
- // signal to move right
-
- parent->page->goright = 1; // tell bt_findslot to go right to rparent
- parent->page->kill = 1;
- parent->page->act--;
-
- // redirect right page pointer in right parent to us
-
- for( idx = 0; idx++ < rparent->page->cnt; )
- if( !slotptr(rparent->page, idx)->dead )
- break;
-
- if( bt_getid (slotptr(rparent->page, idx)->id) != right->page_no )
- return bt->err = BTERR_struct;
-
- bt_putid (slotptr(rparent->page, idx)->id, child->page_no);
-
- if( bt_update (bt, rparent->page, rparent->page_no) )
- return bt->err;