Fix bugs.
authorRobert Haas <rhaas@postgresql.org>
Thu, 20 Feb 2014 21:17:31 +0000 (16:17 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 20 Feb 2014 21:17:31 +0000 (16:17 -0500)
src/backend/utils/mmgr/freepage.c

index 802fb5cd71f968d9ba82b10387ae32a55e2fa588..25fd13700e81ba1871f1c40f88384dfec9b12385 100644 (file)
@@ -550,14 +550,12 @@ FreePageBtreeRemove(FreePageManager *fpm, FreePageBtree *btp, Size index)
  * *result with the results of the search.  If an exact match is found,
  * result->page_exact and result->index_exact will be set to the page and
  * slot where it is located. Otherwise, result->page_exact will be NULL;
- * result->page_next and result->index_next will indicate the location of
- * the following key (unless the proposed first_page would follow everything
- * currently in the tree, in which case result->page_next will be NULL); and
- * result->page_prev and result->index_prev will indicate the preceding
- * key (unless the proposed first_page would precede everything currently
- * in the tree, in which case result->page_prev will be NULL).
- * result->split_pages will contain the number of additional btree pages that
- * will be needed when performing a split to insert a key into
+ * result->page_next and result->index_next will indicate the point at which
+ * the key could be inserted; and result->page_prev and result->index_prev
+ * will indicate the preceding key (unless the proposed first_page would
+ * precede everything currently in the tree, in which case result->page_prev
+ * will be NULL).  result->split_pages will contain the number of additional
+ * btree pages that will be needed when performing a split to insert a key into
  * result->page_exact or result->page_next.  Except as described above, the
  * contents of fields in the result object are undefined on return.
  */
@@ -615,27 +613,19 @@ FreePageBtreeSearch(FreePageManager *fpm, Size first_page,
 
        /* Search leaf page. */
        index = FreePageBtreeSearchLeaf(btp, first_page);
-       if (index >= btp->hdr.nused)
-       {
-               /* Bigger than every key on the page. */
-               Assert(index == btp->hdr.nused);
-               result->page_exact = NULL;
-               result->page_next = NULL;
-       }
-       else if (first_page == btp->u.leaf_key[index].first_page)
+       if (index < btp->hdr.nused &&
+               first_page == btp->u.leaf_key[index].first_page)
        {
                /* Exact match. */
                result->page_exact = btp;
                result->index_exact = index;
                return;                 /* No need to set previous key in this case. */
        }
-       else
-       {
-               /* Not equal to any key and before at least one key. */
-               result->page_exact = NULL;
-               result->page_next = btp;
-               result->index_next = index;
-       }
+
+       /* No exact match; indicate insertion position. */
+       result->page_exact = NULL;
+       result->page_next = btp;
+       result->index_next = index;
 
        /* Find the previous key. */
        if (index > 0)
@@ -1092,7 +1082,7 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
        Assert(result.page_exact == NULL);              /* can't already be there */
        if (result.page_prev != NULL)
                prevkey = &result.page_prev->u.leaf_key[result.index_prev];
-       if (result.page_next != NULL)
+       if (result.index_next < result.page_next->hdr.nused)
                nextkey = &result.page_next->u.leaf_key[result.index_next];
 
        /* Consolidate with the previous entry if possible. */
@@ -1219,7 +1209,7 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
                /* If we still need to perform a split, do it. */
                if (result.split_pages > 0)
                {
-                       FreePageBtree   *target = result.page_next;
+                       FreePageBtree   *split_target = result.page_next;
                        FreePageBtree   *child = NULL;
                        Size    key = first_page;
 
@@ -1229,10 +1219,10 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
                                FreePageBtree *parent;
 
                                /* Identify parent page, which must receive downlink. */
-                               parent = relptr_access(base, target->hdr.parent);
+                               parent = relptr_access(base, split_target->hdr.parent);
 
                                /* Split the page - downlink not added yet. */
-                               newsibling = FreePageBtreeSplitPage(fpm, target);
+                               newsibling = FreePageBtreeSplitPage(fpm, split_target);
 
                                /*
                                 * At this point in the loop, we're always carrying a pending
@@ -1249,11 +1239,11 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
                                        FreePageBtree *insert_into;
 
                                        insert_into = key < newsibling->u.leaf_key[0].first_page ?
-                                               target : newsibling;
+                                               split_target : newsibling;
                                        index = FreePageBtreeSearchLeaf(insert_into, key);
                                        FreePageBtreeInsertLeaf(insert_into, index, key, npages);
-                                       if (index == 0 && insert_into == target)
-                                               FreePageBtreeAdjustAncestorKeys(fpm, target);
+                                       if (index == 0 && insert_into == split_target)
+                                               FreePageBtreeAdjustAncestorKeys(fpm, split_target);
                                }
                                else
                                {
@@ -1262,12 +1252,12 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
 
                                        insert_into =
                                                key < newsibling->u.internal_key[0].first_page ?
-                                               target : newsibling;
+                                               split_target : newsibling;
                                        index = FreePageBtreeSearchInternal(insert_into, key);
                                        FreePageBtreeInsertInternal(base, insert_into, index,
                                                                                                key, child);
-                                       if (index == 0 && insert_into == target)
-                                               FreePageBtreeAdjustAncestorKeys(fpm, target);
+                                       if (index == 0 && insert_into == split_target)
+                                               FreePageBtreeAdjustAncestorKeys(fpm, split_target);
                                }
 
                                /* If the page we just split has no parent, split the root. */
@@ -1281,13 +1271,16 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
                                        relptr_store(base, newroot->hdr.parent,
                                                                 (FreePageBtree *) NULL);
                                        newroot->u.internal_key[0].first_page =
-                                               FreePageBtreeFirstKey(target);
+                                               FreePageBtreeFirstKey(split_target);
                                        relptr_store(base, newroot->u.internal_key[0].child,
-                                               target);
+                                               split_target);
+                                       relptr_store(base, newroot->hdr.parent, newroot);
                                        newroot->u.internal_key[1].first_page =
                                                FreePageBtreeFirstKey(newsibling);
                                        relptr_store(base, newroot->u.internal_key[1].child,
-                                               target);
+                                               newsibling);
+                                       relptr_store(base, newsibling->hdr.parent, newroot);
+                                       relptr_store(base, fpm->btree_root, newroot);
                                        fpm->btree_depth++;
 
                                        break;
@@ -1309,7 +1302,7 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
 
                                /* The parent also needs to be split, so loop around. */
                                child = newsibling;
-                               target = parent;
+                               split_target = parent;
                        }
 
                        /*