aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/time/tqual.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/time/tqual.c')
-rw-r--r--src/backend/utils/time/tqual.c162
1 files changed, 122 insertions, 40 deletions
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 43909008863..916d840ea34 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -16,13 +16,14 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.86 2005/03/20 23:40:27 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.87 2005/04/28 21:47:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "access/multixact.h"
#include "access/subtrans.h"
#include "storage/sinval.h"
#include "utils/tqual.h"
@@ -129,7 +130,12 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return true;
- /* deleting subtransaction aborted */
+ if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
+ return true;
+
+ Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
+
+ /* deleting subtransaction aborted? */
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
@@ -139,9 +145,6 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- return true;
-
return false;
}
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
@@ -167,14 +170,21 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
return false; /* updated by other */
}
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ /* MultiXacts are currently only allowed to lock tuples */
+ Assert(tuple->t_infomask & HEAP_IS_LOCKED);
+ return true;
+ }
+
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
return false;
}
@@ -191,7 +201,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
/* xmax transaction committed */
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
SetBufferCommitInfoNeedsSave(buffer);
@@ -300,7 +310,12 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return true;
- /* deleting subtransaction aborted */
+ if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
+ return true;
+
+ Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
+
+ /* deleting subtransaction aborted? */
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
@@ -310,9 +325,6 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- return true;
-
if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
return true; /* deleted after scan started */
else
@@ -341,14 +353,21 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
return false;
}
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ /* MultiXacts are currently only allowed to lock tuples */
+ Assert(tuple->t_infomask & HEAP_IS_LOCKED);
+ return true;
+ }
+
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
return true; /* deleted after scan started */
@@ -368,7 +387,7 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
/* xmax transaction committed */
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
SetBufferCommitInfoNeedsSave(buffer);
@@ -454,6 +473,22 @@ HeapTupleSatisfiesToast(HeapTupleHeader tuple, Buffer buffer)
* code, since UPDATE needs to know more than "is it visible?". Also,
* tuples of my own xact are tested against the passed CommandId not
* CurrentCommandId.
+ *
+ * The possible return codes are:
+ *
+ * HeapTupleInvisible: the tuple didn't exist at all when the scan started,
+ * e.g. it was created by a later CommandId.
+ *
+ * HeapTupleMayBeUpdated: The tuple is valid and visible, so it may be
+ * updated.
+ *
+ * HeapTupleSelfUpdated: The tuple was updated by the current transaction,
+ * after the current scan started.
+ *
+ * HeapTupleUpdated: The tuple was updated by a committed transaction.
+ *
+ * HeapTupleBeingUpdated: The tuple is being updated by an in-progress
+ * transaction other than the current transaction.
*/
HTSU_Result
HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
@@ -512,7 +547,12 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return HeapTupleMayBeUpdated;
- /* deleting subtransaction aborted */
+ if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
+ return HeapTupleMayBeUpdated;
+
+ Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
+
+ /* deleting subtransaction aborted? */
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
@@ -522,9 +562,6 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- return HeapTupleMayBeUpdated;
-
if (HeapTupleHeaderGetCmax(tuple) >= curcid)
return HeapTupleSelfUpdated; /* updated after scan
* started */
@@ -555,14 +592,26 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return HeapTupleMayBeUpdated;
return HeapTupleUpdated; /* updated by other */
}
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ /* MultiXacts are currently only allowed to lock tuples */
+ Assert(tuple->t_infomask & HEAP_IS_LOCKED);
+
+ if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))
+ return HeapTupleBeingUpdated;
+ tuple->t_infomask |= HEAP_XMAX_INVALID;
+ SetBufferCommitInfoNeedsSave(buffer);
+ return HeapTupleMayBeUpdated;
+ }
+
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return HeapTupleMayBeUpdated;
if (HeapTupleHeaderGetCmax(tuple) >= curcid)
return HeapTupleSelfUpdated; /* updated after scan
@@ -585,7 +634,7 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
/* xmax transaction committed */
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
SetBufferCommitInfoNeedsSave(buffer);
@@ -669,7 +718,12 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return true;
- /* deleting subtransaction aborted */
+ if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
+ return true;
+
+ Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
+
+ /* deleting subtransaction aborted? */
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
@@ -679,9 +733,6 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- return true;
-
return false;
}
else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
@@ -710,15 +761,22 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
SnapshotDirty->tid = tuple->t_ctid;
return false; /* updated by other */
}
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ /* MultiXacts are currently only allowed to lock tuples */
+ Assert(tuple->t_infomask & HEAP_IS_LOCKED);
+ return true;
+ }
+
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
{
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return true;
return false;
}
@@ -738,7 +796,7 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
/* xmax transaction committed */
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
SetBufferCommitInfoNeedsSave(buffer);
@@ -828,7 +886,12 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return true;
- /* deleting subtransaction aborted */
+ if (tuple->t_infomask & HEAP_IS_LOCKED) /* not deleter */
+ return true;
+
+ Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));
+
+ /* deleting subtransaction aborted? */
/* FIXME -- is this correct w.r.t. the cmax of the tuple? */
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
{
@@ -839,9 +902,6 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
- return true;
-
if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
return true; /* deleted after scan started */
else
@@ -902,8 +962,15 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
return true;
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
+ return true;
+
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ /* MultiXacts are currently only allowed to lock tuples */
+ Assert(tuple->t_infomask & HEAP_IS_LOCKED);
return true;
+ }
if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
{
@@ -1043,7 +1110,7 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
{
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
return HEAPTUPLE_INSERT_IN_PROGRESS;
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
return HEAPTUPLE_INSERT_IN_PROGRESS;
/* inserted and then deleted by same xact */
return HEAPTUPLE_DELETE_IN_PROGRESS;
@@ -1074,22 +1141,30 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
if (tuple->t_infomask & HEAP_XMAX_INVALID)
return HEAPTUPLE_LIVE;
- if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+ if (tuple->t_infomask & HEAP_IS_LOCKED)
{
/*
- * "Deleting" xact really only marked it for update, so the tuple
+ * "Deleting" xact really only locked it, so the tuple
* is live in any case. However, we must make sure that either
* XMAX_COMMITTED or XMAX_INVALID gets set once the xact is gone;
* otherwise it is unsafe to recycle CLOG status after vacuuming.
*/
if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
{
- if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
- return HEAPTUPLE_LIVE;
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))
+ return HEAPTUPLE_LIVE;
+ }
+ else
+ {
+ if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
+ return HEAPTUPLE_LIVE;
+ }
/*
* We don't really care whether xmax did commit, abort or
- * crash. We know that xmax did mark the tuple for update, but
+ * crash. We know that xmax did lock the tuple, but
* it did not and will never actually update it.
*/
tuple->t_infomask |= HEAP_XMAX_INVALID;
@@ -1098,6 +1173,13 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
return HEAPTUPLE_LIVE;
}
+ if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
+ {
+ /* MultiXacts are currently only allowed to lock tuples */
+ Assert(tuple->t_infomask & HEAP_IS_LOCKED);
+ return HEAPTUPLE_LIVE;
+ }
+
if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
{
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))