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.c103
1 files changed, 32 insertions, 71 deletions
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index 3fc2a69df1a..9181a7984d7 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Id: hio.c,v 1.31 2000/04/12 17:14:45 momjian Exp $
+ * $Id: hio.c,v 1.32 2000/07/03 02:54:15 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,17 +19,11 @@
#include "access/hio.h"
/*
- * amputunique - place tuple at tid
- * Currently on errors, calls elog. Perhaps should return -1?
- * Possible errors include the addition of a tuple to the page
- * between the time the linep is chosen and the page is L_UP'd.
+ * RelationPutHeapTuple - place tuple at specified page
*
- * This should be coordinated with the B-tree code.
- * Probably needs to have an amdelunique to allow for
- * internal index records to be deleted and reordered as needed.
- * For the heap AM, this should never be needed.
+ * !!! ELOG(ERROR) IS DISALLOWED HERE !!!
*
- * Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
+ * Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
*
*/
void
@@ -57,62 +51,41 @@ RelationPutHeapTuple(Relation relation,
offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
tuple->t_len, InvalidOffsetNumber, LP_USED);
+ if (offnum == InvalidOffsetNumber)
+ elog(STOP, "RelationPutHeapTuple: failed to add tuple");
+
itemId = PageGetItemId((Page) pageHeader, offnum);
item = PageGetItem((Page) pageHeader, itemId);
ItemPointerSet(&((HeapTupleHeader) item)->t_ctid,
BufferGetBlockNumber(buffer), offnum);
- /*
- * Let the caller do this!
- *
- * WriteBuffer(buffer);
- */
-
/* return an accurate tuple */
ItemPointerSet(&tuple->t_self, BufferGetBlockNumber(buffer), offnum);
}
/*
- * This routine is another in the series of attempts to reduce the number
- * of I/O's and system calls executed in the various benchmarks. In
- * particular, this routine is used to append data to the end of a relation
- * file without excessive lseeks. This code should do no more than 2 semops
- * in the ideal case.
+ * RelationGetBufferForTuple
*
- * Eventually, we should cache the number of blocks in a relation somewhere.
- * Until that time, this code will have to do an lseek to determine the number
- * of blocks in a relation.
+ * Returns (locked) buffer to add tuple with given len.
+ * If Ubuf is valid then no attempt to lock it should be made -
+ * this is for heap_update...
*
- * This code should ideally do at most 4 semops, 1 lseek, and possibly 1 write
- * to do an append; it's possible to eliminate 2 of the semops if we do direct
- * buffer stuff (!); the lseek and the write can go if we get
- * RelationGetNumberOfBlocks to be useful.
+ * ELOG(ERROR) is allowed here, so this routine *must* be called
+ * before any (unlogged) changes are made in buffer pool.
*
- * NOTE: This code presumes that we have a write lock on the relation.
- * Not now - we use extend locking...
- *
- * Also note that this routine probably shouldn't have to exist, and does
- * screw up the call graph rather badly, but we are wasting so much time and
- * system resources being massively general that we are losing badly in our
- * performance benchmarks.
*/
-void
-RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
+Buffer
+RelationGetBufferForTuple(Relation relation, Size len, Buffer Ubuf)
{
Buffer buffer;
Page pageHeader;
BlockNumber lastblock;
- OffsetNumber offnum;
- Size len;
- ItemId itemId;
- Item item;
- len = MAXALIGN(tuple->t_len); /* be conservative */
+ len = MAXALIGN(len); /* be conservative */
/*
- * If we're gonna fail for oversize tuple, do it right away... this
- * code should go away eventually.
+ * If we're gonna fail for oversize tuple, do it right away
*/
if (len > MaxTupleSize)
elog(ERROR, "Tuple is too big: size %u, max size %ld",
@@ -152,7 +125,8 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
else
buffer = ReadBuffer(relation, lastblock - 1);
- LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+ if (buffer != Ubuf)
+ LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
pageHeader = (Page) BufferGetPage(buffer);
/*
@@ -160,7 +134,8 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
*/
if (len > PageGetFreeSpace(pageHeader))
{
- LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+ if (buffer != Ubuf)
+ LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
pageHeader = (Page) BufferGetPage(buffer);
@@ -168,36 +143,22 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
if (len > PageGetFreeSpace(pageHeader))
{
-
- /*
- * BUG: by elog'ing here, we leave the new buffer locked and
- * not marked dirty, which may result in an invalid page
- * header being left on disk. But we should not get here
- * given the test at the top of the routine, and the whole
- * deal should go away when we implement tuple splitting
- * anyway...
- */
- elog(ERROR, "Tuple is too big: size %u", len);
+ /* We should not get here given the test at the top */
+ elog(STOP, "Tuple is too big: size %u", len);
}
}
+ /*
+ * Caller should check space in Ubuf but...
+ */
+ else if (buffer == Ubuf)
+ {
+ ReleaseBuffer(buffer);
+ buffer = Ubuf;
+ }
if (!relation->rd_myxactonly)
UnlockPage(relation, 0, ExclusiveLock);
- offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
- tuple->t_len, InvalidOffsetNumber, LP_USED);
-
- itemId = PageGetItemId((Page) pageHeader, offnum);
- item = PageGetItem((Page) pageHeader, itemId);
-
- lastblock = BufferGetBlockNumber(buffer);
-
- ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, lastblock, offnum);
-
- /* return an accurate tuple self-pointer */
- ItemPointerSet(&tuple->t_self, lastblock, offnum);
-
- LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- WriteBuffer(buffer);
+ return(buffer);
}