[Patch] Space reservation (pgupgrade)

Поиск
Список
Период
Сортировка
От Zdenek Kotala
Тема [Patch] Space reservation (pgupgrade)
Дата
Msg-id 49424E74.2060605@sun.com
обсуждение исходный текст
Ответы Re: [Patch] Space reservation (pgupgrade)  (Heikki Linnakangas <heikki.linnakangas@enterprisedb.com>)
Список pgsql-hackers
I attached patch which add capability to reserve space on page for future
upgrade. It is mandatory for future in-place upgrade implementation. This patch
contains basic infrastructure not preupgrade script itself. I'm going to send
WIP preupgrade script today in separate mail.

This patch contains following modifications:

1) I added datpreupgstatus and relpreupgstatus attribute into pg_database and
pg_class. Original idea was to use only flag, but I need more info for tracking
several process status (like 0 - not set, 1 - reserved space set, 2 -
reservation is finished and so on).

I'm not sure if datpreupgstatus will be useful, but I think better is to have it
here.

2) I added two reloption rs_perpage and rs_pertuple for setup amount of reserved
space. I think these two attributes are enough for configure all case. Keep in
mind that for each relation could be these parameters different.

3) I adapted source code to respect new reloptions. Basic idea of it is that
before someone call PageAddItem it checks free space on a page
(PageGetFreeSpace...). I modify PageGetFreeSpace function to count reserved
space. Unfortunately, it requires additional parameters.

It works, but I'm not sure if any external enhancement cannot shortcut this and
call PageAddItem without PageFreeSpace call.

I'm thinking now about refactoring it and replace PageGetFreeSpace(Heap)
functions with RelPageGetFreeSpace and add new function RelPageAddItem.
RelPageAddItem will replace all direct call of PageAddItem.

    Comments, ideas?

        thanks Zdenek

diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/common/reloptions.c
pgsql_spacereserve/src/backend/access/common/reloptions.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/common/reloptions.c    2008-12-12 11:36:42.140563612 +0100
--- pgsql_spacereserve/src/backend/access/common/reloptions.c    2008-12-12 11:36:42.233907101 +0100
***************
*** 286,330 ****
  default_reloptions(Datum reloptions, bool validate,
                     int minFillfactor, int defaultFillfactor)
  {
!     static const char *const default_keywords[1] = {"fillfactor"};
!     char       *values[1];
!     int            fillfactor;
      StdRdOptions *result;

!     parseRelOptions(reloptions, 1, default_keywords, values, validate);

      /*
       * If no options, we can just return NULL rather than doing anything.
       * (defaultFillfactor is thus not used, but we require callers to pass it
       * anyway since we would need it if more options were added.)
       */
!     if (values[0] == NULL)
          return NULL;

!     if (!parse_int(values[0], &fillfactor, 0, NULL))
      {
!         if (validate)
!             ereport(ERROR,
!                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                      errmsg("fillfactor must be an integer: \"%s\"",
!                             values[0])));
!         return NULL;
      }

!     if (fillfactor < minFillfactor || fillfactor > 100)
      {
!         if (validate)
!             ereport(ERROR,
!                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                      errmsg("fillfactor=%d is out of range (should be between %d and 100)",
!                             fillfactor, minFillfactor)));
!         return NULL;
      }

      result = (StdRdOptions *) palloc(sizeof(StdRdOptions));
      SET_VARSIZE(result, sizeof(StdRdOptions));

      result->fillfactor = fillfactor;

      return (bytea *) result;
  }
--- 286,386 ----
  default_reloptions(Datum reloptions, bool validate,
                     int minFillfactor, int defaultFillfactor)
  {
!     static const char *const default_keywords[3] = {"fillfactor","rs_perpage","rs_pertuple"};
!     char       *values[3];
!     int            fillfactor=defaultFillfactor;
!     int            rs_perpage=0;
!     int            rs_pertuple=0;
      StdRdOptions *result;

!     parseRelOptions(reloptions, 3, default_keywords, values, validate);

      /*
       * If no options, we can just return NULL rather than doing anything.
       * (defaultFillfactor is thus not used, but we require callers to pass it
       * anyway since we would need it if more options were added.)
       */
!     if ((values[0] == NULL) && (values[1] == NULL) && (values[2] == NULL))
          return NULL;

!     /* fill factor */
!     if (values[0] != NULL)
      {
!         if (!parse_int(values[0], &fillfactor, 0, NULL))
!         {
!             if (validate)
!                 ereport(ERROR,
!                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                          errmsg("fillfactor must be an integer: \"%s\"",
!                                 values[0])));
!             return NULL;
!         }
!
!         if (fillfactor < minFillfactor || fillfactor > 100)
!         {
!             if (validate)
!                 ereport(ERROR,
!                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                          errmsg("fillfactor=%d is out of range (should be between %d and 100)",
!                                 fillfactor, minFillfactor)));
!             return NULL;
!         }
      }

!     /* reserved space per page */
!     if (values[1] != NULL)
      {
!         if (!parse_int(values[1], &rs_perpage, 0, NULL))
!         {
!             if (validate)
!                 ereport(ERROR,
!                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                          errmsg("rs_perpage must be an integer: \"%s\"",
!                                 values[1])));
!             return NULL;
!         }
!
!         if (rs_perpage < 0 || rs_perpage > BLCKSZ/4)
!         {
!             if (validate)
!                 ereport(ERROR,
!                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                          errmsg("rs_perpage=%d is out of range (should be between 0 and %d)",
!                                 rs_perpage, BLCKSZ/4)));
!             return NULL;
!         }
!     }
!
!     /* reserved space per tuple */
!     if (values[2] != NULL)
!     {
!         if (!parse_int(values[2], &rs_pertuple, 0, NULL))
!         {
!             if (validate)
!                 ereport(ERROR,
!                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                          errmsg("rs_pertuple must be an integer: \"%s\"",
!                                 values[2])));
!             return NULL;
!         }
!
!         if (rs_pertuple < 0 || rs_pertuple > BLCKSZ/16)
!         {
!             if (validate)
!                 ereport(ERROR,
!                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
!                          errmsg("rs_pertuple=%d is out of range (should be between 0 and %d)",
!                                 rs_perpage, BLCKSZ/16)));
!             return NULL;
!         }
      }

      result = (StdRdOptions *) palloc(sizeof(StdRdOptions));
      SET_VARSIZE(result, sizeof(StdRdOptions));

      result->fillfactor = fillfactor;
+     result->rs_perpage = rs_perpage;
+     result->rs_pertuple = rs_pertuple;

      return (bytea *) result;
  }
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gin/ginentrypage.c
pgsql_spacereserve/src/backend/access/gin/ginentrypage.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gin/ginentrypage.c    2008-12-12 11:36:42.142428004 +0100
--- pgsql_spacereserve/src/backend/access/gin/ginentrypage.c    2008-12-12 11:36:42.234193186 +0100
***************
*** 314,320 ****
          itupsz = MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
      }

!     if (PageGetFreeSpace(page) + itupsz >= MAXALIGN(IndexTupleSize(btree->entry)) + sizeof(ItemIdData))
          return true;

      return false;
--- 314,323 ----
          itupsz = MAXALIGN(IndexTupleSize(itup)) + sizeof(ItemIdData);
      }

!     if (PageGetFreeSpace(page,
!                          RelationGetReservedSpacePerPage(btree->index),
!                          RelationGetReservedSpacePerTuple(btree->index)) + itupsz
!              >= MAXALIGN(IndexTupleSize(btree->entry)) + sizeof(ItemIdData))
          return true;

      return false;
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gist.c
pgsql_spacereserve/src/backend/access/gist/gist.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gist.c    2008-12-12 11:36:42.145173957 +0100
--- pgsql_spacereserve/src/backend/access/gist/gist.c    2008-12-12 11:36:42.234512343 +0100
***************
*** 299,305 ****
       * XXX: If we want to change fillfactors between node and leaf, fillfactor
       * = (is_leaf ? state->leaf_fillfactor : state->node_fillfactor)
       */
!     if (gistnospace(state->stack->page, state->itup, state->ituplen,
                      is_leaf ? InvalidOffsetNumber : state->stack->childoffnum,
                      state->freespace))
      {
--- 299,305 ----
       * XXX: If we want to change fillfactors between node and leaf, fillfactor
       * = (is_leaf ? state->leaf_fillfactor : state->node_fillfactor)
       */
!     if (gistnospace(state->r, state->stack->page, state->itup, state->ituplen,
                      is_leaf ? InvalidOffsetNumber : state->stack->childoffnum,
                      state->freespace))
      {
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gistutil.c
pgsql_spacereserve/src/backend/access/gist/gistutil.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gistutil.c    2008-12-12 11:36:42.146684458 +0100
--- pgsql_spacereserve/src/backend/access/gist/gistutil.c    2008-12-12 11:36:42.234672831 +0100
***************
*** 56,62 ****
   * Check space for itup vector on page
   */
  bool
! gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
  {
      unsigned int size = freespace,
                  deleted = 0;
--- 56,62 ----
   * Check space for itup vector on page
   */
  bool
! gistnospace(Relation rel, Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
  {
      unsigned int size = freespace,
                  deleted = 0;
***************
*** 72,78 ****
          deleted = IndexTupleSize(itup) + sizeof(ItemIdData);
      }

!     return (PageGetFreeSpace(page) + deleted < size);
  }

  bool
--- 72,79 ----
          deleted = IndexTupleSize(itup) + sizeof(ItemIdData);
      }

!     return (PageGetFreeSpace(page, RelationGetReservedSpacePerPage(rel),
!                              RelationGetReservedSpacePerTuple(rel)) + deleted < size);
  }

  bool
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gistvacuum.c
pgsql_spacereserve/src/backend/access/gist/gistvacuum.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gistvacuum.c    2008-12-12 11:36:42.148527110 +0100
--- pgsql_spacereserve/src/backend/access/gist/gistvacuum.c    2008-12-12 11:36:42.234839579 +0100
***************
*** 385,391 ****
          if (curlenaddon)
          {
              /* insert updated tuples */
!             if (gistnospace(tempPage, addon, curlenaddon, InvalidOffsetNumber, 0))
              {
                  /* there is no space on page to insert tuples */
                  res = vacuumSplitPage(gv, tempPage, buffer, addon, curlenaddon);
--- 385,391 ----
          if (curlenaddon)
          {
              /* insert updated tuples */
!             if (gistnospace(gv->index, tempPage, addon, curlenaddon, InvalidOffsetNumber, 0))
              {
                  /* there is no space on page to insert tuples */
                  res = vacuumSplitPage(gv, tempPage, buffer, addon, curlenaddon);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gistxlog.c
pgsql_spacereserve/src/backend/access/gist/gistxlog.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/gist/gistxlog.c    2008-12-12 11:36:42.150448436 +0100
--- pgsql_spacereserve/src/backend/access/gist/gistxlog.c    2008-12-12 11:36:42.235025843 +0100
***************
*** 688,694 ****
               * hope, that wiil be enough space....
               */

!             if (gistnospace(pages[0], itup, lenitup, *todelete, 0))
              {

                  /* no space left on page, so we must split */
--- 688,694 ----
               * hope, that wiil be enough space....
               */

!             if (gistnospace(index, pages[0], itup, lenitup, *todelete, 0))
              {

                  /* no space left on page, so we must split */
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/hash/hashinsert.c
pgsql_spacereserve/src/backend/access/hash/hashinsert.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/hash/hashinsert.c    2008-12-12 11:36:42.151473973 +0100
--- pgsql_spacereserve/src/backend/access/hash/hashinsert.c    2008-12-12 11:36:42.235298303 +0100
***************
*** 106,112 ****
      Assert(pageopaque->hasho_bucket == bucket);

      /* Do the insertion */
!     while (PageGetFreeSpace(page) < itemsz)
      {
          /*
           * no space on this page; check for an overflow page
--- 106,113 ----
      Assert(pageopaque->hasho_bucket == bucket);

      /* Do the insertion */
!     while (PageGetFreeSpace(page,RelationGetReservedSpacePerPage(rel),
!             RelationGetReservedSpacePerTuple(rel)) < itemsz)
      {
          /*
           * no space on this page; check for an overflow page
***************
*** 138,144 ****
              page = BufferGetPage(buf);

              /* should fit now, given test above */
!             Assert(PageGetFreeSpace(page) >= itemsz);
          }
          pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
          Assert(pageopaque->hasho_flag == LH_OVERFLOW_PAGE);
--- 139,146 ----
              page = BufferGetPage(buf);

              /* should fit now, given test above */
!             Assert(PageGetFreeSpace(page, RelationGetReservedSpacePerPage(rel),
!                 RelationGetReservedSpacePerTuple(rel)) >= itemsz);
          }
          pageopaque = (HashPageOpaque) PageGetSpecialPointer(page);
          Assert(pageopaque->hasho_flag == LH_OVERFLOW_PAGE);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/hash/hashovfl.c
pgsql_spacereserve/src/backend/access/hash/hashovfl.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/hash/hashovfl.c    2008-12-12 11:36:42.154025625 +0100
--- pgsql_spacereserve/src/backend/access/hash/hashovfl.c    2008-12-12 11:36:42.235471115 +0100
***************
*** 656,662 ****
               * Walk up the bucket chain, looking for a page big enough for
               * this item.  Exit if we reach the read page.
               */
!             while (PageGetFreeSpace(wpage) < itemsz)
              {
                  Assert(!PageIsEmpty(wpage));

--- 656,663 ----
               * Walk up the bucket chain, looking for a page big enough for
               * this item.  Exit if we reach the read page.
               */
!             while (PageGetFreeSpace(wpage, RelationGetReservedSpacePerPage(rel),
!                     RelationGetReservedSpacePerTuple(rel)) < itemsz)
              {
                  Assert(!PageIsEmpty(wpage));

diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/hash/hashpage.c
pgsql_spacereserve/src/backend/access/hash/hashpage.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/hash/hashpage.c    2008-12-12 11:36:42.157263189 +0100
--- pgsql_spacereserve/src/backend/access/hash/hashpage.c    2008-12-12 11:36:42.235655078 +0100
***************
*** 856,862 ****
              itemsz = IndexTupleDSize(*itup);
              itemsz = MAXALIGN(itemsz);

!             if (PageGetFreeSpace(npage) < itemsz)
              {
                  /* write out nbuf and drop lock, but keep pin */
                  _hash_chgbufaccess(rel, nbuf, HASH_WRITE, HASH_NOLOCK);
--- 856,863 ----
              itemsz = IndexTupleDSize(*itup);
              itemsz = MAXALIGN(itemsz);

!             if (PageGetFreeSpace(npage, RelationGetReservedSpacePerPage(rel),
!                 RelationGetReservedSpacePerTuple(rel)) < itemsz)
              {
                  /* write out nbuf and drop lock, but keep pin */
                  _hash_chgbufaccess(rel, nbuf, HASH_WRITE, HASH_NOLOCK);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/heapam.c
pgsql_spacereserve/src/backend/access/heap/heapam.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/heapam.c    2008-12-12 11:36:42.169918324 +0100
--- pgsql_spacereserve/src/backend/access/heap/heapam.c    2008-12-12 11:36:42.236162107 +0100
***************
*** 2634,2640 ****
                        HeapTupleHasExternal(newtup) ||
                        newtup->t_len > TOAST_TUPLE_THRESHOLD);

!     pagefree = PageGetHeapFreeSpace(page);

      newtupsize = MAXALIGN(newtup->t_len);

--- 2634,2642 ----
                        HeapTupleHasExternal(newtup) ||
                        newtup->t_len > TOAST_TUPLE_THRESHOLD);

!     pagefree = PageGetHeapFreeSpace(page,
!                                     RelationGetReservedSpacePerPage(relation),
!                                     RelationGetReservedSpacePerTuple(relation));

      newtupsize = MAXALIGN(newtup->t_len);

***************
*** 2699,2705 ****
              /* Re-acquire the lock on the old tuple's page. */
              LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
              /* Re-check using the up-to-date free space */
!             pagefree = PageGetHeapFreeSpace(page);
              if (newtupsize > pagefree)
              {
                  /*
--- 2701,2709 ----
              /* Re-acquire the lock on the old tuple's page. */
              LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
              /* Re-check using the up-to-date free space */
!             pagefree = PageGetHeapFreeSpace(page,
!                                             RelationGetReservedSpacePerPage(relation),
!                                             RelationGetReservedSpacePerTuple(relation));
              if (newtupsize > pagefree)
              {
                  /*
***************
*** 4155,4161 ****
                              nowunused, nunused,
                              clean_move);

!     freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */

      /*
       * Note: we don't worry about updating the page's prunability hints.
--- 4159,4167 ----
                              nowunused, nunused,
                              clean_move);

!     /* needed to update FSM below, we ignore reservation here, because there is
!         no relation information and FSM can be inaccurate */
!     freespace = PageGetHeapFreeSpace(page, 0, 0);

      /*
       * Note: we don't worry about updating the page's prunability hints.
***************
*** 4397,4407 ****
      HeapTupleHeaderSetCmin(htup, FirstCommandId);
      htup->t_ctid = xlrec->target.tid;

      offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true);
      if (offnum == InvalidOffsetNumber)
          elog(PANIC, "heap_insert_redo: failed to add tuple");

!     freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */

      PageSetLSN(page, lsn);
      PageSetTLI(page, ThisTimeLineID);
--- 4403,4417 ----
      HeapTupleHeaderSetCmin(htup, FirstCommandId);
      htup->t_ctid = xlrec->target.tid;

+     /* XXX: Should we check reserved space here? It is probably not problem,
+       because item is added and WAL logged only if reserved space is OK */
      offnum = PageAddItem(page, (Item) htup, newlen, offnum, true, true);
      if (offnum == InvalidOffsetNumber)
          elog(PANIC, "heap_insert_redo: failed to add tuple");

!     /* needed to update FSM below, we ignore reservation here, because there is
!         no relation information and FSM can be inaccurate */
!     freespace = PageGetHeapFreeSpace(page, 0, 0);

      PageSetLSN(page, lsn);
      PageSetTLI(page, ThisTimeLineID);
***************
*** 4635,4641 ****
      if (xlrec->new_all_visible_cleared)
          PageClearAllVisible(page);

!     freespace = PageGetHeapFreeSpace(page); /* needed to update FSM below */

      PageSetLSN(page, lsn);
      PageSetTLI(page, ThisTimeLineID);
--- 4645,4653 ----
      if (xlrec->new_all_visible_cleared)
          PageClearAllVisible(page);

!     /* needed to update FSM below, we ignore reservation here, because there is
!         no relation information and FSM can be inaccurate */
!     freespace = PageGetHeapFreeSpace(page,0,0);

      PageSetLSN(page, lsn);
      PageSetTLI(page, ThisTimeLineID);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/hio.c
pgsql_spacereserve/src/backend/access/heap/hio.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/hio.c    2008-12-12 11:36:42.172119886 +0100
--- pgsql_spacereserve/src/backend/access/heap/hio.c    2008-12-12 11:36:42.236322663 +0100
***************
*** 269,275 ****
           * we're done.
           */
          page = BufferGetPage(buffer);
!         pageFreeSpace = PageGetHeapFreeSpace(page);
          if (len + saveFreeSpace <= pageFreeSpace)
          {
              /* use this page as future insert target, too */
--- 269,277 ----
           * we're done.
           */
          page = BufferGetPage(buffer);
!         pageFreeSpace = PageGetHeapFreeSpace(page,
!                                              RelationGetReservedSpacePerPage(relation),
!                                              RelationGetReservedSpacePerTuple(relation));
          if (len + saveFreeSpace <= pageFreeSpace)
          {
              /* use this page as future insert target, too */
***************
*** 362,368 ****

      PageInit(page, BufferGetPageSize(buffer), 0);

!     if (len > PageGetHeapFreeSpace(page))
      {
          /* We should not get here given the test at the top */
          elog(PANIC, "tuple is too big: size %lu", (unsigned long) len);
--- 364,372 ----

      PageInit(page, BufferGetPageSize(buffer), 0);

!     if (len > PageGetHeapFreeSpace(page,
!                                    RelationGetReservedSpacePerPage(relation),
!                                    RelationGetReservedSpacePerTuple(relation)))
      {
          /* We should not get here given the test at the top */
          elog(PANIC, "tuple is too big: size %lu", (unsigned long) len);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/pruneheap.c
pgsql_spacereserve/src/backend/access/heap/pruneheap.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/pruneheap.c    2008-12-12 11:36:42.173608706 +0100
--- pgsql_spacereserve/src/backend/access/heap/pruneheap.c    2008-12-12 11:36:42.236500498 +0100
***************
*** 100,106 ****
                                               HEAP_DEFAULT_FILLFACTOR);
      minfree = Max(minfree, BLCKSZ / 10);

!     if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
      {
          /* OK, try to get exclusive buffer lock */
          if (!ConditionalLockBufferForCleanup(buffer))
--- 100,109 ----
                                               HEAP_DEFAULT_FILLFACTOR);
      minfree = Max(minfree, BLCKSZ / 10);

!     if (PageIsFull(page) ||
!         PageGetHeapFreeSpace(page,
!                              RelationGetReservedSpacePerPage(relation),
!                              RelationGetReservedSpacePerTuple(relation)) < minfree)
      {
          /* OK, try to get exclusive buffer lock */
          if (!ConditionalLockBufferForCleanup(buffer))
***************
*** 112,118 ****
           * prune. (We needn't recheck PageIsPrunable, since no one else could
           * have pruned while we hold pin.)
           */
!         if (PageIsFull(page) || PageGetHeapFreeSpace(page) < minfree)
          {
              /* OK to prune (though not to remove redirects) */
              (void) heap_page_prune(relation, buffer, OldestXmin, false, true);
--- 115,124 ----
           * prune. (We needn't recheck PageIsPrunable, since no one else could
           * have pruned while we hold pin.)
           */
!         if (PageIsFull(page) ||
!             PageGetHeapFreeSpace(page,
!                                  RelationGetReservedSpacePerPage(relation),
!                                  RelationGetReservedSpacePerTuple(relation)))
          {
              /* OK to prune (though not to remove redirects) */
              (void) heap_page_prune(relation, buffer, OldestXmin, false, true);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/rewriteheap.c
pgsql_spacereserve/src/backend/access/heap/rewriteheap.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/heap/rewriteheap.c    2008-12-12 11:36:42.174776964 +0100
--- pgsql_spacereserve/src/backend/access/heap/rewriteheap.c    2008-12-12 11:36:42.236670422 +0100
***************
*** 600,606 ****
      /* Now we can check to see if there's enough free space already. */
      if (state->rs_buffer_valid)
      {
!         pageFreeSpace = PageGetHeapFreeSpace(page);

          if (len + saveFreeSpace > pageFreeSpace)
          {
--- 600,608 ----
      /* Now we can check to see if there's enough free space already. */
      if (state->rs_buffer_valid)
      {
!         pageFreeSpace = PageGetHeapFreeSpace(page,
!                                              RelationGetReservedSpacePerPage(state->rs_new_rel),
!                                              RelationGetReservedSpacePerTuple(state->rs_new_rel));

          if (len + saveFreeSpace > pageFreeSpace)
          {
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/nbtree/nbtinsert.c
pgsql_spacereserve/src/backend/access/nbtree/nbtinsert.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/nbtree/nbtinsert.c    2008-12-12 11:36:42.179054235 +0100
--- pgsql_spacereserve/src/backend/access/nbtree/nbtinsert.c    2008-12-12 11:36:42.237013648 +0100
***************
*** 79,85 ****
              int keysz, ScanKey scankey);
  static void _bt_vacuum_one_page(Relation rel, Buffer buffer);

-
  /*
   *    _bt_doinsert() -- Handle insertion of a single index tuple in the tree.
   *
--- 79,84 ----
***************
*** 445,451 ****
       */
      movedright = false;
      vacuumed = false;
!     while (PageGetFreeSpace(page) < itemsz)
      {
          Buffer        rbuf;

--- 444,452 ----
       */
      movedright = false;
      vacuumed = false;
!     while (PageGetFreeSpace(page,
!                              RelationGetReservedSpacePerPage(rel),
!                              RelationGetReservedSpacePerTuple(rel)) < itemsz)
      {
          Buffer        rbuf;

***************
*** 463,469 ****
               */
              vacuumed = true;

!             if (PageGetFreeSpace(page) >= itemsz)
                  break;            /* OK, now we have enough space */
          }

--- 464,472 ----
               */
              vacuumed = true;

!             if (PageGetFreeSpace(page,
!                                   RelationGetReservedSpacePerPage(rel),
!                                   RelationGetReservedSpacePerTuple(rel)) >= itemsz)
                  break;            /* OK, now we have enough space */
          }

***************
*** 579,585 ****
       * so this comparison is correct even though we appear to be accounting
       * only for the item and not for its line pointer.
       */
!     if (PageGetFreeSpace(page) < itemsz)
      {
          bool        is_root = P_ISROOT(lpageop);
          bool        is_only = P_LEFTMOST(lpageop) && P_RIGHTMOST(lpageop);
--- 582,590 ----
       * so this comparison is correct even though we appear to be accounting
       * only for the item and not for its line pointer.
       */
!     if (PageGetFreeSpace(page,
!                          RelationGetReservedSpacePerPage(rel),
!                          RelationGetReservedSpacePerTuple(rel)) < itemsz)
      {
          bool        is_root = P_ISROOT(lpageop);
          bool        is_only = P_LEFTMOST(lpageop) && P_RIGHTMOST(lpageop);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/access/nbtree/nbtsort.c
pgsql_spacereserve/src/backend/access/nbtree/nbtsort.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/access/nbtree/nbtsort.c    2008-12-12 11:36:42.182353003 +0100
--- pgsql_spacereserve/src/backend/access/nbtree/nbtsort.c    2008-12-12 11:36:42.237190941 +0100
***************
*** 462,468 ****
      nblkno = state->btps_blkno;
      last_off = state->btps_lastoff;

!     pgspc = PageGetFreeSpace(npage);
      itupsz = IndexTupleDSize(*itup);
      itupsz = MAXALIGN(itupsz);

--- 462,470 ----
      nblkno = state->btps_blkno;
      last_off = state->btps_lastoff;

!     pgspc = PageGetFreeSpace(npage,
!                               RelationGetReservedSpacePerPage(wstate->index),
!                               RelationGetReservedSpacePerTuple(wstate->index));
      itupsz = IndexTupleDSize(*itup);
      itupsz = MAXALIGN(itupsz);

diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/commands/dbcommands.c
pgsql_spacereserve/src/backend/commands/dbcommands.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/commands/dbcommands.c    2008-12-12 11:36:42.188926495 +0100
--- pgsql_spacereserve/src/backend/commands/dbcommands.c    2008-12-12 11:36:42.237524718 +0100
***************
*** 518,523 ****
--- 518,524 ----
      new_record[Anum_pg_database_datlastsysoid - 1] = ObjectIdGetDatum(src_lastsysoid);
      new_record[Anum_pg_database_datfrozenxid - 1] = TransactionIdGetDatum(src_frozenxid);
      new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace);
+     new_record[Anum_pg_database_datpreupgstatus - 1] = Int32GetDatum(0);

      /*
       * We deliberately set datconfig and datacl to defaults (NULL), rather
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/commands/vacuum.c
pgsql_spacereserve/src/backend/commands/vacuum.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/commands/vacuum.c    2008-12-12 11:36:42.200107235 +0100
--- pgsql_spacereserve/src/backend/commands/vacuum.c    2008-12-12 11:36:42.237837082 +0100
***************
*** 3796,3801 ****
--- 3796,3807 ----
      Size        freespace = PageGetExactFreeSpace(page);
      Size        targetfree;

+     /* we need to reserve space, it could reserved more space because we count
+        all line pointers, not only normal */
+     freespace -= (RelationGetReservedSpacePerPage(relation)+
+                   PageGetMaxOffsetNumber(page)*RelationGetReservedSpacePerTuple(relation));
+
+     freespace = freespace < 0 ? 0 : freespace;
      targetfree = RelationGetTargetPageFreeSpace(relation,
                                                  HEAP_DEFAULT_FILLFACTOR);
      if (freespace > targetfree)
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/commands/vacuumlazy.c
pgsql_spacereserve/src/backend/commands/vacuumlazy.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/commands/vacuumlazy.c    2008-12-12 11:36:42.204215141 +0100
--- pgsql_spacereserve/src/backend/commands/vacuumlazy.c    2008-12-12 11:36:42.238023285 +0100
***************
*** 370,376 ****
                  PageInit(page, BufferGetPageSize(buf), 0);
                  empty_pages++;
              }
!             freespace = PageGetHeapFreeSpace(page);
              MarkBufferDirty(buf);
              UnlockReleaseBuffer(buf);

--- 370,378 ----
                  PageInit(page, BufferGetPageSize(buf), 0);
                  empty_pages++;
              }
!             freespace = PageGetHeapFreeSpace(page,
!                                                RelationGetReservedSpacePerPage(onerel),
!                                                RelationGetReservedSpacePerTuple(onerel));
              MarkBufferDirty(buf);
              UnlockReleaseBuffer(buf);

***************
*** 381,387 ****
          if (PageIsEmpty(page))
          {
              empty_pages++;
!             freespace = PageGetHeapFreeSpace(page);

              if (!PageIsAllVisible(page))
              {
--- 383,391 ----
          if (PageIsEmpty(page))
          {
              empty_pages++;
!             freespace = PageGetHeapFreeSpace(page,
!                                                RelationGetReservedSpacePerPage(onerel),
!                                                RelationGetReservedSpacePerTuple(onerel));

              if (!PageIsAllVisible(page))
              {
***************
*** 606,612 ****
              vacuumed_pages++;
          }

!         freespace = PageGetHeapFreeSpace(page);

          /* Update the all-visible flag on the page */
          if (!PageIsAllVisible(page) && all_visible)
--- 610,618 ----
              vacuumed_pages++;
          }

!         freespace = PageGetHeapFreeSpace(page,
!                                            RelationGetReservedSpacePerPage(onerel),
!                                            RelationGetReservedSpacePerTuple(onerel));

          /* Update the all-visible flag on the page */
          if (!PageIsAllVisible(page) && all_visible)
***************
*** 747,753 ****

          /* Now that we've compacted the page, record its available space */
          page = BufferGetPage(buf);
!         freespace = PageGetHeapFreeSpace(page);

          UnlockReleaseBuffer(buf);
          RecordPageWithFreeSpace(onerel, tblk, freespace);
--- 753,761 ----

          /* Now that we've compacted the page, record its available space */
          page = BufferGetPage(buf);
!         freespace = PageGetHeapFreeSpace(page,
!                                            RelationGetReservedSpacePerPage(onerel),
!                                            RelationGetReservedSpacePerTuple(onerel));

          UnlockReleaseBuffer(buf);
          RecordPageWithFreeSpace(onerel, tblk, freespace);
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/storage/page/bufpage.c
pgsql_spacereserve/src/backend/storage/page/bufpage.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/storage/page/bufpage.c    2008-12-12 11:36:42.207450074 +0100
--- pgsql_spacereserve/src/backend/storage/page/bufpage.c    2008-12-12 11:36:42.238404271 +0100
***************
*** 482,497 ****
   * PageGetHeapFreeSpace on heap pages.
   */
  Size
! PageGetFreeSpace(Page page)
  {
      int            space;

      /*
       * Use signed arithmetic here so that we behave sensibly if pd_lower >
       * pd_upper.
       */
      space = (int) ((PageHeader) page)->pd_upper -
!         (int) ((PageHeader) page)->pd_lower;

      if (space < (int) sizeof(ItemIdData))
          return 0;
--- 482,502 ----
   * PageGetHeapFreeSpace on heap pages.
   */
  Size
! PageGetFreeSpace(Page page, int rs_perpage, int rs_pertuple)
  {
      int            space;
+     int            reserved_space;
+
+     /* Count reserved space. It is used for in-place upgrade. Because this functions
+        is usually called before PageAddItem we need to count with new item */
+     reserved_space = rs_perpage+rs_pertuple*(PageGetMaxOffsetNumber(page)+1);

      /*
       * Use signed arithmetic here so that we behave sensibly if pd_lower >
       * pd_upper.
       */
      space = (int) ((PageHeader) page)->pd_upper -
!         (int) ((PageHeader) page)->pd_lower - reserved_space;

      if (space < (int) sizeof(ItemIdData))
          return 0;
***************
*** 539,549 ****
   * on the number of line pointers, we make this extra check.)
   */
  Size
! PageGetHeapFreeSpace(Page page)
  {
      Size        space;

!     space = PageGetFreeSpace(page);
      if (space > 0)
      {
          OffsetNumber offnum,
--- 544,554 ----
   * on the number of line pointers, we make this extra check.)
   */
  Size
! PageGetHeapFreeSpace(Page page, int rs_perpage, int rs_pertuple)
  {
      Size        space;

!     space = PageGetFreeSpace(page, rs_perpage, rs_pertuple);
      if (space > 0)
      {
          OffsetNumber offnum,
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/backend/utils/cache/relcache.c
pgsql_spacereserve/src/backend/utils/cache/relcache.c
*** pgsql_spacereserve.84e2e9c42ef7/src/backend/utils/cache/relcache.c    2008-12-12 11:36:42.220122442 +0100
--- pgsql_spacereserve/src/backend/utils/cache/relcache.c    2008-12-12 11:36:42.238944249 +0100
***************
*** 2409,2414 ****
--- 2409,2415 ----
      rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
      rel->rd_rel->relnatts = natts;
      rel->rd_rel->reltype = InvalidOid;
+     rel->rd_rel->relpreupgstatus = 0;
      /* needed when bootstrapping: */
      rel->rd_rel->relowner = BOOTSTRAP_SUPERUSERID;

diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/include/access/gist_private.h
pgsql_spacereserve/src/include/access/gist_private.h
*** pgsql_spacereserve.84e2e9c42ef7/src/include/access/gist_private.h    2008-12-12 11:36:42.221738954 +0100
--- pgsql_spacereserve/src/include/access/gist_private.h    2008-12-12 11:36:42.239308369 +0100
***************
*** 279,285 ****

  extern Datum gistoptions(PG_FUNCTION_ARGS);
  extern bool gistfitpage(IndexTuple *itvec, int len);
! extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
  extern void gistcheckpage(Relation rel, Buffer buf);
  extern Buffer gistNewBuffer(Relation r);
  extern void gistfillbuffer(Page page, IndexTuple *itup, int len,
--- 279,285 ----

  extern Datum gistoptions(PG_FUNCTION_ARGS);
  extern bool gistfitpage(IndexTuple *itvec, int len);
! extern bool gistnospace(Relation rel, Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
  extern void gistcheckpage(Relation rel, Buffer buf);
  extern Buffer gistNewBuffer(Relation r);
  extern void gistfillbuffer(Page page, IndexTuple *itup, int len,
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/include/catalog/pg_attribute.h
pgsql_spacereserve/src/include/catalog/pg_attribute.h
*** pgsql_spacereserve.84e2e9c42ef7/src/include/catalog/pg_attribute.h    2008-12-12 11:36:42.225592264 +0100
--- pgsql_spacereserve/src/include/catalog/pg_attribute.h    2008-12-12 11:36:42.239591992 +0100
***************
*** 419,426 ****
  { 1259, {"relhastriggers"},16, -1,    1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1259, {"relhassubclass"},16, -1,    1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1259, {"relfrozenxid"},  28, -1,    4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relacl"},         1034, -1, -1, 23, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1259, {"reloptions"},  1009, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }

  DATA(insert ( 1259 relname            19 -1 NAMEDATALEN    1 0 -1 -1 f p c t f f t 0));
  DATA(insert ( 1259 relnamespace        26 -1 4   2 0 -1 -1 t p i t f f t 0));
--- 419,427 ----
  { 1259, {"relhastriggers"},16, -1,    1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1259, {"relhassubclass"},16, -1,    1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1259, {"relfrozenxid"},  28, -1,    4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relpreupgstatus"}, 21, -1,    2, 23, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relacl"},         1034, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1259, {"reloptions"},  1009, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }

  DATA(insert ( 1259 relname            19 -1 NAMEDATALEN    1 0 -1 -1 f p c t f f t 0));
  DATA(insert ( 1259 relnamespace        26 -1 4   2 0 -1 -1 t p i t f f t 0));
***************
*** 444,451 ****
  DATA(insert ( 1259 relhastriggers    16 -1 1  20 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1259 relhassubclass    16 -1 1  21 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1259 relfrozenxid        28 -1 4  22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relacl          1034 -1 -1 23 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1259 reloptions      1009 -1 -1 24 1 -1 -1 f x i f f f t 0));
  DATA(insert ( 1259 ctid                27 0  6  -1 0 -1 -1 f p s t f f t 0));
  DATA(insert ( 1259 oid                26 0  4  -2 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1259 xmin                28 0  4  -3 0 -1 -1 t p i t f f t 0));
--- 445,453 ----
  DATA(insert ( 1259 relhastriggers    16 -1 1  20 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1259 relhassubclass    16 -1 1  21 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1259 relfrozenxid        28 -1 4  22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relpreupgstatus    21 -1 2  23 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relacl          1034 -1 -1 24 1 -1 -1 f x i f f f t 0));
! DATA(insert ( 1259 reloptions      1009 -1 -1 25 1 -1 -1 f x i f f f t 0));
  DATA(insert ( 1259 ctid                27 0  6  -1 0 -1 -1 f p s t f f t 0));
  DATA(insert ( 1259 oid                26 0  4  -2 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1259 xmin                28 0  4  -3 0 -1 -1 t p i t f f t 0));
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/include/catalog/pg_class.h
pgsql_spacereserve/src/include/catalog/pg_class.h
*** pgsql_spacereserve.84e2e9c42ef7/src/include/catalog/pg_class.h    2008-12-12 11:36:42.227311049 +0100
--- pgsql_spacereserve/src/include/catalog/pg_class.h    2008-12-12 11:36:42.239737867 +0100
***************
*** 58,63 ****
--- 58,64 ----
      bool        relhastriggers;    /* has (or has had) any TRIGGERs */
      bool        relhassubclass; /* has (or has had) derived classes */
      TransactionId relfrozenxid; /* all Xids < this are frozen in this rel */
+     int2        relpreupgstatus;  /* tatus of pre-upgrade process */

      /*
       * VARIABLE LENGTH FIELDS start here.  These fields may be NULL, too.
***************
*** 71,77 ****

  /* Size of fixed part of pg_class tuples, not counting var-length fields */
  #define CLASS_TUPLE_SIZE \
!      (offsetof(FormData_pg_class,relfrozenxid) + sizeof(TransactionId))

  /* ----------------
   *        Form_pg_class corresponds to a pointer to a tuple with
--- 72,78 ----

  /* Size of fixed part of pg_class tuples, not counting var-length fields */
  #define CLASS_TUPLE_SIZE \
!      (offsetof(FormData_pg_class,relpreupgstatus) + sizeof(int2))

  /* ----------------
   *        Form_pg_class corresponds to a pointer to a tuple with
***************
*** 85,91 ****
   * ----------------
   */

! #define Natts_pg_class                    24
  #define Anum_pg_class_relname            1
  #define Anum_pg_class_relnamespace        2
  #define Anum_pg_class_reltype            3
--- 86,92 ----
   * ----------------
   */

! #define Natts_pg_class                    25
  #define Anum_pg_class_relname            1
  #define Anum_pg_class_relnamespace        2
  #define Anum_pg_class_reltype            3
***************
*** 108,115 ****
  #define Anum_pg_class_relhastriggers    20
  #define Anum_pg_class_relhassubclass    21
  #define Anum_pg_class_relfrozenxid        22
! #define Anum_pg_class_relacl            23
! #define Anum_pg_class_reloptions        24

  /* ----------------
   *        initial contents of pg_class
--- 109,117 ----
  #define Anum_pg_class_relhastriggers    20
  #define Anum_pg_class_relhassubclass    21
  #define Anum_pg_class_relfrozenxid        22
! #define Anum_pg_class_relisupgready        23
! #define Anum_pg_class_relacl            24
! #define Anum_pg_class_reloptions        25

  /* ----------------
   *        initial contents of pg_class
***************
*** 121,133 ****
   */

  /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
! DATA(insert OID = 1247 (  pg_type        PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 28 0 t f f f f 3 _null_ _null_ ));
  DESCR("");
! DATA(insert OID = 1249 (  pg_attribute    PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 f f f f f 3 _null_ _null_ ));
  DESCR("");
! DATA(insert OID = 1255 (  pg_proc        PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 24 0 t f f f f 3 _null_ _null_ ));
  DESCR("");
! DATA(insert OID = 1259 (  pg_class        PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 24 0 t f f f f 3 _null_ _null_ ));
  DESCR("");

  #define          RELKIND_INDEX              'i'        /* secondary index */
--- 123,135 ----
   */

  /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
! DATA(insert OID = 1247 (  pg_type        PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 28 0 t f f f f 3 0 _null_ _null_ ));
  DESCR("");
! DATA(insert OID = 1249 (  pg_attribute    PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 f f f f f 3 0 _null_ _null_ ));
  DESCR("");
! DATA(insert OID = 1255 (  pg_proc        PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 24 0 t f f f f 3 0 _null_ _null_ ));
  DESCR("");
! DATA(insert OID = 1259 (  pg_class        PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 25 0 t f f f f 3 0 _null_ _null_ ));
  DESCR("");

  #define          RELKIND_INDEX              'i'        /* secondary index */
diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/include/catalog/pg_database.h
pgsql_spacereserve/src/include/catalog/pg_database.h
*** pgsql_spacereserve.84e2e9c42ef7/src/include/catalog/pg_database.h    2008-12-12 11:36:42.228306479 +0100
--- pgsql_spacereserve/src/include/catalog/pg_database.h    2008-12-12 11:36:42.239875956 +0100
***************
*** 41,46 ****
--- 41,47 ----
      Oid            datlastsysoid;    /* highest OID to consider a system OID */
      TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */
      Oid            dattablespace;    /* default table space for this DB */
+     int2        datpreupgstatus;/* status of pre-upgrade process */
      text        datconfig[1];    /* database-specific GUC (VAR LENGTH) */
      aclitem        datacl[1];        /* access permissions (VAR LENGTH) */
  } FormData_pg_database;
***************
*** 56,62 ****
   *        compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database                13
  #define Anum_pg_database_datname        1
  #define Anum_pg_database_datdba            2
  #define Anum_pg_database_encoding        3
--- 57,63 ----
   *        compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database                14
  #define Anum_pg_database_datname        1
  #define Anum_pg_database_datdba            2
  #define Anum_pg_database_encoding        3
***************
*** 68,77 ****
  #define Anum_pg_database_datlastsysoid    9
  #define Anum_pg_database_datfrozenxid    10
  #define Anum_pg_database_dattablespace    11
! #define Anum_pg_database_datconfig        12
! #define Anum_pg_database_datacl            13

! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_ _null_));
  SHDESCR("default template database");
  #define TemplateDbOid            1

--- 69,79 ----
  #define Anum_pg_database_datlastsysoid    9
  #define Anum_pg_database_datfrozenxid    10
  #define Anum_pg_database_dattablespace    11
! #define Anum_pg_database_datpreupgstatus 12
! #define Anum_pg_database_datconfig        13
! #define Anum_pg_database_datacl            14

! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 0 _null_ _null_));
  SHDESCR("default template database");
  #define TemplateDbOid            1

diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/include/storage/bufpage.h
pgsql_spacereserve/src/include/storage/bufpage.h
*** pgsql_spacereserve.84e2e9c42ef7/src/include/storage/bufpage.h    2008-12-12 11:36:42.231179457 +0100
--- pgsql_spacereserve/src/include/storage/bufpage.h    2008-12-12 11:36:42.240214381 +0100
***************
*** 361,366 ****
--- 361,374 ----
  #define PageClearPrunable(page) \
      (((PageHeader) (page))->pd_prune_xid = InvalidTransactionId)

+ /* PageGetMaxDataSpace
+  * It returns maximal possible amount of space for data on the page. If page has
+  * already item pointers we take them as a non-data space. The reason is that we
+  * cannot reclaim this space for data if it is marked as dead, beacause indexes
+  * can have a pointer on this item.
+  */
+ #define PageGetMaxDataSpace(page) \
+     ( ((PageHeader) (page))->pd_special - MAXALIGN(((PageHeader) (page))->pd_lower) )

  /* ----------------------------------------------------------------
   *        extern declarations
***************
*** 376,384 ****
  extern Page PageGetTempPageCopySpecial(Page page);
  extern void PageRestoreTempPage(Page tempPage, Page oldPage);
  extern void PageRepairFragmentation(Page page);
! extern Size PageGetFreeSpace(Page page);
  extern Size PageGetExactFreeSpace(Page page);
! extern Size PageGetHeapFreeSpace(Page page);
  extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
  extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems);

--- 384,392 ----
  extern Page PageGetTempPageCopySpecial(Page page);
  extern void PageRestoreTempPage(Page tempPage, Page oldPage);
  extern void PageRepairFragmentation(Page page);
! extern Size PageGetFreeSpace(Page page, int rs_perpage, int rs_pertuple);
  extern Size PageGetExactFreeSpace(Page page);
! extern Size PageGetHeapFreeSpace(Page page, int rs_perpage, int rs_pertuple);
  extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
  extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems);

diff -Nrc pgsql_spacereserve.84e2e9c42ef7/src/include/utils/rel.h pgsql_spacereserve/src/include/utils/rel.h
*** pgsql_spacereserve.84e2e9c42ef7/src/include/utils/rel.h    2008-12-12 11:36:42.233198428 +0100
--- pgsql_spacereserve/src/include/utils/rel.h    2008-12-12 11:36:42.240482307 +0100
***************
*** 218,223 ****
--- 218,225 ----
  {
      int32        vl_len_;        /* varlena header (do not touch directly!) */
      int            fillfactor;        /* page fill factor in percent (0..100) */
+     int            rs_perpage;      /* page reserved space per page for in-place upgrade in bytes */
+     int            rs_pertuple;      /* page reserved space per tuple for in-place upgrade in bytes */
  } StdRdOptions;

  #define HEAP_MIN_FILLFACTOR            10
***************
*** 232,237 ****
--- 234,255 ----
       ((StdRdOptions *) (relation)->rd_options)->fillfactor : (defaultff))

  /*
+  * RelationGetReservedSpacePerPage
+  *        Returns the relation's reserved space per page.
+  */
+ #define RelationGetReservedSpacePerPage(relation) \
+     ((relation)->rd_options ? \
+      ((StdRdOptions *) (relation)->rd_options)->rs_perpage : 0)
+
+ /*
+  * RelationGetReservedSpacePerTuple
+  *        Returns the relation's reserved space per tuple.
+  */
+ #define RelationGetReservedSpacePerTuple(relation) \
+     ((relation)->rd_options ? \
+      ((StdRdOptions *) (relation)->rd_options)->rs_pertuple : 0)
+
+ /*
   * RelationGetTargetPageUsage
   *        Returns the relation's desired space usage per page in bytes.
   */

В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Fujii Masao"
Дата:
Сообщение: Re: Sync Rep: First Thoughts on Code
Следующее
От: "Robert Haas"
Дата:
Сообщение: Re: benchmarking the query planner