[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 по дате отправления: