More hacking.
authorRobert Haas <rhaas@postgresql.org>
Thu, 13 Feb 2014 03:39:29 +0000 (22:39 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 13 Feb 2014 03:39:29 +0000 (22:39 -0500)
src/backend/utils/mmgr/freepage.c
src/include/utils/freepage.h

index 7acb434d9383b6e4a1087dd930534525d2a23dfb..221025b4d61f438771f89938512ce0e501e2de7e 100644 (file)
@@ -47,8 +47,8 @@ typedef struct FreePageBtreeInternalKey
 /* Leaf key; no payload data. */
 typedef struct FreePageBtreeLeafKey
 {
-       Size    first_page;                             /* low bound for keys on child page */
-       Size    last_page;                              /* high bound for keys on child page */
+       Size    first_page;                             /* first page in span */
+       Size    npages;                                 /* number of pages in span */
 } FreePageBtreeLeafKey;
 
 /* Work out how many keys will fit on a page. */
@@ -121,7 +121,7 @@ FreePageManagerInitialize(FreePageManager *fpm, char *base, LWLock *lock,
        relptr_store(base, fpm->self, fpm);
        relptr_store(base, fpm->lock, lock);
        fpm->lock_address_is_fixed = lock_address_is_fixed;
-       relptr_store(base, fpm->root, (FreePageBtree *) NULL);
+       relptr_store(base, fpm->btree_root, (FreePageBtree *) NULL);
 
        for (f = 0; f < FPM_NUM_FREELISTS; f++)
                relptr_store(base, fpm->freelist[f], (FreePageSpanLeader *) NULL);
@@ -222,20 +222,85 @@ FreePageManagerGet(FreePageManager *fpm, Size npages, Size *first_page)
        return true;
 }
 
+/*
+ * Insert an item into the btree in the given position on the given page.
+ */
+static void
+FreePageBtreeInsert(FreePageManager *fpm, FreePageBtree *btp, Size index,
+                                       Size first_page, Size npages)
+{
+       char *base = fpm_segment_base(fpm);
+       FreePageBtree *splitroot;
+       int             nsplits = 0;
+
+       Assert(btp->hdr.magic == FREE_PAGE_LEAF_MAGIC);
+       Assert(index < btp->hdr.nused);
+       Assert(btp->hdr.nused <= FPM_ITEMS_PER_LEAF_PAGE);
+
+       /* If the page is not full, this is easy as pie. */
+       if (btp->hdr.nused < FPM_ITEMS_PER_LEAF_PAGE)
+       {
+               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;
+               btp->u.leaf_key[index].npages = npages;
+               ++btp->hdr.nused;
+               return;
+       }
+
+       /*
+        * Move upward until we find a page that isn't full.  We'll need to split
+        * everything below that point.
+        */
+       ++nsplits;
+       splitroot = relptr_access(base, btp->parent);
+       for (;;)
+       {
+               ++nsplits;
+               if (splitroot == NULL)
+                       break;
+
+               Assert(splitroot->hdr.magic == FREE_PAGE_INTERNAL_MAGIC);
+               Assert(btp->hdr.nused <= FPM_ITEMS_PER_INTERNAL_PAGE);
+
+               if (splitroot->hdr.nused < FPM_ITEMS_PER_INTERNAL_PAGE)
+                       break;
+               splitroot = relptr_access(base, splitroot->parent);
+       }
+
+       /*
+        * XXX. Ensure that we have at least nsplit spages in fpm->btree_recycle.
+        * How?
+        */
+
+       /*
+        * If everything up to and including the root was full, split the root.
+        * The depth of the btree increases by one.
+        */
+       if (splitroot == NULL)
+       {
+               /* XXX. Perform root split. */
+       }
+
+       /* Work our way down the tree, splitting as we go. */
+       while (splitroot->hdr.magic == FREE_PAGE_INTERNAL_MAGIC)
+}
+
 /*
  * Remove from the btree the item in the given position on the given page.
  */
 static void
 FreePageBtreeRemove(FreePageManager *fpm, FreePageBtree *btp, Size index)
 {
+       char *base = fpm_segment_base(fpm);
        Assert(btp->hdr.magic == FREE_PAGE_LEAF_MAGIC);
        Assert(index < btp->hdr.nused);
 
        /* Shuffle remaining keys. */
        --btp->hdr.nused;
        if (index < btp->hdr.nused)
-               memmove(&btp->u.leaf_key[index], btp->u.leaf_key[index + 1],
-                               sizeof(FreePageBtreeLeafKey) * btp->hdr.nused - index);
+               memmove(&btp->u.leaf_key[index], &btp->u.leaf_key[index + 1],
+                               sizeof(FreePageBtreeLeafKey) * (btp->hdr.nused - index));
 
        /*
         * XXX.  At this point, the key is gone, but the node may be empty or
@@ -277,7 +342,7 @@ FreePageBtreeSearch(FreePageManager *fpm, Size first_page,
                                        FreePageBtreeSearchResult *result)
 {
        char *base = fpm_segment_base(fpm);
-       FreePageBtree *btp = relptr_access(base, fpm->root);
+       FreePageBtree *btp = relptr_access(base, fpm->btree_root);
        Size    index;
 
        /* If the btree is empty, then this would be the only item. */
index 84ee0d39ab9f55c6d43c9781c005ee465fc7aedc..e33d35ae54b7a5a30d622b82df1c82d86350face 100644 (file)
@@ -49,11 +49,12 @@ typedef struct FreePageManager FreePageManager;
 /* Everything we need in order to manage free pages (see freepage.c) */
 struct FreePageManager
 {
-    relptr(FreePageManager)  self;
-    relptr(LWLock)  lock;
+       relptr(FreePageManager)  self;
+       relptr(LWLock)  lock;
        bool                    lock_address_is_fixed;
-    relptr(FreePageBtree)   root;
-    relptr(FreePageSpanLeader)  freelist[FPM_NUM_FREELISTS];
+       relptr(FreePageBtree)   btree_root;
+       relptr(FreePageSpanLeader)      btree_recycle;
+       relptr(FreePageSpanLeader)  freelist[FPM_NUM_FREELISTS];
 };
 
 /* Macros to convert between page numbers (expressed as Size) and pointers. */