Fix bugs.
authorRobert Haas <rhaas@postgresql.org>
Thu, 20 Feb 2014 19:48:28 +0000 (14:48 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 20 Feb 2014 19:48:28 +0000 (14:48 -0500)
src/backend/utils/mmgr/freepage.c

index 9aa7cce6df308a6d8d9c4ea3661d194bdb023406..802fb5cd71f968d9ba82b10387ae32a55e2fa588 100644 (file)
@@ -393,9 +393,11 @@ FreePageBtreeGetRecycled(FreePageManager *fpm)
 
        Assert(victim != NULL);
        newhead = relptr_access(base, victim->next);
-       relptr_copy(newhead->prev, victim->prev);
+       if (newhead != NULL)
+               relptr_copy(newhead->prev, victim->prev);
        relptr_store(base, fpm->btree_recycle, newhead);
        Assert(fpm_pointer_is_page_aligned(base, victim));
+       fpm->btree_recycle_count--;
        return (FreePageBtree *) victim;
 }
 
@@ -406,6 +408,9 @@ static void
 FreePageBtreeInsertInternal(char *base, FreePageBtree *btp, Size index,
                                                        Size first_page, FreePageBtree *child)
 {
+       Assert(btp->hdr.magic == FREE_PAGE_INTERNAL_MAGIC);
+       Assert(btp->hdr.nused <= FPM_ITEMS_PER_INTERNAL_PAGE);
+       Assert(index <= btp->hdr.nused);
        memmove(&btp->u.internal_key[index + 1], &btp->u.internal_key[index],
                        sizeof(FreePageBtreeInternalKey) * (btp->hdr.nused - index));
        btp->u.internal_key[index].first_page = first_page;
@@ -420,6 +425,9 @@ static void
 FreePageBtreeInsertLeaf(FreePageBtree *btp, Size index, Size first_page,
                                                Size npages)
 {
+       Assert(btp->hdr.magic == FREE_PAGE_LEAF_MAGIC);
+       Assert(btp->hdr.nused <= FPM_ITEMS_PER_LEAF_PAGE);
+       Assert(index <= btp->hdr.nused);
        memmove(&btp->u.leaf_key[index + 1], &btp->u.leaf_key[index],
                        sizeof(FreePageBtreeLeafKey) * (btp->hdr.nused - index));
        btp->u.leaf_key[index].first_page = first_page;
@@ -445,6 +453,7 @@ FreePageBtreeRecycle(FreePageManager *fpm, Size pageno)
        if (head != NULL)
                relptr_store(base, head->prev, span);
        relptr_store(base, fpm->btree_recycle, span);
+       fpm->btree_recycle_count++;
 }
 
 /*
@@ -679,7 +688,7 @@ FreePageBtreeSearchInternal(FreePageBtree *btp, Size first_page)
        Size    high = btp->hdr.nused;
 
        Assert(btp->hdr.magic == FREE_PAGE_INTERNAL_MAGIC);
-       Assert(high > 0 && high < FPM_ITEMS_PER_INTERNAL_PAGE);
+       Assert(high > 0 && high <= FPM_ITEMS_PER_INTERNAL_PAGE);
 
        while (low < high)
        {
@@ -709,7 +718,7 @@ FreePageBtreeSearchLeaf(FreePageBtree *btp, Size first_page)
        Size    high = btp->hdr.nused;
 
        Assert(btp->hdr.magic == FREE_PAGE_LEAF_MAGIC);
-       Assert(high > 0 && high < FPM_ITEMS_PER_LEAF_PAGE);
+       Assert(high > 0 && high <= FPM_ITEMS_PER_LEAF_PAGE);
 
        while (low < high)
        {
@@ -796,7 +805,6 @@ FreePageManagerDumpBtree(FreePageManager *fpm, FreePageBtree *btp, int level,
                        FreePageManagerDumpBtree(fpm, child, level + 1, buf);
                }
        }
-       appendStringInfo(buf, "\n");
 }
 
 /*
@@ -897,6 +905,7 @@ FreePageManagerGetInternal(FreePageManager *fpm, Size npages, Size *first_page)
                relptr_copy(fpm->freelist[f], victim->next);
        if (next != NULL)
                relptr_copy(next->prev, victim->prev);
+       victim_page = fpm_pointer_to_page(base, victim);
 
        /*
         * If we haven't initialized the btree yet, the victim must be the single
@@ -905,7 +914,7 @@ FreePageManagerGetInternal(FreePageManager *fpm, Size npages, Size *first_page)
         */
        if (relptr_is_null(fpm->btree_root))
        {
-               Assert(fpm_pointer_to_page(base, victim) == fpm->singleton_first_page);
+               Assert(victim_page == fpm->singleton_first_page);
                Assert(victim->npages = fpm->singleton_npages);
                Assert(victim->npages >= npages);
                fpm->singleton_first_page += npages;
@@ -1015,7 +1024,6 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
        FreePageBtreeSearchResult result;
        FreePageBtreeLeafKey *prevkey = NULL;
        FreePageBtreeLeafKey *nextkey = NULL;
-       Size    index;
 
        /* We can store a single free span without initializing the btree. */
        if (fpm->btree_depth == 0)
@@ -1135,14 +1143,14 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
                Assert(first_page + npages == nextkey->first_page);
                newpages = (nextkey->first_page - first_page) + nextkey->npages;
 
-               /* Update key in place. */
-               nextkey->first_page = first_page;
-               nextkey->npages = newpages;
-
                /* Put span on correct free list. */
                FreePagePopSpanLeader(fpm, nextkey->first_page);
                FreePagePushSpanLeader(fpm, first_page, newpages);
 
+               /* Update key in place. */
+               nextkey->first_page = first_page;
+               nextkey->npages = newpages;
+
                /* If reducing first key on page, ancestors might need adjustment. */
                if (result.index_next == 0)
                        FreePageBtreeAdjustAncestorKeys(fpm, result.page_next);
@@ -1315,10 +1323,11 @@ FreePageManagerPutInternal(FreePageManager *fpm, Size first_page, Size npages,
 
        /* Physically add the key to the page. */
        Assert(result.page_next->hdr.nused < FPM_ITEMS_PER_LEAF_PAGE);
-       FreePageBtreeInsertLeaf(result.page_next, index, first_page, npages);
+       FreePageBtreeInsertLeaf(result.page_next, result.index_next,
+                                                       first_page, npages);
 
        /* If new first key on page, ancestors might need adjustment. */
-       if (index == 0)
+       if (result.index_next == 0)
                FreePageBtreeAdjustAncestorKeys(fpm, result.page_next);
 
        /* Put it on the free list. */