Commit 264a6b12 authored by Heikki Linnakangas's avatar Heikki Linnakangas

The rolled-back flag on serializable xacts was pointless and redundant with

the marked-for-death flag. It was only set for a fleeting moment while a
transaction was being cleaned up at rollback. All the places that checked
for the rolled-back flag should also check the marked-for-death flag, as
both flags mean that the transaction will roll back. I also renamed the
marked-for-death into "doomed", which is a lot shorter name.
parent 0a0e2b52
...@@ -244,9 +244,9 @@ ...@@ -244,9 +244,9 @@
#define SxactIsOnFinishedList(sxact) (!SHMQueueIsDetached(&((sxact)->finishedLink))) #define SxactIsOnFinishedList(sxact) (!SHMQueueIsDetached(&((sxact)->finishedLink)))
#define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
#define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0) #define SxactIsCommitted(sxact) (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
#define SxactIsRolledBack(sxact) (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 0) #define SxactIsPrepared(sxact) (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
#define SxactIsDoomed(sxact) (((sxact)->flags & SXACT_FLAG_DOOMED) != 0)
#define SxactIsReadOnly(sxact) (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0) #define SxactIsReadOnly(sxact) (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0)
#define SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0) #define SxactHasSummaryConflictIn(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
#define SxactHasSummaryConflictOut(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0) #define SxactHasSummaryConflictOut(sxact) (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0)
...@@ -259,7 +259,6 @@ ...@@ -259,7 +259,6 @@
#define SxactIsDeferrableWaiting(sxact) (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0) #define SxactIsDeferrableWaiting(sxact) (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)
#define SxactIsROSafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0) #define SxactIsROSafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0)
#define SxactIsROUnsafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0) #define SxactIsROUnsafe(sxact) (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)
#define SxactIsMarkedForDeath(sxact) (((sxact)->flags & SXACT_FLAG_MARKED_FOR_DEATH) != 0)
/* /*
* Compute the hash code associated with a PREDICATELOCKTARGETTAG. * Compute the hash code associated with a PREDICATELOCKTARGETTAG.
...@@ -609,8 +608,8 @@ RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer) ...@@ -609,8 +608,8 @@ RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Assert(reader != writer); Assert(reader != writer);
/* Check the ends of the purported conflict first. */ /* Check the ends of the purported conflict first. */
if (SxactIsRolledBack(reader) if (SxactIsDoomed(reader)
|| SxactIsRolledBack(writer) || SxactIsDoomed(writer)
|| SHMQueueEmpty(&reader->outConflicts) || SHMQueueEmpty(&reader->outConflicts)
|| SHMQueueEmpty(&writer->inConflicts)) || SHMQueueEmpty(&writer->inConflicts))
return false; return false;
...@@ -3048,7 +3047,7 @@ SetNewSxactGlobalXmin(void) ...@@ -3048,7 +3047,7 @@ SetNewSxactGlobalXmin(void)
for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact)) for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
{ {
if (!SxactIsRolledBack(sxact) if (!SxactIsDoomed(sxact)
&& !SxactIsCommitted(sxact) && !SxactIsCommitted(sxact)
&& sxact != OldCommittedSxact) && sxact != OldCommittedSxact)
{ {
...@@ -3113,7 +3112,7 @@ ReleasePredicateLocks(const bool isCommit) ...@@ -3113,7 +3112,7 @@ ReleasePredicateLocks(const bool isCommit)
} }
Assert(!isCommit || SxactIsPrepared(MySerializableXact)); Assert(!isCommit || SxactIsPrepared(MySerializableXact));
Assert(!SxactIsRolledBack(MySerializableXact)); Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
Assert(!SxactIsCommitted(MySerializableXact)); Assert(!SxactIsCommitted(MySerializableXact));
/* may not be serializable during COMMIT/ROLLBACK PREPARED */ /* may not be serializable during COMMIT/ROLLBACK PREPARED */
...@@ -3153,9 +3152,7 @@ ReleasePredicateLocks(const bool isCommit) ...@@ -3153,9 +3152,7 @@ ReleasePredicateLocks(const bool isCommit)
MySerializableXact->flags |= SXACT_FLAG_READ_ONLY; MySerializableXact->flags |= SXACT_FLAG_READ_ONLY;
} }
else else
{ MySerializableXact->flags |= SXACT_FLAG_DOOMED;
MySerializableXact->flags |= SXACT_FLAG_ROLLED_BACK;
}
if (!topLevelIsDeclaredReadOnly) if (!topLevelIsDeclaredReadOnly)
{ {
...@@ -3531,7 +3528,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, ...@@ -3531,7 +3528,7 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
nextConflict; nextConflict;
Assert(sxact != NULL); Assert(sxact != NULL);
Assert(SxactIsRolledBack(sxact) || SxactIsCommitted(sxact)); Assert(SxactIsDoomed(sxact) || SxactIsCommitted(sxact));
Assert(LWLockHeldByMe(SerializableFinishedListLock)); Assert(LWLockHeldByMe(SerializableFinishedListLock));
/* /*
...@@ -3736,7 +3733,8 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation, ...@@ -3736,7 +3733,8 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
if (!SerializationNeededForRead(relation, snapshot)) if (!SerializationNeededForRead(relation, snapshot))
return; return;
if (SxactIsMarkedForDeath(MySerializableXact)) /* Check if someone else has already decided that we need to die */
if (SxactIsDoomed(MySerializableXact))
{ {
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
...@@ -3850,11 +3848,9 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation, ...@@ -3850,11 +3848,9 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
} }
sxact = sxid->myXact; sxact = sxid->myXact;
Assert(TransactionIdEquals(sxact->topXid, xid)); Assert(TransactionIdEquals(sxact->topXid, xid));
if (sxact == MySerializableXact if (sxact == MySerializableXact || SxactIsDoomed(sxact))
|| SxactIsRolledBack(sxact)
|| SxactIsMarkedForDeath(sxact))
{ {
/* We can't conflict with our own transaction or one rolled back. */ /* Can't conflict with ourself or a transaction that will roll back. */
LWLockRelease(SerializableXactHashLock); LWLockRelease(SerializableXactHashLock);
return; return;
} }
...@@ -3869,7 +3865,7 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation, ...@@ -3869,7 +3865,7 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
{ {
if (!SxactIsPrepared(sxact)) if (!SxactIsPrepared(sxact))
{ {
sxact->flags |= SXACT_FLAG_MARKED_FOR_DEATH; sxact->flags |= SXACT_FLAG_DOOMED;
LWLockRelease(SerializableXactHashLock); LWLockRelease(SerializableXactHashLock);
return; return;
} }
...@@ -3996,7 +3992,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag) ...@@ -3996,7 +3992,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
mypredlocktag = predlock->tag; mypredlocktag = predlock->tag;
} }
} }
else if (!SxactIsRolledBack(sxact) else if (!SxactIsDoomed(sxact)
&& (!SxactIsCommitted(sxact) && (!SxactIsCommitted(sxact)
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin, || TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
sxact->finishedBefore)) sxact->finishedBefore))
...@@ -4009,7 +4005,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag) ...@@ -4009,7 +4005,7 @@ CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
* Re-check after getting exclusive lock because the other * Re-check after getting exclusive lock because the other
* transaction may have flagged a conflict. * transaction may have flagged a conflict.
*/ */
if (!SxactIsRolledBack(sxact) if (!SxactIsDoomed(sxact)
&& (!SxactIsCommitted(sxact) && (!SxactIsCommitted(sxact)
|| TransactionIdPrecedes(GetTransactionSnapshot()->xmin, || TransactionIdPrecedes(GetTransactionSnapshot()->xmin,
sxact->finishedBefore)) sxact->finishedBefore))
...@@ -4113,7 +4109,8 @@ CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple, ...@@ -4113,7 +4109,8 @@ CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple,
if (!SerializationNeededForWrite(relation)) if (!SerializationNeededForWrite(relation))
return; return;
if (SxactIsMarkedForDeath(MySerializableXact)) /* Check if someone else has already decided that we need to die */
if (SxactIsDoomed(MySerializableXact))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE), (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to read/write dependencies among transactions"), errmsg("could not serialize access due to read/write dependencies among transactions"),
...@@ -4417,7 +4414,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader, ...@@ -4417,7 +4414,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader,
{ {
SERIALIZABLEXACT *t0 = conflict->sxactOut; SERIALIZABLEXACT *t0 = conflict->sxactOut;
if (!SxactIsRolledBack(t0) if (!SxactIsDoomed(t0)
&& (!SxactIsCommitted(t0) && (!SxactIsCommitted(t0)
|| t0->commitSeqNo >= writer->commitSeqNo) || t0->commitSeqNo >= writer->commitSeqNo)
&& (!SxactIsReadOnly(t0) && (!SxactIsReadOnly(t0)
...@@ -4464,7 +4461,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader, ...@@ -4464,7 +4461,7 @@ OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader,
errdetail("Cancelled on conflict out to pivot %u, during read.", writer->topXid), errdetail("Cancelled on conflict out to pivot %u, during read.", writer->topXid),
errhint("The transaction might succeed if retried."))); errhint("The transaction might succeed if retried.")));
} }
writer->flags |= SXACT_FLAG_MARKED_FOR_DEATH; writer->flags |= SXACT_FLAG_DOOMED;
} }
} }
...@@ -4496,7 +4493,8 @@ PreCommit_CheckForSerializationFailure(void) ...@@ -4496,7 +4493,8 @@ PreCommit_CheckForSerializationFailure(void)
LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE); LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
if (SxactIsMarkedForDeath(MySerializableXact)) /* Check if someone else has already decided that we need to die */
if (SxactIsDoomed(MySerializableXact))
{ {
LWLockRelease(SerializableXactHashLock); LWLockRelease(SerializableXactHashLock);
ereport(ERROR, ereport(ERROR,
...@@ -4513,8 +4511,7 @@ PreCommit_CheckForSerializationFailure(void) ...@@ -4513,8 +4511,7 @@ PreCommit_CheckForSerializationFailure(void)
while (nearConflict) while (nearConflict)
{ {
if (!SxactIsCommitted(nearConflict->sxactOut) if (!SxactIsCommitted(nearConflict->sxactOut)
&& !SxactIsRolledBack(nearConflict->sxactOut) && !SxactIsDoomed(nearConflict->sxactOut))
&& !SxactIsMarkedForDeath(nearConflict->sxactOut))
{ {
RWConflict farConflict; RWConflict farConflict;
...@@ -4527,10 +4524,9 @@ PreCommit_CheckForSerializationFailure(void) ...@@ -4527,10 +4524,9 @@ PreCommit_CheckForSerializationFailure(void)
if (farConflict->sxactOut == MySerializableXact if (farConflict->sxactOut == MySerializableXact
|| (!SxactIsCommitted(farConflict->sxactOut) || (!SxactIsCommitted(farConflict->sxactOut)
&& !SxactIsReadOnly(farConflict->sxactOut) && !SxactIsReadOnly(farConflict->sxactOut)
&& !SxactIsRolledBack(farConflict->sxactOut) && !SxactIsDoomed(farConflict->sxactOut)))
&& !SxactIsMarkedForDeath(farConflict->sxactOut)))
{ {
nearConflict->sxactOut->flags |= SXACT_FLAG_MARKED_FOR_DEATH; nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
break; break;
} }
farConflict = (RWConflict) farConflict = (RWConflict)
......
...@@ -90,22 +90,21 @@ typedef struct SERIALIZABLEXACT ...@@ -90,22 +90,21 @@ typedef struct SERIALIZABLEXACT
int pid; /* pid of associated process */ int pid; /* pid of associated process */
} SERIALIZABLEXACT; } SERIALIZABLEXACT;
#define SXACT_FLAG_ROLLED_BACK 0x00000001 #define SXACT_FLAG_COMMITTED 0x00000001 /* already committed */
#define SXACT_FLAG_COMMITTED 0x00000002 #define SXACT_FLAG_PREPARED 0x00000002 /* about to commit */
#define SXACT_FLAG_DOOMED 0x00000004 /* will roll back */
/* /*
* The following flag actually means that the flagged transaction has a * The following flag actually means that the flagged transaction has a
* conflict out *to a transaction which committed ahead of it*. It's hard * conflict out *to a transaction which committed ahead of it*. It's hard
* to get that into a name of a reasonable length. * to get that into a name of a reasonable length.
*/ */
#define SXACT_FLAG_CONFLICT_OUT 0x00000004 #define SXACT_FLAG_CONFLICT_OUT 0x00000008
#define SXACT_FLAG_READ_ONLY 0x00000008 #define SXACT_FLAG_READ_ONLY 0x00000010
#define SXACT_FLAG_MARKED_FOR_DEATH 0x00000010
#define SXACT_FLAG_DEFERRABLE_WAITING 0x00000020 #define SXACT_FLAG_DEFERRABLE_WAITING 0x00000020
#define SXACT_FLAG_RO_SAFE 0x00000040 #define SXACT_FLAG_RO_SAFE 0x00000040
#define SXACT_FLAG_RO_UNSAFE 0x00000080 #define SXACT_FLAG_RO_UNSAFE 0x00000080
#define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000100 #define SXACT_FLAG_SUMMARY_CONFLICT_IN 0x00000100
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000200 #define SXACT_FLAG_SUMMARY_CONFLICT_OUT 0x00000200
#define SXACT_FLAG_PREPARED 0x00000400
/* /*
* The following types are used to provide an ad hoc list for holding * The following types are used to provide an ad hoc list for holding
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment