{
FreePageBtree *root = relptr_access(base, fpm->btree_root);
- /* Can't do anything if the root has multiple keys. */
- if (root->hdr.nused > 1)
- break;
-
- /* Root should never be empty. */
- Assert(root->hdr.nused == 1);
+ /* If the root contains only one key, reduce depth by one. */
+ if (root->hdr.nused == 1)
+ {
+ /* Shrink depth of tree by one. */
+ Assert(fpm->btree_depth > 0);
+ --fpm->btree_depth;
+ if (root->hdr.magic == FREE_PAGE_LEAF_MAGIC)
+ {
+ /* If root is a leaf, convert only entry to singleton range. */
+ relptr_store(base, fpm->btree_root, (FreePageBtree *) NULL);
+ fpm->singleton_first_page = root->u.leaf_key[0].first_page;
+ fpm->singleton_npages = root->u.leaf_key[0].npages;
+ }
+ else
+ {
+ FreePageBtree *newroot;
- /* Shrink depth of tree by one. */
- Assert(fpm->btree_depth > 0);
- --fpm->btree_depth;
- if (root->hdr.magic == FREE_PAGE_LEAF_MAGIC)
+ /* If root is an internal page, make only child the root. */
+ Assert(root->hdr.magic == FREE_PAGE_INTERNAL_MAGIC);
+ relptr_copy(fpm->btree_root, root->u.internal_key[0].child);
+ newroot = relptr_access(base, fpm->btree_root);
+ relptr_store(base, newroot->hdr.parent, (FreePageBtree *) NULL);
+ }
+ FreePageBtreeRecycle(fpm, fpm_pointer_to_page(base, root));
+ }
+ else if (root->hdr.nused == 2 &&
+ root->hdr.magic == FREE_PAGE_LEAF_MAGIC)
{
- /* If root is a leaf, convert only entry to singleton range. */
- relptr_store(base, fpm->btree_root, (FreePageBtree *) NULL);
- fpm->singleton_first_page = root->u.leaf_key[0].first_page;
- fpm->singleton_npages = root->u.leaf_key[0].npages;
+ Size end_of_first;
+ Size start_of_second;
+
+ end_of_first = root->u.leaf_key[0].first_page +
+ root->u.leaf_key[0].npages;
+ start_of_second = root->u.leaf_key[1].first_page;
+
+ if (end_of_first + 1 == start_of_second)
+ {
+ Size root_page = fpm_pointer_to_page(base, root);
+
+ if (end_of_first == root_page)
+ {
+ FreePagePopSpanLeader(fpm, root->u.leaf_key[0].first_page);
+ FreePagePopSpanLeader(fpm, root->u.leaf_key[1].first_page);
+ fpm->singleton_first_page = root->u.leaf_key[0].first_page;
+ fpm->singleton_npages = root->u.leaf_key[0].npages +
+ root->u.leaf_key[1].npages + 1;
+ fpm->btree_depth = 0;
+ relptr_store(base, fpm->btree_root,
+ (FreePageBtree *) NULL);
+ FreePagePushSpanLeader(fpm, fpm->singleton_first_page,
+ fpm->singleton_npages);
+ }
+ }
+
+ /* Whether it worked or not, it's time to stop. */
+ break;
}
else
{
- FreePageBtree *newroot;
-
- /* If root is an internal page, make only child the root. */
- Assert(root->hdr.magic == FREE_PAGE_INTERNAL_MAGIC);
- relptr_copy(fpm->btree_root, root->u.internal_key[0].child);
- newroot = relptr_access(base, fpm->btree_root);
- relptr_store(base, newroot->hdr.parent, (FreePageBtree *) NULL);
+ /* Nothing more to do. Stop. */
+ break;
}
- FreePageBtreeRecycle(fpm, fpm_pointer_to_page(base, root));
}
/*
fpm->singleton_npages = 0;
fpm->btree_depth = 1;
+ /*
+ * Corner case: it may be that the btree root took the very last
+ * free page. In that case, the sole btree entry covers a zero
+ * page run, which is invalid. Overwrite it with the entry we're
+ * trying to insert and get out.
+ */
+ if (root->u.leaf_key[0].npages == 0)
+ {
+ root->u.leaf_key[0].first_page = first_page;
+ root->u.leaf_key[0].npages = npages;
+ return npages;
+ }
+
/* Fall through to insert the new key. */
}
}