]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Repair possible failure to update hint bits back to disk, per
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 15 Oct 2004 22:40:29 +0000 (22:40 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 15 Oct 2004 22:40:29 +0000 (22:40 +0000)
http://archives.postgresql.org/pgsql-hackers/2004-10/msg00464.php.
This fix is intended to be permanent: it moves the responsibility for
calling SetBufferCommitInfoNeedsSave() into the tqual.c routines,
eliminating the requirement for callers to test whether t_infomask changed.
Also, tighten validity checking on buffer IDs in bufmgr.c --- several
routines were paranoid about out-of-range shared buffer numbers but not
about out-of-range local ones, which seems a tad pointless.

13 files changed:
contrib/pgstattuple/pgstattuple.c
src/backend/access/heap/heapam.c
src/backend/access/index/indexam.c
src/backend/access/nbtree/nbtinsert.c
src/backend/catalog/index.c
src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/backend/storage/buffer/bufmgr.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/time/tqual.c
src/include/access/valid.h
src/include/storage/bufmgr.h
src/include/utils/tqual.h

index bfe37eb9ed6975b4ae8eb208da84561741958cfc..e2fab7863eb4ef8ed05d08695380552395cec858 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.16 2004/08/29 05:06:37 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.17 2004/10/15 22:39:38 tgl Exp $
  *
  * Copyright (c) 2001,2002     Tatsuo Ishii
  *
@@ -134,7 +134,10 @@ pgstattuple_real(Relation rel)
        /* scan the relation */
        while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
        {
-               if (HeapTupleSatisfiesNow(tuple->t_data))
+               /* must hold a buffer lock to call HeapTupleSatisfiesNow */
+               LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
+
+               if (HeapTupleSatisfiesNow(tuple->t_data, scan->rs_cbuf))
                {
                        tuple_len += tuple->t_len;
                        tuple_count++;
@@ -145,6 +148,8 @@ pgstattuple_real(Relation rel)
                        dead_tuple_count++;
                }
 
+               LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
+
                /*
                 * To avoid physically reading the table twice, try to do the
                 * free-space scan in parallel with the heap scan.      However,
@@ -156,7 +161,9 @@ pgstattuple_real(Relation rel)
                while (block <= tupblock)
                {
                        buffer = ReadBuffer(rel, block);
+                       LockBuffer(buffer, BUFFER_LOCK_SHARE);
                        free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
+                       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
                        ReleaseBuffer(buffer);
                        block++;
                }
index b9a6072c799835424d4e8a45ad11e92060c874f7..af5325ea632a82e198ba5c8253b88d089e72bf1f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.178 2004/10/12 21:54:34 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.179 2004/10/15 22:39:42 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1314,7 +1314,7 @@ heap_delete(Relation relation, ItemPointer tid,
        tp.t_tableOid = relation->rd_id;
 
 l1:
-       result = HeapTupleSatisfiesUpdate(tp.t_data, cid);
+       result = HeapTupleSatisfiesUpdate(tp.t_data, cid, buffer);
 
        if (result == HeapTupleInvisible)
        {
@@ -1331,7 +1331,7 @@ l1:
                XactLockTableWait(xwait);
 
                LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
-               if (TransactionIdDidAbort(xwait))
+               if (!TransactionIdDidCommit(xwait))
                        goto l1;
 
                /*
@@ -1356,7 +1356,7 @@ l1:
        if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
        {
                /* Perform additional check for serializable RI updates */
-               if (!HeapTupleSatisfiesSnapshot(tp.t_data, crosscheck))
+               if (!HeapTupleSatisfiesSnapshot(tp.t_data, crosscheck, buffer))
                        result = HeapTupleUpdated;
        }
 
@@ -1543,7 +1543,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
         */
 
 l2:
-       result = HeapTupleSatisfiesUpdate(oldtup.t_data, cid);
+       result = HeapTupleSatisfiesUpdate(oldtup.t_data, cid, buffer);
 
        if (result == HeapTupleInvisible)
        {
@@ -1560,7 +1560,7 @@ l2:
                XactLockTableWait(xwait);
 
                LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
-               if (TransactionIdDidAbort(xwait))
+               if (!TransactionIdDidCommit(xwait))
                        goto l2;
 
                /*
@@ -1585,7 +1585,7 @@ l2:
        if (crosscheck != InvalidSnapshot && result == HeapTupleMayBeUpdated)
        {
                /* Perform additional check for serializable RI updates */
-               if (!HeapTupleSatisfiesSnapshot(oldtup.t_data, crosscheck))
+               if (!HeapTupleSatisfiesSnapshot(oldtup.t_data, crosscheck, buffer))
                        result = HeapTupleUpdated;
        }
 
@@ -1871,7 +1871,7 @@ heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer,
        tuple->t_len = ItemIdGetLength(lp);
 
 l3:
-       result = HeapTupleSatisfiesUpdate(tuple->t_data, cid);
+       result = HeapTupleSatisfiesUpdate(tuple->t_data, cid, *buffer);
 
        if (result == HeapTupleInvisible)
        {
@@ -1888,7 +1888,7 @@ l3:
                XactLockTableWait(xwait);
 
                LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
-               if (TransactionIdDidAbort(xwait))
+               if (!TransactionIdDidCommit(xwait))
                        goto l3;
 
                /*
index 7c698fb48a25edaf1af6443b9035fccfd84b9000..214f646276bf30a50dc1d3c3547ed2cfd011afaa 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.75 2004/09/30 23:21:14 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.76 2004/10/15 22:39:46 tgl Exp $
  *
  * INTERFACE ROUTINES
  *             index_open              - open an index relation by relation OID
@@ -497,7 +497,6 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
        for (;;)
        {
                bool            found;
-               uint16          sv_infomask;
 
                pgstat_count_index_scan(&scan->xs_pgstat_info);
 
@@ -541,19 +540,14 @@ index_getnext(IndexScanDesc scan, ScanDirection direction)
                 * index AM to not return it on future indexscans.
                 *
                 * We told heap_release_fetch to keep a pin on the buffer, so we can
-                * re-access the tuple here.  But we must re-lock the buffer
-                * first. Also, it's just barely possible for an update of hint
-                * bits to occur here.
+                * re-access the tuple here.  But we must re-lock the buffer first.
                 */
                LockBuffer(scan->xs_cbuf, BUFFER_LOCK_SHARE);
-               sv_infomask = heapTuple->t_data->t_infomask;
 
-               if (HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin) ==
-                       HEAPTUPLE_DEAD)
+               if (HeapTupleSatisfiesVacuum(heapTuple->t_data, RecentGlobalXmin,
+                                                                        scan->xs_cbuf) == HEAPTUPLE_DEAD)
                        scan->kill_prior_tuple = true;
 
-               if (sv_infomask != heapTuple->t_data->t_infomask)
-                       SetBufferCommitInfoNeedsSave(scan->xs_cbuf);
                LockBuffer(scan->xs_cbuf, BUFFER_LOCK_UNLOCK);
        }
 
index 815e207fb2f504d428196cc5203921ec9e87c16f..32615a62c27a3250805b7fb677f51c62ed3ddef1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.116 2004/08/29 05:06:40 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.117 2004/10/15 22:39:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -261,19 +261,13 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
                                         * marked killed.  This logic should match
                                         * index_getnext and btgettuple.
                                         */
-                                       uint16          sv_infomask;
-
                                        LockBuffer(hbuffer, BUFFER_LOCK_SHARE);
-                                       sv_infomask = htup.t_data->t_infomask;
-                                       if (HeapTupleSatisfiesVacuum(htup.t_data,
-                                                                                                RecentGlobalXmin) ==
-                                               HEAPTUPLE_DEAD)
+                                       if (HeapTupleSatisfiesVacuum(htup.t_data, RecentGlobalXmin,
+                                                                                                hbuffer) == HEAPTUPLE_DEAD)
                                        {
                                                curitemid->lp_flags |= LP_DELETE;
                                                SetBufferCommitInfoNeedsSave(buf);
                                        }
-                                       if (sv_infomask != htup.t_data->t_infomask)
-                                               SetBufferCommitInfoNeedsSave(hbuffer);
                                        LockBuffer(hbuffer, BUFFER_LOCK_UNLOCK);
                                        ReleaseBuffer(hbuffer);
                                }
index 8fb2f8f4f222c44185ae6ea9c2b2702f3bcbb7c5..19fc60b6c8898bfcd7f76ab54841f8c8646b3b93 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.240 2004/10/01 17:11:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.241 2004/10/15 22:39:53 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1472,18 +1472,16 @@ IndexBuildHeapScan(Relation heapRelation,
                {
                        /* do our own time qual check */
                        bool            indexIt;
-                       uint16          sv_infomask;
 
                        /*
-                        * HeapTupleSatisfiesVacuum may update tuple's hint status
-                        * bits. We could possibly get away with not locking the
-                        * buffer here, since caller should hold ShareLock on the
-                        * relation, but let's be conservative about it.
+                        * We could possibly get away with not locking the buffer here,
+                        * since caller should hold ShareLock on the relation, but let's
+                        * be conservative about it.
                         */
                        LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
-                       sv_infomask = heapTuple->t_data->t_infomask;
 
-                       switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin))
+                       switch (HeapTupleSatisfiesVacuum(heapTuple->t_data, OldestXmin,
+                                                                                        scan->rs_cbuf))
                        {
                                case HEAPTUPLE_DEAD:
                                        indexIt = false;
@@ -1544,10 +1542,6 @@ IndexBuildHeapScan(Relation heapRelation,
                                        break;
                        }
 
-                       /* check for hint-bit update by HeapTupleSatisfiesVacuum */
-                       if (sv_infomask != heapTuple->t_data->t_infomask)
-                               SetBufferCommitInfoNeedsSave(scan->rs_cbuf);
-
                        LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
 
                        if (!indexIt)
index 232ec9a89e69c11fdc17153234d840e2e15950a8..3d0c6e0e996d65bf04cf069cd7c1b013d02549f9 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.294 2004/10/07 14:19:58 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.295 2004/10/15 22:39:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1190,6 +1190,12 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                buf = ReadBuffer(onerel, blkno);
                page = BufferGetPage(buf);
 
+               /*
+                * We don't bother to do LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE)
+                * because we assume that holding exclusive lock on the relation
+                * will keep other backends from looking at the page.
+                */
+
                vacpage->blkno = blkno;
                vacpage->offsets_used = 0;
                vacpage->offsets_free = 0;
@@ -1235,7 +1241,6 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                         offnum <= maxoff;
                         offnum = OffsetNumberNext(offnum))
                {
-                       uint16          sv_infomask;
                        ItemId          itemid = PageGetItemId(page, offnum);
                        bool            tupgone = false;
 
@@ -1255,9 +1260,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                        tuple.t_len = ItemIdGetLength(itemid);
                        ItemPointerSet(&(tuple.t_self), blkno, offnum);
 
-                       sv_infomask = tuple.t_data->t_infomask;
-
-                       switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin))
+                       switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
                        {
                                case HEAPTUPLE_DEAD:
                                        tupgone = true;         /* we can delete the tuple */
@@ -1348,10 +1351,6 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
                                        break;
                        }
 
-                       /* check for hint-bit update by HeapTupleSatisfiesVacuum */
-                       if (sv_infomask != tuple.t_data->t_infomask)
-                               pgchanged = true;
-
                        if (tupgone)
                        {
                                ItemId          lpp;
index ebdb27f336f299205aa64cc397a4bc0049979b31..62ba05f9698dc15c437238df675e6553ef6d8852 100644 (file)
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.46 2004/09/30 23:21:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.47 2004/10/15 22:39:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -291,7 +291,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                         offnum = OffsetNumberNext(offnum))
                {
                        ItemId          itemid;
-                       uint16          sv_infomask;
 
                        itemid = PageGetItemId(page, offnum);
 
@@ -307,9 +306,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                        ItemPointerSet(&(tuple.t_self), blkno, offnum);
 
                        tupgone = false;
-                       sv_infomask = tuple.t_data->t_infomask;
 
-                       switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin))
+                       switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
                        {
                                case HEAPTUPLE_DEAD:
                                        tupgone = true;         /* we can delete the tuple */
@@ -364,10 +362,6 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                                        break;
                        }
 
-                       /* check for hint-bit update by HeapTupleSatisfiesVacuum */
-                       if (sv_infomask != tuple.t_data->t_infomask)
-                               pgchanged = true;
-
                        if (tupgone)
                        {
                                lazy_record_dead_tuple(vacrelstats, &(tuple.t_self));
@@ -399,9 +393,9 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
                LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
                if (pgchanged)
-                       SetBufferCommitInfoNeedsSave(buf);
-
-               ReleaseBuffer(buf);
+                       WriteBuffer(buf);
+               else
+                       ReleaseBuffer(buf);
        }
 
        /* save stats for use later */
@@ -790,8 +784,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
                Page            page;
                OffsetNumber offnum,
                                        maxoff;
-               bool            pgchanged,
-                                       tupgone,
+               bool            tupgone,
                                        hastup;
 
                vacuum_delay_point();
@@ -813,7 +806,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
                        continue;
                }
 
-               pgchanged = false;
                hastup = false;
                maxoff = PageGetMaxOffsetNumber(page);
                for (offnum = FirstOffsetNumber;
@@ -821,7 +813,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
                         offnum = OffsetNumberNext(offnum))
                {
                        ItemId          itemid;
-                       uint16          sv_infomask;
 
                        itemid = PageGetItemId(page, offnum);
 
@@ -834,9 +825,8 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
                        ItemPointerSet(&(tuple.t_self), blkno, offnum);
 
                        tupgone = false;
-                       sv_infomask = tuple.t_data->t_infomask;
 
-                       switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin))
+                       switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
                        {
                                case HEAPTUPLE_DEAD:
                                        tupgone = true;         /* we can delete the tuple */
@@ -862,10 +852,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
                                        break;
                        }
 
-                       /* check for hint-bit update by HeapTupleSatisfiesVacuum */
-                       if (sv_infomask != tuple.t_data->t_infomask)
-                               pgchanged = true;
-
                        if (!tupgone)
                        {
                                hastup = true;
@@ -875,10 +861,7 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
 
                LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
-               if (pgchanged)
-                       WriteBuffer(buf);
-               else
-                       ReleaseBuffer(buf);
+               ReleaseBuffer(buf);
 
                /* Done scanning if we found a tuple here */
                if (hastup)
index b98193ad38c74ddd5adf7de0f89a4a35d38e3215..a0f2bf9c117f981aa01fd779bb57a8299502d41d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.177 2004/09/06 17:31:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.178 2004/10/15 22:39:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -477,15 +477,15 @@ write_buffer(Buffer buffer, bool release)
 {
        BufferDesc *bufHdr;
 
+       if (!BufferIsValid(buffer))
+               elog(ERROR, "bad buffer id: %d", buffer);
+
        if (BufferIsLocal(buffer))
        {
                WriteLocalBuffer(buffer, release);
                return;
        }
 
-       if (BAD_BUFFER_ID(buffer))
-               elog(ERROR, "bad buffer id: %d", buffer);
-
        bufHdr = &BufferDescriptors[buffer - 1];
 
        Assert(PrivateRefCount[buffer - 1] > 0);
@@ -1465,6 +1465,9 @@ ReleaseBuffer(Buffer buffer)
 {
        BufferDesc *bufHdr;
 
+       if (!BufferIsValid(buffer))
+               elog(ERROR, "bad buffer id: %d", buffer);
+
        ResourceOwnerForgetBuffer(CurrentResourceOwner, buffer);
 
        if (BufferIsLocal(buffer))
@@ -1474,9 +1477,6 @@ ReleaseBuffer(Buffer buffer)
                return;
        }
 
-       if (BAD_BUFFER_ID(buffer))
-               elog(ERROR, "bad buffer id: %d", buffer);
-
        bufHdr = &BufferDescriptors[buffer - 1];
 
        Assert(PrivateRefCount[buffer - 1] > 0);
@@ -1503,17 +1503,16 @@ ReleaseBuffer(Buffer buffer)
 void
 IncrBufferRefCount(Buffer buffer)
 {
+       Assert(BufferIsValid(buffer));
        ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
        ResourceOwnerRememberBuffer(CurrentResourceOwner, buffer);
        if (BufferIsLocal(buffer))
        {
-               Assert(buffer >= -NLocBuffer);
                Assert(LocalRefCount[-buffer - 1] > 0);
                LocalRefCount[-buffer - 1]++;
        }
        else
        {
-               Assert(!BAD_BUFFER_ID(buffer));
                Assert(PrivateRefCount[buffer - 1] > 0);
                PrivateRefCount[buffer - 1]++;
        }
@@ -1606,9 +1605,12 @@ ReleaseAndReadBuffer_Debug(char *file,
  *
  *     Mark a buffer dirty when we have updated tuple commit-status bits in it.
  *
- * This is similar to WriteNoReleaseBuffer, except that we have not made a
- * critical change that has to be flushed to disk before xact commit --- the
- * status-bit update could be redone by someone else just as easily.
+ * This is essentially the same as WriteNoReleaseBuffer.  We preserve the
+ * distinction as a way of documenting that the caller has not made a critical
+ * data change --- the status-bit update could be redone by someone else just
+ * as easily.  Therefore, no WAL log record need be generated, whereas calls
+ * to WriteNoReleaseBuffer really ought to be associated with a WAL-entry-
+ * creating action.
  *
  * This routine might get called many times on the same page, if we are making
  * the first scan after commit of an xact that added/deleted many tuples.
@@ -1623,15 +1625,15 @@ SetBufferCommitInfoNeedsSave(Buffer buffer)
 {
        BufferDesc *bufHdr;
 
+       if (!BufferIsValid(buffer))
+               elog(ERROR, "bad buffer id: %d", buffer);
+
        if (BufferIsLocal(buffer))
        {
                WriteLocalBuffer(buffer, false);
                return;
        }
 
-       if (BAD_BUFFER_ID(buffer))
-               elog(ERROR, "bad buffer id: %d", buffer);
-
        bufHdr = &BufferDescriptors[buffer - 1];
 
        if ((bufHdr->flags & (BM_DIRTY | BM_JUST_DIRTIED)) !=
@@ -1662,7 +1664,6 @@ UnlockBuffers(void)
                if (buflocks == 0)
                        continue;
 
-               Assert(BufferIsValid(i + 1));
                buf = &(BufferDescriptors[i]);
 
                HOLD_INTERRUPTS();              /* don't want to die() partway through... */
index 20ad56c31f1b18aa8e19c2c20f50ceee7a4f25ff..b195e243393fcf09cf5efc02f9b609d8b9c496ee 100644 (file)
@@ -17,7 +17,7 @@
  *
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.73 2004/09/13 20:07:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.74 2004/10/15 22:40:11 tgl Exp $
  *
  * ----------
  */
@@ -224,10 +224,15 @@ RI_FKey_check(PG_FUNCTION_ARGS)
         * We should not even consider checking the row if it is no longer
         * valid since it was either deleted (doesn't matter) or updated (in
         * which case it'll be checked with its final values).
+        *
+        * We do not know what buffer the new_row is in, but it doesn't matter
+        * since it's not possible for a hint-bit update to occur here (the
+        * new_row could only contain our own XID, and we haven't yet committed
+        * or aborted...)
         */
        if (new_row)
        {
-               if (!HeapTupleSatisfiesItself(new_row->t_data))
+               if (!HeapTupleSatisfiesItself(new_row->t_data, InvalidBuffer))
                {
                        heap_close(pk_rel, RowShareLock);
                        return PointerGetDatum(NULL);
index 3adab87ace4c6be7ac4ac5ecd5417b2a5d35a5cb..f36e2c13b6c1a2d1c83911a1ae517ee97a97b88b 100644 (file)
@@ -3,20 +3,20 @@
  * tqual.c
  *       POSTGRES "time" qualification code, ie, tuple visibility rules.
  *
- * NOTE: all the HeapTupleSatisfies routines will update the tuple's
- * "hint" status bits if we see that the inserting or deleting transaction
- * has now committed or aborted.  The caller is responsible for noticing any
- * change in t_infomask and scheduling a disk write if so.     Note that the
- * caller must hold at least a shared buffer context lock on the buffer
+ * The caller must hold at least a shared buffer context lock on the buffer
  * containing the tuple.  (VACUUM FULL assumes it's sufficient to have
  * exclusive lock on the containing relation, instead.)
  *
+ * NOTE: all the HeapTupleSatisfies routines will update the tuple's
+ * "hint" status bits if we see that the inserting or deleting transaction
+ * has now committed or aborted.
+ *
  *
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.79 2004/09/16 18:35:22 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.80 2004/10/15 22:40:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,7 +78,7 @@ TransactionId RecentGlobalXmin = InvalidTransactionId;
  *                      Xmax is not committed)))                       that has not been committed
  */
 bool
-HeapTupleSatisfiesItself(HeapTupleHeader tuple)
+HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
 {
        if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        {
@@ -96,9 +96,11 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
                                if (TransactionIdDidCommit(xvac))
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
                        }
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
@@ -110,10 +112,14 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
                                if (TransactionIdIsInProgress(xvac))
                                        return false;
                                if (TransactionIdDidCommit(xvac))
+                               {
                                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                                       SetBufferCommitInfoNeedsSave(buffer);
+                               }
                                else
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                        }
@@ -127,6 +133,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                        {
                                tuple->t_infomask |= HEAP_XMAX_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return true;
                        }
 
@@ -140,11 +147,17 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
                else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
                {
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
-                               tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
+                       {
+                               tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
+                       }
                        return false;
                }
                else
+               {
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
        }
 
        /* by here, the inserting transaction has committed */
@@ -169,7 +182,10 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
        if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
        {
                if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
-                       tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
+               {
+                       tuple->t_infomask |= HEAP_XMAX_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
                return true;
        }
 
@@ -178,10 +194,12 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
        if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
        {
                tuple->t_infomask |= HEAP_XMAX_INVALID;
+               SetBufferCommitInfoNeedsSave(buffer);
                return true;
        }
 
        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+       SetBufferCommitInfoNeedsSave(buffer);
        return false;
 }
 
@@ -228,7 +246,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
  *             that do catalog accesses.  this is unfortunate, but not critical.
  */
 bool
-HeapTupleSatisfiesNow(HeapTupleHeader tuple)
+HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
 {
        if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        {
@@ -246,9 +264,11 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
                                if (TransactionIdDidCommit(xvac))
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
                        }
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
@@ -260,10 +280,14 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
                                if (TransactionIdIsInProgress(xvac))
                                        return false;
                                if (TransactionIdDidCommit(xvac))
+                               {
                                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                                       SetBufferCommitInfoNeedsSave(buffer);
+                               }
                                else
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                        }
@@ -280,6 +304,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                        {
                                tuple->t_infomask |= HEAP_XMAX_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return true;
                        }
 
@@ -296,11 +321,17 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
                else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
                {
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
-                               tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
+                       {
+                               tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
+                       }
                        return false;
                }
                else
+               {
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
        }
 
        /* by here, the inserting transaction has committed */
@@ -328,7 +359,10 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
        if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
        {
                if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
-                       tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
+               {
+                       tuple->t_infomask |= HEAP_XMAX_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
                return true;
        }
 
@@ -337,10 +371,12 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
        if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
        {
                tuple->t_infomask |= HEAP_XMAX_INVALID;
+               SetBufferCommitInfoNeedsSave(buffer);
                return true;
        }
 
        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+       SetBufferCommitInfoNeedsSave(buffer);
        return false;
 }
 
@@ -359,7 +395,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
  * table.
  */
 bool
-HeapTupleSatisfiesToast(HeapTupleHeader tuple)
+HeapTupleSatisfiesToast(HeapTupleHeader tuple, Buffer buffer)
 {
        if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        {
@@ -377,9 +413,11 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
                                if (TransactionIdDidCommit(xvac))
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
                        }
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
@@ -391,10 +429,14 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
                                if (TransactionIdIsInProgress(xvac))
                                        return false;
                                if (TransactionIdDidCommit(xvac))
+                               {
                                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                                       SetBufferCommitInfoNeedsSave(buffer);
+                               }
                                else
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                        }
@@ -414,7 +456,8 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple)
  *     CurrentCommandId.
  */
 int
-HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
+HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
+                                                Buffer buffer)
 {
        if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        {
@@ -432,9 +475,11 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
                                if (TransactionIdDidCommit(xvac))
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return HeapTupleInvisible;
                                }
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
                        }
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
@@ -446,10 +491,14 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
                                if (TransactionIdIsInProgress(xvac))
                                        return HeapTupleInvisible;
                                if (TransactionIdDidCommit(xvac))
+                               {
                                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                                       SetBufferCommitInfoNeedsSave(buffer);
+                               }
                                else
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return HeapTupleInvisible;
                                }
                        }
@@ -467,6 +516,7 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                        {
                                tuple->t_infomask |= HEAP_XMAX_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return HeapTupleMayBeUpdated;
                        }
 
@@ -485,11 +535,17 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
                else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
                {
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
-                               tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
+                       {
+                               tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
+                       }
                        return HeapTupleInvisible;
                }
                else
+               {
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
        }
 
        /* by here, the inserting transaction has committed */
@@ -519,7 +575,8 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
        {
                if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                {
-                       tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
+                       tuple->t_infomask |= HEAP_XMAX_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
                        return HeapTupleMayBeUpdated;
                }
                /* running xact */
@@ -531,10 +588,12 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
        if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
        {
                tuple->t_infomask |= HEAP_XMAX_INVALID;
+               SetBufferCommitInfoNeedsSave(buffer);
                return HeapTupleMayBeUpdated;
        }
 
        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+       SetBufferCommitInfoNeedsSave(buffer);
        return HeapTupleUpdated;        /* updated by other */
 }
 
@@ -556,7 +615,7 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid)
  * t_ctid (forward link) is returned if it's being updated.
  */
 bool
-HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
+HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
 {
        SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
        ItemPointerSetInvalid(&(SnapshotDirty->tid));
@@ -577,9 +636,11 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
                                if (TransactionIdDidCommit(xvac))
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
                        }
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
@@ -591,10 +652,14 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
                                if (TransactionIdIsInProgress(xvac))
                                        return false;
                                if (TransactionIdDidCommit(xvac))
+                               {
                                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                                       SetBufferCommitInfoNeedsSave(buffer);
+                               }
                                else
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                        }
@@ -608,6 +673,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                        {
                                tuple->t_infomask |= HEAP_XMAX_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return true;
                        }
 
@@ -623,6 +689,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
                        {
                                tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return false;
                        }
                        SnapshotDirty->xmin = HeapTupleHeaderGetXmin(tuple);
@@ -630,7 +697,10 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
                        return true;            /* in insertion by other */
                }
                else
+               {
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
        }
 
        /* by here, the inserting transaction has committed */
@@ -657,7 +727,8 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
        {
                if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                {
-                       tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
+                       tuple->t_infomask |= HEAP_XMAX_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
                        return true;
                }
                /* running xact */
@@ -670,10 +741,12 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
        if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
        {
                tuple->t_infomask |= HEAP_XMAX_INVALID;
+               SetBufferCommitInfoNeedsSave(buffer);
                return true;
        }
 
        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+       SetBufferCommitInfoNeedsSave(buffer);
        SnapshotDirty->tid = tuple->t_ctid;
        return false;                           /* updated by other */
 }
@@ -700,7 +773,8 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
  * can't see it.)
  */
 bool
-HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
+HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
+                                                  Buffer buffer)
 {
        if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
        {
@@ -718,9 +792,11 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
                                if (TransactionIdDidCommit(xvac))
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
                        }
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
@@ -732,10 +808,14 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
                                if (TransactionIdIsInProgress(xvac))
                                        return false;
                                if (TransactionIdDidCommit(xvac))
+                               {
                                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                                       SetBufferCommitInfoNeedsSave(buffer);
+                               }
                                else
                                {
                                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                                       SetBufferCommitInfoNeedsSave(buffer);
                                        return false;
                                }
                        }
@@ -753,6 +833,7 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
                        {
                                tuple->t_infomask |= HEAP_XMAX_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return true;
                        }
 
@@ -769,11 +850,17 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
                else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
                {
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
+                       {
                                tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
+                       }
                        return false;
                }
                else
+               {
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
        }
 
        /*
@@ -831,12 +918,16 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
                if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
                {
                        if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
-                               tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
+                       {
+                               tuple->t_infomask |= HEAP_XMAX_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
+                       }
                        return true;
                }
 
                /* xmax transaction committed */
                tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+               SetBufferCommitInfoNeedsSave(buffer);
        }
 
        /*
@@ -886,7 +977,8 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
  * even if we see that the deleting transaction has committed.
  */
 HTSV_Result
-HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
+HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
+                                                Buffer buffer)
 {
        /*
         * Has inserting transaction committed?
@@ -916,9 +1008,11 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                        if (TransactionIdDidCommit(xvac))
                        {
                                tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return HEAPTUPLE_DEAD;
                        }
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
                }
                else if (tuple->t_infomask & HEAP_MOVED_IN)
                {
@@ -929,10 +1023,14 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                        if (TransactionIdIsInProgress(xvac))
                                return HEAPTUPLE_INSERT_IN_PROGRESS;
                        if (TransactionIdDidCommit(xvac))
+                       {
                                tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                               SetBufferCommitInfoNeedsSave(buffer);
+                       }
                        else
                        {
                                tuple->t_infomask |= HEAP_XMIN_INVALID;
+                               SetBufferCommitInfoNeedsSave(buffer);
                                return HEAPTUPLE_DEAD;
                        }
                }
@@ -946,7 +1044,10 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                        return HEAPTUPLE_DELETE_IN_PROGRESS;
                }
                else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
+               {
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
                else
                {
                        /*
@@ -954,6 +1055,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                         * crashed
                         */
                        tuple->t_infomask |= HEAP_XMIN_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
                        return HEAPTUPLE_DEAD;
                }
                /* Should only get here if we set XMIN_COMMITTED */
@@ -986,6 +1088,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                         * it did not and will never actually update it.
                         */
                        tuple->t_infomask |= HEAP_XMAX_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
                }
                return HEAPTUPLE_LIVE;
        }
@@ -995,7 +1098,10 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
                        return HEAPTUPLE_DELETE_IN_PROGRESS;
                else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
+               {
                        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
                else
                {
                        /*
@@ -1003,6 +1109,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                         * crashed
                         */
                        tuple->t_infomask |= HEAP_XMAX_INVALID;
+                       SetBufferCommitInfoNeedsSave(buffer);
                        return HEAPTUPLE_LIVE;
                }
                /* Should only get here if we set XMAX_COMMITTED */
index 785ae80b2433a2c0a901155fed5f226cc4bb9e11..62a547a181a38eeb290fa496baa53d84be49724e 100644 (file)
@@ -7,20 +7,18 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/valid.h,v 1.34 2004/08/29 04:13:04 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/valid.h,v 1.35 2004/10/15 22:40:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef VALID_H
 #define VALID_H
 
-/* ----------------
+/*
  *             HeapKeyTest
  *
- *             Test a heap tuple with respect to a scan key.
- * ----------------
+ *             Test a heap tuple to see if it satisfies a scan key.
  */
-
 #define HeapKeyTest(tuple, \
                                        tupdesc, \
                                        nkeys, \
@@ -28,9 +26,7 @@
                                        result) \
 do \
 { \
-/* We use underscores to protect the variable passed in as parameters */ \
-/* We use two underscore here because this macro is included in the \
-   macro below */ \
+       /* Use underscores to protect the variables passed in as parameters */ \
        int                     __cur_nkeys = (nkeys); \
        ScanKey         __cur_keys = (keys); \
  \
@@ -40,6 +36,12 @@ do \
                Datum   __atp; \
                bool    __isnull; \
                Datum   __test; \
+ \
+               if (__cur_keys->sk_flags & SK_ISNULL) \
+               { \
+                       (result) = false; \
+                       break; \
+               } \
  \
                __atp = heap_getattr((tuple), \
                                                         __cur_keys->sk_attno, \
@@ -47,13 +49,6 @@ do \
                                                         &__isnull); \
  \
                if (__isnull) \
-               { \
-                       /* XXX eventually should check if SK_ISNULL */ \
-                       (result) = false; \
-                       break; \
-               } \
- \
-               if (__cur_keys->sk_flags & SK_ISNULL) \
                { \
                        (result) = false; \
                        break; \
@@ -70,7 +65,7 @@ do \
        } \
 } while (0)
 
-/* ----------------
+/*
  *             HeapTupleSatisfies
  *
  *     res is set TRUE if the HeapTuple satisfies the timequal and keytest,
@@ -83,7 +78,6 @@ do \
  *     least likely to fail, too.      we should really add the time qual test to
  *     the restriction and optimize it in the normal way.      this has interactions
  *     with joey's expensive function work.
- * ----------------
  */
 #define HeapTupleSatisfies(tuple, \
                                                   relation, \
@@ -95,24 +89,13 @@ do \
                                                   res) \
 do \
 { \
-/* We use underscores to protect the variable passed in as parameters */ \
        if ((key) != NULL) \
-               HeapKeyTest(tuple, RelationGetDescr(relation), \
-                                                  (nKeys), (key), (res)); \
+               HeapKeyTest(tuple, RelationGetDescr(relation), nKeys, key, res); \
        else \
                (res) = true; \
  \
-       if (res) \
-       { \
-               if ((relation)->rd_rel->relkind != RELKIND_UNCATALOGED) \
-               { \
-                       uint16  _infomask = (tuple)->t_data->t_infomask; \
-                       \
-                       (res) = HeapTupleSatisfiesVisibility((tuple), (snapshot)); \
-                       if ((tuple)->t_data->t_infomask != _infomask) \
-                               SetBufferCommitInfoNeedsSave(buffer); \
-               } \
-       } \
+       if ((res) && (relation)->rd_rel->relkind != RELKIND_UNCATALOGED) \
+               (res) = HeapTupleSatisfiesVisibility(tuple, snapshot, buffer); \
 } while (0)
 
 #endif   /* VALID_H */
index cb8feda8bdf306e0ee387eca68714529d8c619bb..04bc09e22c69707301f4688205a5981ae46728b1 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.86 2004/08/29 05:06:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/bufmgr.h,v 1.87 2004/10/15 22:40:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,13 +51,14 @@ extern int32 *LocalRefCount;
  * These routines are beaten on quite heavily, hence the macroization.
  */
 
-#define BAD_BUFFER_ID(bid) ((bid) < 1 || (bid) > NBuffers)
-
 /*
  * BufferIsValid
  *             True iff the given buffer number is valid (either as a shared
  *             or local buffer).
  *
+ * This is not quite the inverse of the BufferIsInvalid() macro, since this
+ * adds sanity rangechecks on the buffer number.
+ *
  * Note: For a long time this was defined the same as BufferIsPinned,
  * that is it would say False if you didn't hold a pin on the buffer.
  * I believe this was bogus and served only to mask logic errors.
@@ -66,10 +67,9 @@ extern int32 *LocalRefCount;
  */
 #define BufferIsValid(bufnum) \
 ( \
-       BufferIsLocal(bufnum) ? \
-               ((bufnum) >= -NLocBuffer) \
-       : \
-               (! BAD_BUFFER_ID(bufnum)) \
+       (bufnum) != InvalidBuffer && \
+       (bufnum) >= -NLocBuffer && \
+       (bufnum) <= NBuffers \
 )
 
 /*
@@ -81,15 +81,13 @@ extern int32 *LocalRefCount;
  */
 #define BufferIsPinned(bufnum) \
 ( \
-       BufferIsLocal(bufnum) ? \
-               ((bufnum) >= -NLocBuffer && LocalRefCount[-(bufnum) - 1] > 0) \
+       !BufferIsValid(bufnum) ? \
+               false \
        : \
-       ( \
-               BAD_BUFFER_ID(bufnum) ? \
-                       false \
+               BufferIsLocal(bufnum) ? \
+                       (LocalRefCount[-(bufnum) - 1] > 0) \
                : \
                        (PrivateRefCount[(bufnum) - 1] > 0) \
-       ) \
 )
 
 /*
index 0854fa793a1a164d4ad007079850dc739be5babe..8aa6ed2c678f012f18f7fe9bbb09545ce85bab2d 100644 (file)
@@ -1,14 +1,14 @@
 /*-------------------------------------------------------------------------
  *
  * tqual.h
- *       POSTGRES "time" qualification definitions, ie, tuple visibility rules.
+ *       POSTGRES "time qualification" definitions, ie, tuple visibility rules.
  *
  *       Should be moved/renamed...    - vadim 07/28/98
  *
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/tqual.h,v 1.53 2004/09/16 18:35:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/tqual.h,v 1.54 2004/10/15 22:40:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 
 #include "access/htup.h"
 #include "access/xact.h"
+#include "storage/buf.h"
 
 
 /*
@@ -72,23 +73,23 @@ extern TransactionId RecentGlobalXmin;
  *             Assumes heap tuple is valid.
  *             Beware of multiple evaluations of snapshot argument.
  */
-#define HeapTupleSatisfiesVisibility(tuple, snapshot) \
+#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \
 ((snapshot) == SnapshotNow ? \
-       HeapTupleSatisfiesNow((tuple)->t_data) \
+       HeapTupleSatisfiesNow((tuple)->t_data, buffer) \
 : \
        ((snapshot) == SnapshotSelf ? \
-               HeapTupleSatisfiesItself((tuple)->t_data) \
+               HeapTupleSatisfiesItself((tuple)->t_data, buffer) \
        : \
                ((snapshot) == SnapshotAny ? \
                        true \
                : \
                        ((snapshot) == SnapshotToast ? \
-                               HeapTupleSatisfiesToast((tuple)->t_data) \
+                               HeapTupleSatisfiesToast((tuple)->t_data, buffer) \
                        : \
                                ((snapshot) == SnapshotDirty ? \
-                                       HeapTupleSatisfiesDirty((tuple)->t_data) \
+                                       HeapTupleSatisfiesDirty((tuple)->t_data, buffer) \
                                : \
-                                       HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
+                                       HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot, buffer) \
                                ) \
                        ) \
                ) \
@@ -108,21 +109,20 @@ typedef enum
        HEAPTUPLE_DEAD,                         /* tuple is dead and deletable */
        HEAPTUPLE_LIVE,                         /* tuple is live (committed, no deleter) */
        HEAPTUPLE_RECENTLY_DEAD,        /* tuple is dead, but not deletable yet */
-       HEAPTUPLE_INSERT_IN_PROGRESS,           /* inserting xact is still in
-                                                                                * progress */
+       HEAPTUPLE_INSERT_IN_PROGRESS,   /* inserting xact is still in progress */
        HEAPTUPLE_DELETE_IN_PROGRESS    /* deleting xact is still in progress */
 } HTSV_Result;
 
-extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple);
+extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer);
+extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer);
+extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer);
+extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple, Buffer buffer);
 extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
-                                                  Snapshot snapshot);
+                                                  Snapshot snapshot, Buffer buffer);
 extern int HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
-                                                CommandId curcid);
+                                                CommandId curcid, Buffer buffer);
 extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
-                                                TransactionId OldestXmin);
+                                                TransactionId OldestXmin, Buffer buffer);
 
 extern Snapshot GetTransactionSnapshot(void);
 extern Snapshot GetLatestSnapshot(void);