+// a fence key was deleted from a page
+// push new fence value upwards
+
+BTERR bt_fixfence (BtDb *bt, uid page_no, uint lvl)
+{
+unsigned char leftkey[256], rightkey[256];
+BtKey ptr;
+
+ // remove deleted key, the old fence value
+
+ ptr = keyptr(bt->page, bt->page->cnt);
+ memcpy(rightkey, ptr, ptr->len + 1);
+
+ memset (slotptr(bt->page, bt->page->cnt--), 0, sizeof(BtSlot));
+ bt->page->dirty = 1;
+
+ ptr = keyptr(bt->page, bt->page->cnt);
+ memcpy(leftkey, ptr, ptr->len + 1);
+
+ if( bt_update (bt, bt->page, page_no) )
+ return bt->err;
+
+ if( bt_lockpage (bt, page_no, BtLockParent) )
+ return bt->err;
+
+ if( bt_unlockpage (bt, page_no, BtLockWrite) )
+ return bt->err;
+
+ // insert new (now smaller) fence key
+
+ if( bt_insertkey (bt, leftkey+1, *leftkey, lvl + 1, page_no, time(NULL)) )
+ return bt->err;
+
+ // remove old (larger) fence key
+
+ if( bt_deletekey (bt, rightkey+1, *rightkey, lvl + 1) )
+ return bt->err;
+
+ return bt_unlockpage (bt, page_no, BtLockParent);
+}
+
+// root has a single child
+// collapse a level from the btree
+// call with root locked in bt->page
+
+BTERR bt_collapseroot (BtDb *bt, BtPage root)
+{
+uid child;
+uint idx;
+
+ // find the child entry
+ // and promote to new root
+
+ do {
+ for( idx = 0; idx++ < root->cnt; )
+ if( !slotptr(root, idx)->dead )
+ break;
+
+ child = bt_getid (slotptr(root, idx)->id);
+
+ if( bt_lockpage (bt, child, BtLockDelete) )
+ return bt->err;
+
+ if( bt_lockpage (bt, child, BtLockWrite) )
+ return bt->err;
+
+ if( bt_mappage (bt, &bt->temp, child) )
+ return bt->err;
+
+ memcpy (root, bt->temp, bt->page_size);
+
+ if( bt_update (bt, root, ROOT_page) )
+ return bt->err;
+
+ if( bt_freepage (bt, child) )
+ return bt->err;
+
+ } while( root->lvl > 1 && root->act == 1 );
+
+ return bt_unlockpage (bt, ROOT_page, BtLockWrite);
+}
+