Skip to content

Commit 1b67fe1

Browse files
committed
heap' logging
1 parent 80c6469 commit 1b67fe1

File tree

7 files changed

+130
-130
lines changed

7 files changed

+130
-130
lines changed

src/backend/access/heap/heapam.c

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.74 2000/07/02 22:00:27 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.75 2000/07/03 02:54:15 vadim Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1271,10 +1271,9 @@ heap_get_latest_tid(Relation relation,
12711271
Oid
12721272
heap_insert(Relation relation, HeapTuple tup)
12731273
{
1274-
/* ----------------
1275-
* increment access statistics
1276-
* ----------------
1277-
*/
1274+
Buffer buffer;
1275+
1276+
/* increment access statistics */
12781277
tup->tableOid = relation->rd_id;
12791278
IncrHeapAccessStat(local_insert);
12801279
IncrHeapAccessStat(global_insert);
@@ -1300,15 +1299,20 @@ heap_insert(Relation relation, HeapTuple tup)
13001299
tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
13011300
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
13021301

1303-
RelationPutHeapTupleAtEnd(relation, tup);
1302+
/* Find buffer for this tuple */
1303+
buffer = RelationGetBufferForTuple(relation, tup->t_len, InvalidBuffer);
1304+
1305+
/* NO ELOG(ERROR) from here till changes are logged */
1306+
RelationPutHeapTuple(relation, buffer, tup);
13041307

13051308
#ifdef XLOG
13061309
/* XLOG stuff */
13071310
{
13081311
xl_heap_insert xlrec;
13091312
xlrec.itid.dbId = relation->rd_lockInfo.lockRelId.dbId;
13101313
xlrec.itid.relId = relation->rd_lockInfo.lockRelId.relId;
1311-
XXX xlrec.itid.tid = tp.t_self;
1314+
xlrec.itid.cid = GetCurrentCommandId();
1315+
xlrec.itid.tid = tup->t_self;
13121316
xlrec.t_natts = tup->t_data->t_natts;
13131317
xlrec.t_oid = tup->t_data->t_oid;
13141318
xlrec.t_hoff = tup->t_data->t_hoff;
@@ -1319,10 +1323,14 @@ XXX xlrec.itid.tid = tp.t_self;
13191323
(char*) tup->t_data + offsetof(HeapTupleHeaderData, tbits),
13201324
tup->t_len - offsetof(HeapTupleHeaderData, tbits));
13211325

1322-
dp->pd_lsn = recptr;
1326+
((PageHeader) BufferGetPage(buffer))->pd_lsn = recptr;
1327+
((PageHeader) BufferGetPage(buffer))->pd_sui = ThisStartUpID;
13231328
}
13241329
#endif
13251330

1331+
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1332+
WriteBuffer(buffer);
1333+
13261334
if (IsSystemRelationName(RelationGetRelationName(relation)))
13271335
RelationMark4RollbackHeapTuple(relation, tup);
13281336

@@ -1417,11 +1425,13 @@ heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
14171425
xl_heap_delete xlrec;
14181426
xlrec.dtid.dbId = relation->rd_lockInfo.lockRelId.dbId;
14191427
xlrec.dtid.relId = relation->rd_lockInfo.lockRelId.relId;
1428+
xlrec.dtid.cid = GetCurrentCommandId();
14201429
xlrec.dtid.tid = tp.t_self;
14211430
XLogRecPtr recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE,
14221431
(char*) xlrec, sizeof(xlrec), NULL, 0);
14231432

14241433
dp->pd_lsn = recptr;
1434+
dp->pd_sui = ThisStartUpID;
14251435
}
14261436
#endif
14271437

@@ -1451,7 +1461,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
14511461
ItemId lp;
14521462
HeapTupleData oldtup;
14531463
PageHeader dp;
1454-
Buffer buffer;
1464+
Buffer buffer, newbuf;
14551465
int result;
14561466

14571467
newtup->tableOid = relation->rd_id;
@@ -1531,43 +1541,65 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
15311541
newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
15321542
newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
15331543

1534-
/* logically delete old item */
1544+
/* Find buffer for new tuple */
1545+
1546+
if ((unsigned) MAXALIGN(newtup->t_len) <= PageGetFreeSpace((Page) dp))
1547+
newbuf = buffer;
1548+
else
1549+
newbuf = RelationGetBufferForTuple(relation, newtup->t_len, buffer);
1550+
1551+
/* NO ELOG(ERROR) from here till changes are logged */
1552+
1553+
/* insert new tuple */
1554+
RelationPutHeapTuple(relation, newbuf, newtup);
1555+
1556+
/* logically delete old tuple */
15351557
TransactionIdStore(GetCurrentTransactionId(), &(oldtup.t_data->t_xmax));
15361558
oldtup.t_data->t_cmax = GetCurrentCommandId();
15371559
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
15381560
HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
15391561

1540-
/* insert new item */
1541-
if ((unsigned) MAXALIGN(newtup->t_len) <= PageGetFreeSpace((Page) dp))
1542-
RelationPutHeapTuple(relation, buffer, newtup);
1543-
else
1562+
/* record address of new tuple in t_ctid of old one */
1563+
oldtup.t_data->t_ctid = newtup->t_self;
1564+
1565+
#ifdef XLOG
1566+
/* XLOG stuff */
15441567
{
1568+
xl_heap_update xlrec;
1569+
xlrec.dtid.dbId = relation->rd_lockInfo.lockRelId.dbId;
1570+
xlrec.dtid.relId = relation->rd_lockInfo.lockRelId.relId;
1571+
xlrec.dtid.cid = GetCurrentCommandId();
1572+
xlrec.itid.tid = newtup->t_self;
1573+
xlrec.t_natts = newtup->t_data->t_natts;
1574+
xlrec.t_hoff = newtup->t_data->t_hoff;
1575+
xlrec.mask = newtup->t_data->t_infomask;
1576+
1577+
XLogRecPtr recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_UPDATE,
1578+
(char*) xlrec, sizeof(xlrec),
1579+
(char*) newtup->t_data + offsetof(HeapTupleHeaderData, tbits),
1580+
newtup->t_len - offsetof(HeapTupleHeaderData, tbits));
15451581

1546-
/*
1547-
* New item won't fit on same page as old item, have to look for a
1548-
* new place to put it. Note that we have to unlock current buffer
1549-
* context - not good but RelationPutHeapTupleAtEnd uses extend
1550-
* lock.
1551-
*/
1552-
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1553-
RelationPutHeapTupleAtEnd(relation, newtup);
1554-
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
1582+
if (newbuf != buffer)
1583+
{
1584+
((PageHeader) BufferGetPage(newbuf))->pd_lsn = recptr;
1585+
((PageHeader) BufferGetPage(newbuf))->pd_sui = ThisStartUpID;
1586+
}
1587+
((PageHeader) BufferGetPage(buffer))->pd_lsn = recptr;
1588+
((PageHeader) BufferGetPage(buffer))->pd_sui = ThisStartUpID;
15551589
}
1556-
/* mark for rollback caches */
1557-
RelationMark4RollbackHeapTuple(relation, newtup);
1558-
1559-
/*
1560-
* New item in place, now record address of new tuple in t_ctid of old
1561-
* one.
1562-
*/
1563-
oldtup.t_data->t_ctid = newtup->t_self;
1590+
#endif
15641591

1592+
if (newbuf != buffer)
1593+
{
1594+
LockBuffer(newbuf, BUFFER_LOCK_UNLOCK);
1595+
WriteBuffer(newbuf);
1596+
}
15651597
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
1598+
WriteBuffer(buffer);
15661599

15671600
/* invalidate caches */
15681601
RelationInvalidateHeapTuple(relation, &oldtup);
1569-
1570-
WriteBuffer(buffer);
1602+
RelationMark4RollbackHeapTuple(relation, newtup);
15711603

15721604
return HeapTupleMayBeUpdated;
15731605
}
@@ -1648,6 +1680,14 @@ heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer)
16481680
return result;
16491681
}
16501682

1683+
#ifdef XLOG
1684+
/*
1685+
* XLOG stuff: no logging is required as long as we have no
1686+
* savepoints. For savepoints private log could be used...
1687+
*/
1688+
((PageHeader) BufferGetPage(*buffer))->pd_sui = ThisStartUpID;
1689+
#endif
1690+
16511691
/* store transaction information of xact marking the tuple */
16521692
TransactionIdStore(GetCurrentTransactionId(), &(tuple->t_data->t_xmax));
16531693
tuple->t_data->t_cmax = GetCurrentCommandId();

src/backend/access/heap/hio.c

Lines changed: 32 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Id: hio.c,v 1.31 2000/04/12 17:14:45 momjian Exp $
11+
* $Id: hio.c,v 1.32 2000/07/03 02:54:15 vadim Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -19,17 +19,11 @@
1919
#include "access/hio.h"
2020

2121
/*
22-
* amputunique - place tuple at tid
23-
* Currently on errors, calls elog. Perhaps should return -1?
24-
* Possible errors include the addition of a tuple to the page
25-
* between the time the linep is chosen and the page is L_UP'd.
22+
* RelationPutHeapTuple - place tuple at specified page
2623
*
27-
* This should be coordinated with the B-tree code.
28-
* Probably needs to have an amdelunique to allow for
29-
* internal index records to be deleted and reordered as needed.
30-
* For the heap AM, this should never be needed.
24+
* !!! ELOG(ERROR) IS DISALLOWED HERE !!!
3125
*
32-
* Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
26+
* Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
3327
*
3428
*/
3529
void
@@ -57,62 +51,41 @@ RelationPutHeapTuple(Relation relation,
5751
offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
5852
tuple->t_len, InvalidOffsetNumber, LP_USED);
5953

54+
if (offnum == InvalidOffsetNumber)
55+
elog(STOP, "RelationPutHeapTuple: failed to add tuple");
56+
6057
itemId = PageGetItemId((Page) pageHeader, offnum);
6158
item = PageGetItem((Page) pageHeader, itemId);
6259

6360
ItemPointerSet(&((HeapTupleHeader) item)->t_ctid,
6461
BufferGetBlockNumber(buffer), offnum);
6562

66-
/*
67-
* Let the caller do this!
68-
*
69-
* WriteBuffer(buffer);
70-
*/
71-
7263
/* return an accurate tuple */
7364
ItemPointerSet(&tuple->t_self, BufferGetBlockNumber(buffer), offnum);
7465
}
7566

7667
/*
77-
* This routine is another in the series of attempts to reduce the number
78-
* of I/O's and system calls executed in the various benchmarks. In
79-
* particular, this routine is used to append data to the end of a relation
80-
* file without excessive lseeks. This code should do no more than 2 semops
81-
* in the ideal case.
68+
* RelationGetBufferForTuple
8269
*
83-
* Eventually, we should cache the number of blocks in a relation somewhere.
84-
* Until that time, this code will have to do an lseek to determine the number
85-
* of blocks in a relation.
70+
* Returns (locked) buffer to add tuple with given len.
71+
* If Ubuf is valid then no attempt to lock it should be made -
72+
* this is for heap_update...
8673
*
87-
* This code should ideally do at most 4 semops, 1 lseek, and possibly 1 write
88-
* to do an append; it's possible to eliminate 2 of the semops if we do direct
89-
* buffer stuff (!); the lseek and the write can go if we get
90-
* RelationGetNumberOfBlocks to be useful.
74+
* ELOG(ERROR) is allowed here, so this routine *must* be called
75+
* before any (unlogged) changes are made in buffer pool.
9176
*
92-
* NOTE: This code presumes that we have a write lock on the relation.
93-
* Not now - we use extend locking...
94-
*
95-
* Also note that this routine probably shouldn't have to exist, and does
96-
* screw up the call graph rather badly, but we are wasting so much time and
97-
* system resources being massively general that we are losing badly in our
98-
* performance benchmarks.
9977
*/
100-
void
101-
RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
78+
Buffer
79+
RelationGetBufferForTuple(Relation relation, Size len, Buffer Ubuf)
10280
{
10381
Buffer buffer;
10482
Page pageHeader;
10583
BlockNumber lastblock;
106-
OffsetNumber offnum;
107-
Size len;
108-
ItemId itemId;
109-
Item item;
11084

111-
len = MAXALIGN(tuple->t_len); /* be conservative */
85+
len = MAXALIGN(len); /* be conservative */
11286

11387
/*
114-
* If we're gonna fail for oversize tuple, do it right away... this
115-
* code should go away eventually.
88+
* If we're gonna fail for oversize tuple, do it right away
11689
*/
11790
if (len > MaxTupleSize)
11891
elog(ERROR, "Tuple is too big: size %u, max size %ld",
@@ -152,52 +125,40 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
152125
else
153126
buffer = ReadBuffer(relation, lastblock - 1);
154127

155-
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
128+
if (buffer != Ubuf)
129+
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
156130
pageHeader = (Page) BufferGetPage(buffer);
157131

158132
/*
159133
* Is there room on the last existing page?
160134
*/
161135
if (len > PageGetFreeSpace(pageHeader))
162136
{
163-
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
137+
if (buffer != Ubuf)
138+
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
164139
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
165140
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
166141
pageHeader = (Page) BufferGetPage(buffer);
167142
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
168143

169144
if (len > PageGetFreeSpace(pageHeader))
170145
{
171-
172-
/*
173-
* BUG: by elog'ing here, we leave the new buffer locked and
174-
* not marked dirty, which may result in an invalid page
175-
* header being left on disk. But we should not get here
176-
* given the test at the top of the routine, and the whole
177-
* deal should go away when we implement tuple splitting
178-
* anyway...
179-
*/
180-
elog(ERROR, "Tuple is too big: size %u", len);
146+
/* We should not get here given the test at the top */
147+
elog(STOP, "Tuple is too big: size %u", len);
181148
}
182149
}
150+
/*
151+
* Caller should check space in Ubuf but...
152+
*/
153+
else if (buffer == Ubuf)
154+
{
155+
ReleaseBuffer(buffer);
156+
buffer = Ubuf;
157+
}
183158

184159
if (!relation->rd_myxactonly)
185160
UnlockPage(relation, 0, ExclusiveLock);
186161

187-
offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
188-
tuple->t_len, InvalidOffsetNumber, LP_USED);
189-
190-
itemId = PageGetItemId((Page) pageHeader, offnum);
191-
item = PageGetItem((Page) pageHeader, itemId);
192-
193-
lastblock = BufferGetBlockNumber(buffer);
194-
195-
ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, lastblock, offnum);
196-
197-
/* return an accurate tuple self-pointer */
198-
ItemPointerSet(&tuple->t_self, lastblock, offnum);
199-
200-
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
201-
WriteBuffer(buffer);
162+
return(buffer);
202163

203164
}

0 commit comments

Comments
 (0)