diff options
Diffstat (limited to 'src/backend/access/heap/hio.c')
-rw-r--r-- | src/backend/access/heap/hio.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index 82fb0a3268a..aaaec863ba1 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.62 2006/07/02 02:23:18 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/hio.c,v 1.63 2006/07/03 22:45:37 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -93,6 +93,11 @@ RelationPutHeapTuple(Relation relation, * any committed data of other transactions. (See heap_insert's comments * for additional constraints needed for safe usage of this behavior.) * + * We always try to avoid filling existing pages further than the fillfactor. + * This is OK since this routine is not consulted when updating a tuple and + * keeping it on the same page, which is the scenario fillfactor is meant + * to reserve space for. + * * ereport(ERROR) is allowed here, so this routine *must* be called * before any (unlogged) changes are made in buffer pool. */ @@ -103,17 +108,12 @@ RelationGetBufferForTuple(Relation relation, Size len, Buffer buffer = InvalidBuffer; Page pageHeader; Size pageFreeSpace, - freespace; + saveFreeSpace; BlockNumber targetBlock, otherBlock; bool needLock; - if (relation->rd_options == NULL) - elog(ERROR, "RelationGetBufferForTuple %s IS NULL", RelationGetRelationName(relation)); - Assert(relation->rd_options != NULL); - len = MAXALIGN(len); /* be conservative */ - freespace = HeapGetPageFreeSpace(relation); /* * If we're gonna fail for oversize tuple, do it right away @@ -125,6 +125,10 @@ RelationGetBufferForTuple(Relation relation, Size len, (unsigned long) len, (unsigned long) MaxTupleSize))); + /* Compute desired extra freespace due to fillfactor option */ + saveFreeSpace = RelationGetTargetPageFreeSpace(relation, + HEAP_DEFAULT_FILLFACTOR); + if (otherBuffer != InvalidBuffer) otherBlock = BufferGetBlockNumber(otherBuffer); else @@ -143,8 +147,14 @@ RelationGetBufferForTuple(Relation relation, Size len, * When use_fsm is false, we either put the tuple onto the existing target * page or extend the relation. */ - - targetBlock = relation->rd_targblock; + if (len + saveFreeSpace <= MaxTupleSize) + targetBlock = relation->rd_targblock; + else + { + /* can't fit, don't screw up FSM request tracking by trying */ + targetBlock = InvalidBlockNumber; + use_fsm = false; + } if (targetBlock == InvalidBlockNumber && use_fsm) { @@ -152,7 +162,8 @@ RelationGetBufferForTuple(Relation relation, Size len, * We have no cached target page, so ask the FSM for an initial * target. */ - targetBlock = GetPageWithFreeSpace(&relation->rd_node, len + freespace); + targetBlock = GetPageWithFreeSpace(&relation->rd_node, + len + saveFreeSpace); /* * If the FSM knows nothing of the rel, try the last page before we @@ -208,7 +219,7 @@ RelationGetBufferForTuple(Relation relation, Size len, */ pageHeader = (Page) BufferGetPage(buffer); pageFreeSpace = PageGetFreeSpace(pageHeader); - if (len + freespace <= pageFreeSpace) + if (len + saveFreeSpace <= pageFreeSpace) { /* use this page as future insert target, too */ relation->rd_targblock = targetBlock; @@ -241,7 +252,7 @@ RelationGetBufferForTuple(Relation relation, Size len, targetBlock = RecordAndGetPageWithFreeSpace(&relation->rd_node, targetBlock, pageFreeSpace, - len + freespace); + len + saveFreeSpace); } /* |