aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/heap/hio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/heap/hio.c')
-rw-r--r--src/backend/access/heap/hio.c35
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);
}
/*