PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
predicate.h File Reference
#include "storage/lock.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
Include dependency graph for predicate.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define NUM_OLDSERXID_BUFFERS   16
 

Functions

void InitPredicateLocks (void)
 
Size PredicateLockShmemSize (void)
 
void CheckPointPredicate (void)
 
bool PageIsPredicateLocked (Relation relation, BlockNumber blkno)
 
Snapshot GetSerializableTransactionSnapshot (Snapshot snapshot)
 
void SetSerializableTransactionSnapshot (Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
 
void RegisterPredicateLockingXid (TransactionId xid)
 
void PredicateLockRelation (Relation relation, Snapshot snapshot)
 
void PredicateLockPage (Relation relation, BlockNumber blkno, Snapshot snapshot)
 
void PredicateLockTuple (Relation relation, HeapTuple tuple, Snapshot snapshot)
 
void PredicateLockPageSplit (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void PredicateLockPageCombine (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void TransferPredicateLocksToHeapRelation (Relation relation)
 
void ReleasePredicateLocks (bool isCommit)
 
void CheckForSerializableConflictOut (bool valid, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
 
void CheckForSerializableConflictIn (Relation relation, HeapTuple tuple, Buffer buffer)
 
void CheckTableForSerializableConflictIn (Relation relation)
 
void PreCommit_CheckForSerializationFailure (void)
 
void AtPrepare_PredicateLocks (void)
 
void PostPrepare_PredicateLocks (TransactionId xid)
 
void PredicateLockTwoPhaseFinish (TransactionId xid, bool isCommit)
 
void predicatelock_twophase_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 

Variables

int max_predicate_locks_per_xact
 
int max_predicate_locks_per_relation
 
int max_predicate_locks_per_page
 

Macro Definition Documentation

#define NUM_OLDSERXID_BUFFERS   16

Definition at line 31 of file predicate.h.

Referenced by OldSerXidInit(), and PredicateLockShmemSize().

Function Documentation

void AtPrepare_PredicateLocks ( void  )

Definition at line 4803 of file predicate.c.

References TwoPhasePredicateRecord::data, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, InvalidSerializableXact, TwoPhasePredicateRecord::lockRecord, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myTarget, NULL, offsetof, SERIALIZABLEXACT::predicateLocks, RegisterTwoPhaseRecord(), SHMQueueNext(), PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, TwoPhasePredicateLockRecord::target, TWOPHASE_RM_PREDICATELOCK_ID, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, PREDICATELOCK::xactLink, TwoPhasePredicateRecord::xactRecord, SERIALIZABLEXACT::xmin, and TwoPhasePredicateXactRecord::xmin.

Referenced by PrepareTransaction().

4804 {
4805  PREDICATELOCK *predlock;
4806  SERIALIZABLEXACT *sxact;
4807  TwoPhasePredicateRecord record;
4808  TwoPhasePredicateXactRecord *xactRecord;
4809  TwoPhasePredicateLockRecord *lockRecord;
4810 
4811  sxact = MySerializableXact;
4812  xactRecord = &(record.data.xactRecord);
4813  lockRecord = &(record.data.lockRecord);
4814 
4816  return;
4817 
4818  /* Generate an xact record for our SERIALIZABLEXACT */
4820  xactRecord->xmin = MySerializableXact->xmin;
4821  xactRecord->flags = MySerializableXact->flags;
4822 
4823  /*
4824  * Note that we don't include the list of conflicts in our out in the
4825  * statefile, because new conflicts can be added even after the
4826  * transaction prepares. We'll just make a conservative assumption during
4827  * recovery instead.
4828  */
4829 
4831  &record, sizeof(record));
4832 
4833  /*
4834  * Generate a lock record for each lock.
4835  *
4836  * To do this, we need to walk the predicate lock list in our sxact rather
4837  * than using the local predicate lock table because the latter is not
4838  * guaranteed to be accurate.
4839  */
4840  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4841 
4842  predlock = (PREDICATELOCK *)
4843  SHMQueueNext(&(sxact->predicateLocks),
4844  &(sxact->predicateLocks),
4845  offsetof(PREDICATELOCK, xactLink));
4846 
4847  while (predlock != NULL)
4848  {
4850  lockRecord->target = predlock->tag.myTarget->tag;
4851 
4853  &record, sizeof(record));
4854 
4855  predlock = (PREDICATELOCK *)
4856  SHMQueueNext(&(sxact->predicateLocks),
4857  &(predlock->xactLink),
4858  offsetof(PREDICATELOCK, xactLink));
4859  }
4860 
4861  LWLockRelease(SerializablePredicateLockListLock);
4862 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
TwoPhasePredicateRecordType type
PREDICATELOCKTARGETTAG target
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1164
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define TWOPHASE_RM_PREDICATELOCK_ID
Definition: twophase_rmgr.h:28
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
union TwoPhasePredicateRecord::@101 data
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:555
PREDICATELOCKTARGET * myTarget
void CheckForSerializableConflictIn ( Relation  relation,
HeapTuple  tuple,
Buffer  buffer 
)

Definition at line 4324 of file predicate.c.

References BufferGetBlockNumber(), BufferIsValid, CheckTargetForConflictsIn(), RelFileNode::dbNode, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, MyXactDidWrite, NULL, RelationData::rd_id, RelationData::rd_node, SerializationNeededForWrite(), SET_PREDICATELOCKTARGETTAG_PAGE, SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, SxactIsDoomed, and HeapTupleData::t_self.

Referenced by _bt_check_unique(), _bt_doinsert(), heap_delete(), heap_insert(), heap_multi_insert(), heap_update(), and index_insert().

4326 {
4327  PREDICATELOCKTARGETTAG targettag;
4328 
4329  if (!SerializationNeededForWrite(relation))
4330  return;
4331 
4332  /* Check if someone else has already decided that we need to die */
4334  ereport(ERROR,
4335  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4336  errmsg("could not serialize access due to read/write dependencies among transactions"),
4337  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4338  errhint("The transaction might succeed if retried.")));
4339 
4340  /*
4341  * We're doing a write which might cause rw-conflicts now or later.
4342  * Memorize that fact.
4343  */
4344  MyXactDidWrite = true;
4345 
4346  /*
4347  * It is important that we check for locks from the finest granularity to
4348  * the coarsest granularity, so that granularity promotion doesn't cause
4349  * us to miss a lock. The new (coarser) lock will be acquired before the
4350  * old (finer) locks are released.
4351  *
4352  * It is not possible to take and hold a lock across the checks for all
4353  * granularities because each target could be in a separate partition.
4354  */
4355  if (tuple != NULL)
4356  {
4358  relation->rd_node.dbNode,
4359  relation->rd_id,
4360  ItemPointerGetBlockNumber(&(tuple->t_self)),
4361  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4362  CheckTargetForConflictsIn(&targettag);
4363  }
4364 
4365  if (BufferIsValid(buffer))
4366  {
4368  relation->rd_node.dbNode,
4369  relation->rd_id,
4371  CheckTargetForConflictsIn(&targettag);
4372  }
4373 
4375  relation->rd_node.dbNode,
4376  relation->rd_id);
4377  CheckTargetForConflictsIn(&targettag);
4378 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
int errhint(const char *fmt,...)
Definition: elog.c:987
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4146
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
int errcode(int sqlerrcode)
Definition: elog.c:575
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:542
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
ItemPointerData t_self
Definition: htup.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
int errmsg(const char *fmt,...)
Definition: elog.c:797
static bool MyXactDidWrite
Definition: predicate.c:412
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
void CheckForSerializableConflictOut ( bool  valid,
Relation  relation,
HeapTuple  tuple,
Buffer  buffer,
Snapshot  snapshot 
)

Definition at line 3943 of file predicate.c.

References Assert, SERIALIZABLEXACT::earliestOutConflictCommit, elog, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, FlagRWConflict(), SERIALIZABLEXACT::flags, GetTopTransactionIdIfAny(), HASH_FIND, hash_search(), HEAPTUPLE_DEAD, HEAPTUPLE_DELETE_IN_PROGRESS, HEAPTUPLE_INSERT_IN_PROGRESS, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXmin, HeapTupleSatisfiesVacuum(), SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXID::myXact, NULL, OldSerXidGetMinConflictCommitSeqNo(), RWConflictExists(), SERIALIZABLEXACT::SeqNo, SerializationNeededForRead(), SHMQueueEmpty(), SubTransGetTopmostTransaction(), SXACT_FLAG_DOOMED, SXACT_FLAG_SUMMARY_CONFLICT_OUT, SxactHasConflictOut, SxactHasSummaryConflictIn, SxactHasSummaryConflictOut, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, HeapTupleData::t_data, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdIsValid, TransactionIdPrecedes(), TransactionXmin, SERIALIZABLEXIDTAG::xid, and XidIsConcurrent().

Referenced by bitgetpage(), heap_fetch(), heap_get_latest_tid(), heap_hot_search_buffer(), heapgetpage(), heapgettup(), and tablesample_getnext().

3946 {
3947  TransactionId xid;
3948  SERIALIZABLEXIDTAG sxidtag;
3949  SERIALIZABLEXID *sxid;
3950  SERIALIZABLEXACT *sxact;
3951  HTSV_Result htsvResult;
3952 
3953  if (!SerializationNeededForRead(relation, snapshot))
3954  return;
3955 
3956  /* Check if someone else has already decided that we need to die */
3958  {
3959  ereport(ERROR,
3960  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3961  errmsg("could not serialize access due to read/write dependencies among transactions"),
3962  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3963  errhint("The transaction might succeed if retried.")));
3964  }
3965 
3966  /*
3967  * Check to see whether the tuple has been written to by a concurrent
3968  * transaction, either to create it not visible to us, or to delete it
3969  * while it is visible to us. The "visible" bool indicates whether the
3970  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
3971  * is going on with it.
3972  */
3973  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
3974  switch (htsvResult)
3975  {
3976  case HEAPTUPLE_LIVE:
3977  if (visible)
3978  return;
3979  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3980  break;
3982  if (!visible)
3983  return;
3984  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3985  break;
3987  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3988  break;
3990  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3991  break;
3992  case HEAPTUPLE_DEAD:
3993  return;
3994  default:
3995 
3996  /*
3997  * The only way to get to this default clause is if a new value is
3998  * added to the enum type without adding it to this switch
3999  * statement. That's a bug, so elog.
4000  */
4001  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
4002 
4003  /*
4004  * In spite of having all enum values covered and calling elog on
4005  * this default, some compilers think this is a code path which
4006  * allows xid to be used below without initialization. Silence
4007  * that warning.
4008  */
4009  xid = InvalidTransactionId;
4010  }
4013 
4014  /*
4015  * Find top level xid. Bail out if xid is too early to be a conflict, or
4016  * if it's our own xid.
4017  */
4019  return;
4020  xid = SubTransGetTopmostTransaction(xid);
4022  return;
4024  return;
4025 
4026  /*
4027  * Find sxact or summarized info for the top level xid.
4028  */
4029  sxidtag.xid = xid;
4030  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4031  sxid = (SERIALIZABLEXID *)
4033  if (!sxid)
4034  {
4035  /*
4036  * Transaction not found in "normal" SSI structures. Check whether it
4037  * got pushed out to SLRU storage for "old committed" transactions.
4038  */
4039  SerCommitSeqNo conflictCommitSeqNo;
4040 
4041  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
4042  if (conflictCommitSeqNo != 0)
4043  {
4044  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4046  || conflictCommitSeqNo
4048  ereport(ERROR,
4049  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4050  errmsg("could not serialize access due to read/write dependencies among transactions"),
4051  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4052  errhint("The transaction might succeed if retried.")));
4053 
4056  ereport(ERROR,
4057  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4058  errmsg("could not serialize access due to read/write dependencies among transactions"),
4059  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4060  errhint("The transaction might succeed if retried.")));
4061 
4063  }
4064 
4065  /* It's not serializable or otherwise not important. */
4066  LWLockRelease(SerializableXactHashLock);
4067  return;
4068  }
4069  sxact = sxid->myXact;
4070  Assert(TransactionIdEquals(sxact->topXid, xid));
4071  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4072  {
4073  /* Can't conflict with ourself or a transaction that will roll back. */
4074  LWLockRelease(SerializableXactHashLock);
4075  return;
4076  }
4077 
4078  /*
4079  * We have a conflict out to a transaction which has a conflict out to a
4080  * summarized transaction. That summarized transaction must have
4081  * committed first, and we can't tell when it committed in relation to our
4082  * snapshot acquisition, so something needs to be canceled.
4083  */
4084  if (SxactHasSummaryConflictOut(sxact))
4085  {
4086  if (!SxactIsPrepared(sxact))
4087  {
4088  sxact->flags |= SXACT_FLAG_DOOMED;
4089  LWLockRelease(SerializableXactHashLock);
4090  return;
4091  }
4092  else
4093  {
4094  LWLockRelease(SerializableXactHashLock);
4095  ereport(ERROR,
4096  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4097  errmsg("could not serialize access due to read/write dependencies among transactions"),
4098  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4099  errhint("The transaction might succeed if retried.")));
4100  }
4101  }
4102 
4103  /*
4104  * If this is a read-only transaction and the writing transaction has
4105  * committed, and it doesn't have a rw-conflict to a transaction which
4106  * committed before it, no conflict.
4107  */
4109  && SxactIsCommitted(sxact)
4110  && !SxactHasSummaryConflictOut(sxact)
4111  && (!SxactHasConflictOut(sxact)
4113  {
4114  /* Read-only transaction will appear to run first. No conflict. */
4115  LWLockRelease(SerializableXactHashLock);
4116  return;
4117  }
4118 
4119  if (!XidIsConcurrent(xid))
4120  {
4121  /* This write was already in our snapshot; no conflict. */
4122  LWLockRelease(SerializableXactHashLock);
4123  return;
4124  }
4125 
4127  {
4128  /* We don't want duplicate conflict records in the list. */
4129  LWLockRelease(SerializableXactHashLock);
4130  return;
4131  }
4132 
4133  /*
4134  * Flag the conflict. But first, if this conflict creates a dangerous
4135  * structure, ereport an error.
4136  */
4138  LWLockRelease(SerializableXactHashLock);
4139 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:637
int errhint(const char *fmt,...)
Definition: elog.c:987
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4500
uint32 TransactionId
Definition: c.h:397
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:269
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool XidIsConcurrent(TransactionId xid)
Definition: predicate.c:3900
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1164
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:386
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
HTSV_Result
Definition: tqual.h:49
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
TransactionId TransactionXmin
Definition: snapmgr.c:164
HeapTupleHeader t_data
Definition: htup.h:67
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
#define ereport(elevel, rest)
Definition: elog.h:122
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:270
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define InvalidSerCommitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo earliestOutConflictCommit
union SERIALIZABLEXACT::@100 SeqNo
static SerCommitSeqNo OldSerXidGetMinConflictCommitSeqNo(TransactionId xid)
Definition: predicate.c:949
uint64 SerCommitSeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:276
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:498
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
void CheckPointPredicate ( void  )

Definition at line 1041 of file predicate.c.

References OldSerXidControlData::headPage, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), OldSerXidPage, OldSerXidSlruCtl, SimpleLruFlush(), SimpleLruTruncate(), OldSerXidControlData::tailXid, and TransactionIdIsValid.

Referenced by CheckPointGuts().

1042 {
1043  int tailPage;
1044 
1045  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
1046 
1047  /* Exit quickly if the SLRU is currently not in use. */
1048  if (oldSerXidControl->headPage < 0)
1049  {
1050  LWLockRelease(OldSerXidLock);
1051  return;
1052  }
1053 
1055  {
1056  /* We can truncate the SLRU up to the page containing tailXid */
1057  tailPage = OldSerXidPage(oldSerXidControl->tailXid);
1058  }
1059  else
1060  {
1061  /*
1062  * The SLRU is no longer needed. Truncate to head before we set head
1063  * invalid.
1064  *
1065  * XXX: It's possible that the SLRU is not needed again until XID
1066  * wrap-around has happened, so that the segment containing headPage
1067  * that we leave behind will appear to be new again. In that case it
1068  * won't be removed until XID horizon advances enough to make it
1069  * current again.
1070  */
1071  tailPage = oldSerXidControl->headPage;
1072  oldSerXidControl->headPage = -1;
1073  }
1074 
1075  LWLockRelease(OldSerXidLock);
1076 
1077  /* Truncate away pages that are no longer required */
1079 
1080  /*
1081  * Flush dirty SLRU pages to disk
1082  *
1083  * This is not actually necessary from a correctness point of view. We do
1084  * it merely as a debugging aid.
1085  *
1086  * We're doing this after the truncation to avoid writing pages right
1087  * before deleting the file in which they sit, which would be completely
1088  * pointless.
1089  */
1091 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1169
#define OldSerXidPage(xid)
Definition: predicate.c:331
#define OldSerXidSlruCtl
Definition: predicate.c:312
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1104
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static OldSerXidControl oldSerXidControl
Definition: predicate.c:344
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId tailXid
Definition: predicate.c:338
void CheckTableForSerializableConflictIn ( Relation  relation)

Definition at line 4408 of file predicate.c.

References Assert, RelFileNode::dbNode, FlagRWConflict(), GET_PREDICATELOCKTARGETTAG_DB, GET_PREDICATELOCKTARGETTAG_RELATION, hash_seq_init(), hash_seq_search(), i, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myXact, MyXactDidWrite, NULL, NUM_PREDICATELOCK_PARTITIONS, offsetof, PredicateLockHashPartitionLockByIndex, PREDICATELOCKTARGET::predicateLocks, RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, RWConflictExists(), SerializationNeededForWrite(), SHMQueueNext(), PredXactListData::SxactGlobalXmin, PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, PREDICATELOCK::targetLink, and TransactionIdIsValid.

Referenced by ExecuteTruncate(), and heap_drop_with_catalog().

4409 {
4410  HASH_SEQ_STATUS seqstat;
4411  PREDICATELOCKTARGET *target;
4412  Oid dbId;
4413  Oid heapId;
4414  int i;
4415 
4416  /*
4417  * Bail out quickly if there are no serializable transactions running.
4418  * It's safe to check this without taking locks because the caller is
4419  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4420  * would matter here can be acquired while that is held.
4421  */
4423  return;
4424 
4425  if (!SerializationNeededForWrite(relation))
4426  return;
4427 
4428  /*
4429  * We're doing a write which might cause rw-conflicts now or later.
4430  * Memorize that fact.
4431  */
4432  MyXactDidWrite = true;
4433 
4434  Assert(relation->rd_index == NULL); /* not an index relation */
4435 
4436  dbId = relation->rd_node.dbNode;
4437  heapId = relation->rd_id;
4438 
4439  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4440  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4442  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4443 
4444  /* Scan through target list */
4446 
4447  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4448  {
4449  PREDICATELOCK *predlock;
4450 
4451  /*
4452  * Check whether this is a target which needs attention.
4453  */
4454  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4455  continue; /* wrong relation id */
4456  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4457  continue; /* wrong database id */
4458 
4459  /*
4460  * Loop through locks for this target and flag conflicts.
4461  */
4462  predlock = (PREDICATELOCK *)
4463  SHMQueueNext(&(target->predicateLocks),
4464  &(target->predicateLocks),
4465  offsetof(PREDICATELOCK, targetLink));
4466  while (predlock)
4467  {
4468  PREDICATELOCK *nextpredlock;
4469 
4470  nextpredlock = (PREDICATELOCK *)
4471  SHMQueueNext(&(target->predicateLocks),
4472  &(predlock->targetLink),
4473  offsetof(PREDICATELOCK, targetLink));
4474 
4475  if (predlock->tag.myXact != MySerializableXact
4477  {
4479  }
4480 
4481  predlock = nextpredlock;
4482  }
4483  }
4484 
4485  /* Release locks in reverse order */
4486  LWLockRelease(SerializableXactHashLock);
4487  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4489  LWLockRelease(SerializablePredicateLockListLock);
4490 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:637
static HTAB * PredicateLockTargetHash
Definition: predicate.c:387
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4500
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:542
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
Form_pg_index rd_index
Definition: rel.h:159
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
Oid rd_id
Definition: rel.h:116
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:248
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:412
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:555
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1634 of file predicate.c.

References Assert, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, GetSafeSnapshot(), GetSerializableTransactionSnapshotInt(), InvalidPid, IsolationIsSerializable, NULL, RecoveryInProgress(), XactDeferrable, and XactReadOnly.

Referenced by GetTransactionSnapshot().

1635 {
1637 
1638  /*
1639  * Can't use serializable mode while recovery is still active, as it is,
1640  * for example, on a hot standby. We could get here despite the check in
1641  * check_XactIsoLevel() if default_transaction_isolation is set to
1642  * serializable, so phrase the hint accordingly.
1643  */
1644  if (RecoveryInProgress())
1645  ereport(ERROR,
1646  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1647  errmsg("cannot use serializable mode in a hot standby"),
1648  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1649  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1650 
1651  /*
1652  * A special optimization is available for SERIALIZABLE READ ONLY
1653  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1654  * thereby avoid all SSI overhead once it's running.
1655  */
1657  return GetSafeSnapshot(snapshot);
1658 
1659  return GetSerializableTransactionSnapshotInt(snapshot,
1660  NULL, InvalidPid);
1661 }
bool XactDeferrable
Definition: xact.c:80
int errhint(const char *fmt,...)
Definition: elog.c:987
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1512
int errcode(int sqlerrcode)
Definition: elog.c:575
bool RecoveryInProgress(void)
Definition: xlog.c:7878
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1705
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define InvalidPid
Definition: miscadmin.h:31
void InitPredicateLocks ( void  )

Definition at line 1106 of file predicate.c.

References PredXactListData::activeList, Assert, PredXactListData::availableList, RWConflictPoolHeaderData::availableList, PredXactListData::CanPartialClearThrough, SERIALIZABLEXACT::commitSeqNo, CreatePredXact(), PredXactListData::element, RWConflictPoolHeaderData::element, HASHCTL::entrysize, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, HASHCTL::hash, HASH_BLOBS, HASH_ELEM, HASH_ENTER, HASH_FIXED_SIZE, HASH_FUNCTION, HASH_PARTITION, hash_search(), PredXactListData::HavePartialClearedThrough, i, SERIALIZABLEXACT::inConflicts, InvalidTransactionId, IsUnderPostmaster, HASHCTL::keysize, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, PredXactListElementData::link, max_prepared_xacts, MaxBackends, MemSet, mul_size(), NPREDICATELOCKTARGETENTS, HASHCTL::num_partitions, NUM_PREDICATELOCK_PARTITIONS, PredXactListData::OldCommittedSxact, OldSerXidInit(), SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, predicatelock_hash(), PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, PredXactListDataSize, PredXactListElementDataSize, SERIALIZABLEXACT::prepareSeqNo, RWConflictDataSize, RWConflictPoolHeaderDataSize, ScratchTargetTagHash, SERIALIZABLEXACT::SeqNo, SetInvalidVirtualTransactionId, ShmemAlloc(), ShmemInitHash(), ShmemInitStruct(), SHMQueueInit(), SHMQueueInsertBefore(), SXACT_FLAG_COMMITTED, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SERIALIZABLEXACT::topXid, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, and SERIALIZABLEXACT::xmin.

Referenced by CreateSharedMemoryAndSemaphores().

1107 {
1108  HASHCTL info;
1109  long max_table_size;
1110  Size requestSize;
1111  bool found;
1112 
1113 #ifndef EXEC_BACKEND
1115 #endif
1116 
1117  /*
1118  * Compute size of predicate lock target hashtable. Note these
1119  * calculations must agree with PredicateLockShmemSize!
1120  */
1121  max_table_size = NPREDICATELOCKTARGETENTS();
1122 
1123  /*
1124  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1125  * per-predicate-lock-target information.
1126  */
1127  MemSet(&info, 0, sizeof(info));
1128  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1129  info.entrysize = sizeof(PREDICATELOCKTARGET);
1131 
1132  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1133  max_table_size,
1134  max_table_size,
1135  &info,
1136  HASH_ELEM | HASH_BLOBS |
1138 
1139  /*
1140  * Reserve a dummy entry in the hash table; we use it to make sure there's
1141  * always one entry available when we need to split or combine a page,
1142  * because running out of space there could mean aborting a
1143  * non-serializable transaction.
1144  */
1145  if (!IsUnderPostmaster)
1146  {
1148  HASH_ENTER, &found);
1149  Assert(!found);
1150  }
1151 
1152  /* Pre-calculate the hash and partition lock of the scratch entry */
1155 
1156  /*
1157  * Allocate hash table for PREDICATELOCK structs. This stores per
1158  * xact-lock-of-a-target information.
1159  */
1160  MemSet(&info, 0, sizeof(info));
1161  info.keysize = sizeof(PREDICATELOCKTAG);
1162  info.entrysize = sizeof(PREDICATELOCK);
1163  info.hash = predicatelock_hash;
1165 
1166  /* Assume an average of 2 xacts per target */
1167  max_table_size *= 2;
1168 
1169  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1170  max_table_size,
1171  max_table_size,
1172  &info,
1175 
1176  /*
1177  * Compute size for serializable transaction hashtable. Note these
1178  * calculations must agree with PredicateLockShmemSize!
1179  */
1180  max_table_size = (MaxBackends + max_prepared_xacts);
1181 
1182  /*
1183  * Allocate a list to hold information on transactions participating in
1184  * predicate locking.
1185  *
1186  * Assume an average of 10 predicate locking transactions per backend.
1187  * This allows aggressive cleanup while detail is present before data must
1188  * be summarized for storage in SLRU and the "dummy" transaction.
1189  */
1190  max_table_size *= 10;
1191 
1192  PredXact = ShmemInitStruct("PredXactList",
1194  &found);
1195  Assert(found == IsUnderPostmaster);
1196  if (!found)
1197  {
1198  int i;
1199 
1208  requestSize = mul_size((Size) max_table_size,
1210  PredXact->element = ShmemAlloc(requestSize);
1211  /* Add all elements to available list, clean. */
1212  memset(PredXact->element, 0, requestSize);
1213  for (i = 0; i < max_table_size; i++)
1214  {
1216  &(PredXact->element[i].link));
1217  }
1233  }
1234  /* This never changes, so let's keep a local copy. */
1236 
1237  /*
1238  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1239  * information for serializable transactions which have accessed data.
1240  */
1241  MemSet(&info, 0, sizeof(info));
1242  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1243  info.entrysize = sizeof(SERIALIZABLEXID);
1244 
1245  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1246  max_table_size,
1247  max_table_size,
1248  &info,
1249  HASH_ELEM | HASH_BLOBS |
1250  HASH_FIXED_SIZE);
1251 
1252  /*
1253  * Allocate space for tracking rw-conflicts in lists attached to the
1254  * transactions.
1255  *
1256  * Assume an average of 5 conflicts per transaction. Calculations suggest
1257  * that this will prevent resource exhaustion in even the most pessimal
1258  * loads up to max_connections = 200 with all 200 connections pounding the
1259  * database with serializable transactions. Beyond that, there may be
1260  * occasional transactions canceled when trying to flag conflicts. That's
1261  * probably OK.
1262  */
1263  max_table_size *= 5;
1264 
1265  RWConflictPool = ShmemInitStruct("RWConflictPool",
1267  &found);
1268  Assert(found == IsUnderPostmaster);
1269  if (!found)
1270  {
1271  int i;
1272 
1274  requestSize = mul_size((Size) max_table_size,
1276  RWConflictPool->element = ShmemAlloc(requestSize);
1277  /* Add all elements to available list, clean. */
1278  memset(RWConflictPool->element, 0, requestSize);
1279  for (i = 0; i < max_table_size; i++)
1280  {
1282  &(RWConflictPool->element[i].outLink));
1283  }
1284  }
1285 
1286  /*
1287  * Create or attach to the header for the list of finished serializable
1288  * transactions.
1289  */
1291  ShmemInitStruct("FinishedSerializableTransactions",
1292  sizeof(SHM_QUEUE),
1293  &found);
1294  Assert(found == IsUnderPostmaster);
1295  if (!found)
1297 
1298  /*
1299  * Initialize the SLRU storage for old committed serializable
1300  * transactions.
1301  */
1302  OldSerXidInit();
1303 }
TransactionId finishedBefore
#define PredXactListDataSize
struct SERIALIZABLEXID SERIALIZABLEXID
static HTAB * PredicateLockTargetHash
Definition: predicate.c:387
#define HASH_ELEM
Definition: hsearch.h:87
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:251
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
struct SERIALIZABLEXIDTAG SERIALIZABLEXIDTAG
struct PREDICATELOCKTARGET PREDICATELOCKTARGET
Size entrysize
Definition: hsearch.h:73
static uint32 predicatelock_hash(const void *key, Size keysize)
Definition: predicate.c:1371
static HTAB * SerializableXidHash
Definition: predicate.c:386
#define MemSet(start, val, len)
Definition: c.h:858
static void OldSerXidInit(void)
Definition: predicate.c:798
void * ShmemAlloc(Size size)
Definition: shmem.c:157
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
#define HASH_PARTITION
Definition: hsearch.h:83
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
SHM_QUEUE possibleUnsafeConflicts
static HTAB * PredicateLockHash
Definition: predicate.c:388
int max_prepared_xacts
Definition: twophase.c:117
static RWConflictPoolHeader RWConflictPool
Definition: predicate.c:380
struct PREDICATELOCK PREDICATELOCK
long num_partitions
Definition: hsearch.h:67
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
struct PREDICATELOCKTAG PREDICATELOCKTAG
int MaxBackends
Definition: globals.c:127
#define RWConflictDataSize
VirtualTransactionId vxid
bool IsUnderPostmaster
Definition: globals.c:101
#define InvalidTransactionId
Definition: transam.h:31
SerCommitSeqNo lastCommitBeforeSnapshot
SerCommitSeqNo commitSeqNo
#define RWConflictPoolHeaderDataSize
SerCommitSeqNo HavePartialClearedThrough
#define HASH_BLOBS
Definition: hsearch.h:88
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
Size keysize
Definition: hsearch.h:72
union SERIALIZABLEXACT::@100 SeqNo
#define Assert(condition)
Definition: c.h:676
#define SetInvalidVirtualTransactionId(vxid)
Definition: lock.h:77
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
size_t Size
Definition: c.h:356
SerCommitSeqNo LastSxactCommitSeqNo
SERIALIZABLEXACT * OldCommittedSxact
#define HASH_FIXED_SIZE
Definition: hsearch.h:96
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:352
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int i
static const PREDICATELOCKTARGETTAG ScratchTargetTag
Definition: predicate.c:396
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:317
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:389
static uint32 ScratchTargetTagHash
Definition: predicate.c:397
static LWLock * ScratchPartitionLock
Definition: predicate.c:398
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:564
PredXactListElement element
#define PredXactListElementDataSize
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
bool PageIsPredicateLocked ( Relation  relation,
BlockNumber  blkno 
)

Definition at line 1927 of file predicate.c.

References RelFileNode::dbNode, HASH_FIND, hash_search_with_hash_value(), LW_SHARED, LWLockAcquire(), LWLockRelease(), NULL, PredicateLockHashPartitionLock, PredicateLockTargetTagHashCode, RelationData::rd_id, RelationData::rd_node, and SET_PREDICATELOCKTARGETTAG_PAGE.

1928 {
1929  PREDICATELOCKTARGETTAG targettag;
1930  uint32 targettaghash;
1931  LWLock *partitionLock;
1932  PREDICATELOCKTARGET *target;
1933 
1935  relation->rd_node.dbNode,
1936  relation->rd_id,
1937  blkno);
1938 
1939  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1940  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1941  LWLockAcquire(partitionLock, LW_SHARED);
1942  target = (PREDICATELOCKTARGET *)
1944  &targettag, targettaghash,
1945  HASH_FIND, NULL);
1946  LWLockRelease(partitionLock);
1947 
1948  return (target != NULL);
1949 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:387
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
unsigned int uint32
Definition: c.h:268
Oid rd_id
Definition: rel.h:116
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4872 of file predicate.c.

References Assert, hash_destroy(), InvalidSerializableXact, MyXactDidWrite, NULL, SERIALIZABLEXACT::pid, and SxactIsPrepared.

Referenced by PrepareTransaction().

4873 {
4875  return;
4876 
4878 
4879  MySerializableXact->pid = 0;
4880 
4883 
4885  MyXactDidWrite = false;
4886 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:810
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
#define InvalidSerializableXact
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
static bool MyXactDidWrite
Definition: predicate.c:412
void PreCommit_CheckForSerializationFailure ( void  )

Definition at line 4710 of file predicate.c.

References Assert, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, SERIALIZABLEXACT::flags, SERIALIZABLEXACT::inConflicts, RWConflictData::inLink, InvalidSerializableXact, IsolationIsSerializable, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), offsetof, SERIALIZABLEXACT::prepareSeqNo, SHMQueueNext(), SXACT_FLAG_DOOMED, SXACT_FLAG_PREPARED, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, and RWConflictData::sxactOut.

Referenced by CommitTransaction(), and PrepareTransaction().

4711 {
4712  RWConflict nearConflict;
4713 
4715  return;
4716 
4718 
4719  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4720 
4721  /* Check if someone else has already decided that we need to die */
4723  {
4724  LWLockRelease(SerializableXactHashLock);
4725  ereport(ERROR,
4726  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4727  errmsg("could not serialize access due to read/write dependencies among transactions"),
4728  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4729  errhint("The transaction might succeed if retried.")));
4730  }
4731 
4732  nearConflict = (RWConflict)
4735  offsetof(RWConflictData, inLink));
4736  while (nearConflict)
4737  {
4738  if (!SxactIsCommitted(nearConflict->sxactOut)
4739  && !SxactIsDoomed(nearConflict->sxactOut))
4740  {
4741  RWConflict farConflict;
4742 
4743  farConflict = (RWConflict)
4744  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4745  &nearConflict->sxactOut->inConflicts,
4746  offsetof(RWConflictData, inLink));
4747  while (farConflict)
4748  {
4749  if (farConflict->sxactOut == MySerializableXact
4750  || (!SxactIsCommitted(farConflict->sxactOut)
4751  && !SxactIsReadOnly(farConflict->sxactOut)
4752  && !SxactIsDoomed(farConflict->sxactOut)))
4753  {
4754  /*
4755  * Normally, we kill the pivot transaction to make sure we
4756  * make progress if the failing transaction is retried.
4757  * However, we can't kill it if it's already prepared, so
4758  * in that case we commit suicide instead.
4759  */
4760  if (SxactIsPrepared(nearConflict->sxactOut))
4761  {
4762  LWLockRelease(SerializableXactHashLock);
4763  ereport(ERROR,
4764  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4765  errmsg("could not serialize access due to read/write dependencies among transactions"),
4766  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4767  errhint("The transaction might succeed if retried.")));
4768  }
4769  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4770  break;
4771  }
4772  farConflict = (RWConflict)
4773  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4774  &farConflict->inLink,
4775  offsetof(RWConflictData, inLink));
4776  }
4777  }
4778 
4779  nearConflict = (RWConflict)
4781  &nearConflict->inLink,
4782  offsetof(RWConflictData, inLink));
4783  }
4784 
4787 
4788  LWLockRelease(SerializableXactHashLock);
4789 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
int errhint(const char *fmt,...)
Definition: elog.c:987
static PredXactList PredXact
Definition: predicate.c:374
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
#define InvalidSerializableXact
#define SXACT_FLAG_PREPARED
#define ereport(elevel, rest)
Definition: elog.h:122
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define SXACT_FLAG_DOOMED
#define Assert(condition)
Definition: c.h:676
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
void predicatelock_twophase_recover ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4921 of file predicate.c.

References Assert, VirtualTransactionId::backendId, SERIALIZABLEXACT::commitSeqNo, CreatePredicateLock(), CreatePredXact(), TwoPhasePredicateRecord::data, ereport, errcode(), errmsg(), ERROR, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, HASH_ENTER, HASH_FIND, hash_search(), SERIALIZABLEXACT::inConflicts, InvalidBackendId, InvalidSerCommitSeqNo, InvalidSerializableXact, InvalidTransactionId, SERIALIZABLEXACT::lastCommitBeforeSnapshot, VirtualTransactionId::localTransactionId, TwoPhasePredicateRecord::lockRecord, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), max_prepared_xacts, MaxBackends, SERIALIZABLEXID::myXact, NULL, OldSerXidSetActiveSerXmin(), SERIALIZABLEXACT::outConflicts, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, SERIALIZABLEXACT::prepareSeqNo, RecoverySerCommitSeqNo, SERIALIZABLEXACT::SeqNo, SHMQueueElemInit(), SHMQueueInit(), SXACT_FLAG_SUMMARY_CONFLICT_IN, SXACT_FLAG_SUMMARY_CONFLICT_OUT, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactIsPrepared, SxactIsReadOnly, TwoPhasePredicateLockRecord::target, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollows(), TransactionIdIsValid, TWOPHASEPREDICATERECORD_LOCK, TWOPHASEPREDICATERECORD_XACT, TwoPhasePredicateRecord::type, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, TwoPhasePredicateRecord::xactRecord, SERIALIZABLEXIDTAG::xid, SERIALIZABLEXACT::xmin, and TwoPhasePredicateXactRecord::xmin.

4923 {
4924  TwoPhasePredicateRecord *record;
4925 
4926  Assert(len == sizeof(TwoPhasePredicateRecord));
4927 
4928  record = (TwoPhasePredicateRecord *) recdata;
4929 
4930  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4931  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4932 
4933  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4934  {
4935  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4936  TwoPhasePredicateXactRecord *xactRecord;
4937  SERIALIZABLEXACT *sxact;
4938  SERIALIZABLEXID *sxid;
4939  SERIALIZABLEXIDTAG sxidtag;
4940  bool found;
4941 
4942  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4943 
4944  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4945  sxact = CreatePredXact();
4946  if (!sxact)
4947  ereport(ERROR,
4948  (errcode(ERRCODE_OUT_OF_MEMORY),
4949  errmsg("out of shared memory")));
4950 
4951  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
4952  sxact->vxid.backendId = InvalidBackendId;
4954  sxact->pid = 0;
4955 
4956  /* a prepared xact hasn't committed yet */
4960 
4962 
4963  /*
4964  * Don't need to track this; no transactions running at the time the
4965  * recovered xact started are still active, except possibly other
4966  * prepared xacts and we don't care whether those are RO_SAFE or not.
4967  */
4969 
4970  SHMQueueInit(&(sxact->predicateLocks));
4971  SHMQueueElemInit(&(sxact->finishedLink));
4972 
4973  sxact->topXid = xid;
4974  sxact->xmin = xactRecord->xmin;
4975  sxact->flags = xactRecord->flags;
4976  Assert(SxactIsPrepared(sxact));
4977  if (!SxactIsReadOnly(sxact))
4978  {
4982  }
4983 
4984  /*
4985  * We don't know whether the transaction had any conflicts or not, so
4986  * we'll conservatively assume that it had both a conflict in and a
4987  * conflict out, and represent that with the summary conflict flags.
4988  */
4989  SHMQueueInit(&(sxact->outConflicts));
4990  SHMQueueInit(&(sxact->inConflicts));
4993 
4994  /* Register the transaction's xid */
4995  sxidtag.xid = xid;
4997  &sxidtag,
4998  HASH_ENTER, &found);
4999  Assert(sxid != NULL);
5000  Assert(!found);
5001  sxid->myXact = (SERIALIZABLEXACT *) sxact;
5002 
5003  /*
5004  * Update global xmin. Note that this is a special case compared to
5005  * registering a normal transaction, because the global xmin might go
5006  * backwards. That's OK, because until recovery is over we're not
5007  * going to complete any transactions or create any non-prepared
5008  * transactions, so there's no danger of throwing away.
5009  */
5012  {
5013  PredXact->SxactGlobalXmin = sxact->xmin;
5016  }
5017  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5018  {
5021  }
5022 
5023  LWLockRelease(SerializableXactHashLock);
5024  }
5025  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5026  {
5027  /* Lock record. Recreate the PREDICATELOCK */
5028  TwoPhasePredicateLockRecord *lockRecord;
5029  SERIALIZABLEXID *sxid;
5030  SERIALIZABLEXACT *sxact;
5031  SERIALIZABLEXIDTAG sxidtag;
5032  uint32 targettaghash;
5033 
5034  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5035  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5036 
5037  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5038  sxidtag.xid = xid;
5039  sxid = (SERIALIZABLEXID *)
5041  LWLockRelease(SerializableXactHashLock);
5042 
5043  Assert(sxid != NULL);
5044  sxact = sxid->myXact;
5045  Assert(sxact != InvalidSerializableXact);
5046 
5047  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5048  }
5049 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2376
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
static PredXactList PredXact
Definition: predicate.c:374
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
TransactionId SxactGlobalXmin
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * SerializableXidHash
Definition: predicate.c:386
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
TwoPhasePredicateRecordType type
LocalTransactionId localTransactionId
Definition: lock.h:66
PREDICATELOCKTARGETTAG target
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
TwoPhasePredicateXactRecord xactRecord
#define InvalidSerializableXact
int MaxBackends
Definition: globals.c:127
VirtualTransactionId vxid
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:268
uint32 LocalTransactionId
Definition: c.h:399
SerCommitSeqNo lastCommitBeforeSnapshot
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
#define InvalidBackendId
Definition: backendid.h:23
union SERIALIZABLEXACT::@100 SeqNo
#define RecoverySerCommitSeqNo
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
BackendId backendId
Definition: lock.h:65
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:990
SerCommitSeqNo prepareSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
union TwoPhasePredicateRecord::@101 data
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TwoPhasePredicateLockRecord lockRecord
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:564
void PredicateLockPage ( Relation  relation,
BlockNumber  blkno,
Snapshot  snapshot 
)

Definition at line 2519 of file predicate.c.

References RelFileNode::dbNode, PredicateLockAcquire(), RelationData::rd_id, RelationData::rd_node, SerializationNeededForRead(), and SET_PREDICATELOCKTARGETTAG_PAGE.

Referenced by _bt_endpoint(), _bt_first(), _bt_readnextpage(), and IndexOnlyNext().

2520 {
2522 
2523  if (!SerializationNeededForRead(relation, snapshot))
2524  return;
2525 
2527  relation->rd_node.dbNode,
2528  relation->rd_id,
2529  blkno);
2530  PredicateLockAcquire(&tag);
2531 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2437
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:498
void PredicateLockPageCombine ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3194 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead().

3196 {
3197  /*
3198  * Page combines differ from page splits in that we ought to be able to
3199  * remove the locks on the old page after transferring them to the new
3200  * page, instead of duplicating them. However, because we can't edit other
3201  * backends' local lock tables, removing the old lock would leave them
3202  * with an entry in their LocalPredicateLockHash for a lock they're not
3203  * holding, which isn't acceptable. So we wind up having to do the same
3204  * work as a page split, acquiring a lock on the new page and keeping the
3205  * old page locked too. That can lead to some false positives, but should
3206  * be rare in practice.
3207  */
3208  PredicateLockPageSplit(relation, oldblkno, newblkno);
3209 }
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3109
void PredicateLockPageSplit ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3109 of file predicate.c.

References Assert, BlockNumberIsValid, RelFileNode::dbNode, GetParentPredicateLockTag(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PredicateLockingNeededForRelation(), RelationData::rd_id, RelationData::rd_node, SET_PREDICATELOCKTARGETTAG_PAGE, success, PredXactListData::SxactGlobalXmin, TransactionIdIsValid, and TransferPredicateLocksToNewTarget().

Referenced by _bt_insertonpg(), and PredicateLockPageCombine().

3111 {
3112  PREDICATELOCKTARGETTAG oldtargettag;
3113  PREDICATELOCKTARGETTAG newtargettag;
3114  bool success;
3115 
3116  /*
3117  * Bail out quickly if there are no serializable transactions running.
3118  *
3119  * It's safe to do this check without taking any additional locks. Even if
3120  * a serializable transaction starts concurrently, we know it can't take
3121  * any SIREAD locks on the page being split because the caller is holding
3122  * the associated buffer page lock. Memory reordering isn't an issue; the
3123  * memory barrier in the LWLock acquisition guarantees that this read
3124  * occurs while the buffer page lock is held.
3125  */
3127  return;
3128 
3129  if (!PredicateLockingNeededForRelation(relation))
3130  return;
3131 
3132  Assert(oldblkno != newblkno);
3133  Assert(BlockNumberIsValid(oldblkno));
3134  Assert(BlockNumberIsValid(newblkno));
3135 
3136  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3137  relation->rd_node.dbNode,
3138  relation->rd_id,
3139  oldblkno);
3140  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3141  relation->rd_node.dbNode,
3142  relation->rd_id,
3143  newblkno);
3144 
3145  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
3146 
3147  /*
3148  * Try copying the locks over to the new page's tag, creating it if
3149  * necessary.
3150  */
3151  success = TransferPredicateLocksToNewTarget(oldtargettag,
3152  newtargettag,
3153  false);
3154 
3155  if (!success)
3156  {
3157  /*
3158  * No more predicate lock entries are available. Failure isn't an
3159  * option here, so promote the page lock to a relation lock.
3160  */
3161 
3162  /* Get the parent relation lock's lock tag */
3163  success = GetParentPredicateLockTag(&oldtargettag,
3164  &newtargettag);
3165  Assert(success);
3166 
3167  /*
3168  * Move the locks to the parent. This shouldn't fail.
3169  *
3170  * Note that here we are removing locks held by other backends,
3171  * leading to a possible inconsistency in their local lock hash table.
3172  * This is OK because we're replacing it with a lock that covers the
3173  * old one.
3174  */
3175  success = TransferPredicateLocksToNewTarget(oldtargettag,
3176  newtargettag,
3177  true);
3178  Assert(success);
3179  }
3180 
3181  LWLockRelease(SerializablePredicateLockListLock);
3182 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:479
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2676
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static bool success
Definition: pg_basebackup.c:96
Oid rd_id
Definition: rel.h:116
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1991
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:85
#define Assert(condition)
Definition: c.h:676
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void PredicateLockRelation ( Relation  relation,
Snapshot  snapshot 
)

Definition at line 2496 of file predicate.c.

References RelFileNode::dbNode, PredicateLockAcquire(), RelationData::rd_id, RelationData::rd_node, SerializationNeededForRead(), and SET_PREDICATELOCKTARGETTAG_RELATION.

Referenced by _bt_endpoint(), _bt_first(), heap_beginscan_internal(), and index_beginscan_internal().

2497 {
2499 
2500  if (!SerializationNeededForRead(relation, snapshot))
2501  return;
2502 
2504  relation->rd_node.dbNode,
2505  relation->rd_id);
2506  PredicateLockAcquire(&tag);
2507 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2437
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:498
Size PredicateLockShmemSize ( void  )

Definition at line 1309 of file predicate.c.

References add_size(), hash_estimate_size(), max_prepared_xacts, MaxBackends, mul_size(), NPREDICATELOCKTARGETENTS, NUM_OLDSERXID_BUFFERS, PredXactListDataSize, PredXactListElementDataSize, RWConflictDataSize, RWConflictPoolHeaderDataSize, and SimpleLruShmemSize().

Referenced by CreateSharedMemoryAndSemaphores().

1310 {
1311  Size size = 0;
1312  long max_table_size;
1313 
1314  /* predicate lock target hash table */
1315  max_table_size = NPREDICATELOCKTARGETENTS();
1316  size = add_size(size, hash_estimate_size(max_table_size,
1317  sizeof(PREDICATELOCKTARGET)));
1318 
1319  /* predicate lock hash table */
1320  max_table_size *= 2;
1321  size = add_size(size, hash_estimate_size(max_table_size,
1322  sizeof(PREDICATELOCK)));
1323 
1324  /*
1325  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1326  * margin.
1327  */
1328  size = add_size(size, size / 10);
1329 
1330  /* transaction list */
1331  max_table_size = MaxBackends + max_prepared_xacts;
1332  max_table_size *= 10;
1333  size = add_size(size, PredXactListDataSize);
1334  size = add_size(size, mul_size((Size) max_table_size,
1336 
1337  /* transaction xid table */
1338  size = add_size(size, hash_estimate_size(max_table_size,
1339  sizeof(SERIALIZABLEXID)));
1340 
1341  /* rw-conflict pool */
1342  max_table_size *= 5;
1343  size = add_size(size, RWConflictPoolHeaderDataSize);
1344  size = add_size(size, mul_size((Size) max_table_size,
1346 
1347  /* Head for list of finished serializable transactions. */
1348  size = add_size(size, sizeof(SHM_QUEUE));
1349 
1350  /* Shared memory structures for SLRU tracking of old committed xids. */
1351  size = add_size(size, sizeof(OldSerXidControlData));
1353 
1354  return size;
1355 }
#define PredXactListDataSize
#define NPREDICATELOCKTARGETENTS()
Definition: predicate.c:251
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:31
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:145
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:127
#define RWConflictDataSize
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:728
#define RWConflictPoolHeaderDataSize
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:356
#define PredXactListElementDataSize
void PredicateLockTuple ( Relation  relation,
HeapTuple  tuple,
Snapshot  snapshot 
)

Definition at line 2541 of file predicate.c.

References RelFileNode::dbNode, GetTopTransactionIdIfAny(), HeapTupleHeaderGetXmin, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, NULL, PredicateLockAcquire(), PredicateLockExists(), RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, SerializationNeededForRead(), SET_PREDICATELOCKTARGETTAG_RELATION, SET_PREDICATELOCKTARGETTAG_TUPLE, SubTransGetTopmostTransaction(), HeapTupleData::t_data, HeapTupleData::t_self, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and TransactionXmin.

Referenced by bitgetpage(), heap_fetch(), and heap_hot_search_buffer().

2542 {
2544  ItemPointer tid;
2545  TransactionId targetxmin;
2546 
2547  if (!SerializationNeededForRead(relation, snapshot))
2548  return;
2549 
2550  /*
2551  * If it's a heap tuple, return if this xact wrote it.
2552  */
2553  if (relation->rd_index == NULL)
2554  {
2555  TransactionId myxid;
2556 
2557  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2558 
2559  myxid = GetTopTransactionIdIfAny();
2560  if (TransactionIdIsValid(myxid))
2561  {
2563  {
2564  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2565 
2566  if (TransactionIdEquals(xid, myxid))
2567  {
2568  /* We wrote it; we already have a write lock. */
2569  return;
2570  }
2571  }
2572  }
2573  }
2574 
2575  /*
2576  * Do quick-but-not-definitive test for a relation lock first. This will
2577  * never cause a return when the relation is *not* locked, but will
2578  * occasionally let the check continue when there really *is* a relation
2579  * level lock.
2580  */
2582  relation->rd_node.dbNode,
2583  relation->rd_id);
2584  if (PredicateLockExists(&tag))
2585  return;
2586 
2587  tid = &(tuple->t_self);
2589  relation->rd_node.dbNode,
2590  relation->rd_id,
2593  PredicateLockAcquire(&tag);
2594 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:397
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1964
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
TransactionId TransactionXmin
Definition: snapmgr.c:164
HeapTupleHeader t_data
Definition: htup.h:67
Form_pg_index rd_index
Definition: rel.h:159
ItemPointerData t_self
Definition: htup.h:65
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2437
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define ItemPointerGetOffsetNumber(pointer)
Definition: itemptr.h:95
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:498
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4894 of file predicate.c.

References HASH_FIND, hash_search(), LW_SHARED, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXID::myXact, MyXactDidWrite, NULL, ReleasePredicateLocks(), and SERIALIZABLEXIDTAG::xid.

Referenced by FinishPreparedTransaction().

4895 {
4896  SERIALIZABLEXID *sxid;
4897  SERIALIZABLEXIDTAG sxidtag;
4898 
4899  sxidtag.xid = xid;
4900 
4901  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4902  sxid = (SERIALIZABLEXID *)
4904  LWLockRelease(SerializableXactHashLock);
4905 
4906  /* xid will not be found if it wasn't a serializable transaction */
4907  if (sxid == NULL)
4908  return;
4909 
4910  /* Release its locks */
4911  MySerializableXact = sxid->myXact;
4912  MyXactDidWrite = true; /* conservatively assume that we wrote
4913  * something */
4914  ReleasePredicateLocks(isCommit);
4915 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
static HTAB * SerializableXidHash
Definition: predicate.c:386
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3266
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static bool MyXactDidWrite
Definition: predicate.c:412
void RegisterPredicateLockingXid ( TransactionId  xid)

Definition at line 1878 of file predicate.c.

References Assert, HASH_ENTER, hash_search(), InvalidSerializableXact, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MySerializableXact, SERIALIZABLEXID::myXact, SERIALIZABLEXACT::topXid, TransactionIdIsValid, and SERIALIZABLEXIDTAG::xid.

Referenced by AssignTransactionId().

1879 {
1880  SERIALIZABLEXIDTAG sxidtag;
1881  SERIALIZABLEXID *sxid;
1882  bool found;
1883 
1884  /*
1885  * If we're not tracking predicate lock data for this transaction, we
1886  * should ignore the request and return quickly.
1887  */
1889  return;
1890 
1891  /* We should have a valid XID and be at the top level. */
1893 
1894  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1895 
1896  /* This should only be done once per transaction. */
1898 
1899  MySerializableXact->topXid = xid;
1900 
1901  sxidtag.xid = xid;
1903  &sxidtag,
1904  HASH_ENTER, &found);
1905  Assert(!found);
1906 
1907  /* Initialize the structure. */
1908  sxid->myXact = MySerializableXact;
1909  LWLockRelease(SerializableXactHashLock);
1910 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
static HTAB * SerializableXidHash
Definition: predicate.c:386
SERIALIZABLEXACT * myXact
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:676
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void ReleasePredicateLocks ( bool  isCommit)

Definition at line 3266 of file predicate.c.

References Assert, PredXactListData::CanPartialClearThrough, ClearOldPredicateLocks(), SERIALIZABLEXACT::commitSeqNo, SERIALIZABLEXACT::earliestOutConflictCommit, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FirstNormalSerCommitSeqNo, SERIALIZABLEXACT::flags, FlagSxactUnsafe(), hash_destroy(), SERIALIZABLEXACT::inConflicts, RWConflictData::inLink, InvalidSerializableXact, IsolationIsSerializable, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyXactDidWrite, VariableCacheData::nextXid, NULL, offsetof, SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::prepareSeqNo, ProcSendSignal(), ReleaseOneSerializableXact(), ReleaseRWConflict(), SERIALIZABLEXACT::SeqNo, SetNewSxactGlobalXmin(), ShmemVariableCache, SHMQueueEmpty(), SHMQueueInsertBefore(), SHMQueueNext(), SXACT_FLAG_COMMITTED, SXACT_FLAG_CONFLICT_OUT, SXACT_FLAG_DOOMED, SXACT_FLAG_PREPARED, SXACT_FLAG_READ_ONLY, SXACT_FLAG_RO_SAFE, SXACT_FLAG_ROLLED_BACK, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactHasConflictOut, SxactHasSummaryConflictOut, RWConflictData::sxactIn, SxactIsCommitted, SxactIsDeferrableWaiting, SxactIsDoomed, SxactIsOnFinishedList, SxactIsPrepared, SxactIsReadOnly, SxactIsRolledBack, SxactIsROSafe, SxactIsROUnsafe, RWConflictData::sxactOut, TransactionIdEquals, PredXactListData::WritableSxactCount, and SERIALIZABLEXACT::xmin.

Referenced by GetSafeSnapshot(), PredicateLockTwoPhaseFinish(), ResourceOwnerReleaseInternal(), and SerializationNeededForRead().

3267 {
3268  bool needToClear;
3269  RWConflict conflict,
3270  nextConflict,
3271  possibleUnsafeConflict;
3272  SERIALIZABLEXACT *roXact;
3273 
3274  /*
3275  * We can't trust XactReadOnly here, because a transaction which started
3276  * as READ WRITE can show as READ ONLY later, e.g., within
3277  * subtransactions. We want to flag a transaction as READ ONLY if it
3278  * commits without writing so that de facto READ ONLY transactions get the
3279  * benefit of some RO optimizations, so we will use this local variable to
3280  * get some cleanup logic right which is based on whether the transaction
3281  * was declared READ ONLY at the top level.
3282  */
3283  bool topLevelIsDeclaredReadOnly;
3284 
3286  {
3288  return;
3289  }
3290 
3291  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3292 
3293  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3294  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3297 
3298  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3300 
3301  /* We'd better not already be on the cleanup list. */
3303 
3304  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3305 
3306  /*
3307  * We don't hold XidGenLock lock here, assuming that TransactionId is
3308  * atomic!
3309  *
3310  * If this value is changing, we don't care that much whether we get the
3311  * old or new value -- it is just used to determine how far
3312  * GlobalSerializableXmin must advance before this transaction can be
3313  * fully cleaned up. The worst that could happen is we wait for one more
3314  * transaction to complete before freeing some RAM; correctness of visible
3315  * behavior is not affected.
3316  */
3318 
3319  /*
3320  * If it's not a commit it's a rollback, and we can clear our locks
3321  * immediately.
3322  */
3323  if (isCommit)
3324  {
3327  /* Recognize implicit read-only transaction (commit without write). */
3328  if (!MyXactDidWrite)
3330  }
3331  else
3332  {
3333  /*
3334  * The DOOMED flag indicates that we intend to roll back this
3335  * transaction and so it should not cause serialization failures for
3336  * other transactions that conflict with it. Note that this flag might
3337  * already be set, if another backend marked this transaction for
3338  * abort.
3339  *
3340  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3341  * has been called, and so the SerializableXact is eligible for
3342  * cleanup. This means it should not be considered when calculating
3343  * SxactGlobalXmin.
3344  */
3347 
3348  /*
3349  * If the transaction was previously prepared, but is now failing due
3350  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3351  * prepare, clear the prepared flag. This simplifies conflict
3352  * checking.
3353  */
3355  }
3356 
3357  if (!topLevelIsDeclaredReadOnly)
3358  {
3360  if (--(PredXact->WritableSxactCount) == 0)
3361  {
3362  /*
3363  * Release predicate locks and rw-conflicts in for all committed
3364  * transactions. There are no longer any transactions which might
3365  * conflict with the locks and no chance for new transactions to
3366  * overlap. Similarly, existing conflicts in can't cause pivots,
3367  * and any conflicts in which could have completed a dangerous
3368  * structure would already have caused a rollback, so any
3369  * remaining ones must be benign.
3370  */
3372  }
3373  }
3374  else
3375  {
3376  /*
3377  * Read-only transactions: clear the list of transactions that might
3378  * make us unsafe. Note that we use 'inLink' for the iteration as
3379  * opposed to 'outLink' for the r/w xacts.
3380  */
3381  possibleUnsafeConflict = (RWConflict)
3384  offsetof(RWConflictData, inLink));
3385  while (possibleUnsafeConflict)
3386  {
3387  nextConflict = (RWConflict)
3389  &possibleUnsafeConflict->inLink,
3390  offsetof(RWConflictData, inLink));
3391 
3392  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3393  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3394 
3395  ReleaseRWConflict(possibleUnsafeConflict);
3396 
3397  possibleUnsafeConflict = nextConflict;
3398  }
3399  }
3400 
3401  /* Check for conflict out to old committed transactions. */
3402  if (isCommit
3405  {
3406  /*
3407  * we don't know which old committed transaction we conflicted with,
3408  * so be conservative and use FirstNormalSerCommitSeqNo here
3409  */
3413  }
3414 
3415  /*
3416  * Release all outConflicts to committed transactions. If we're rolling
3417  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3418  * previously committed transactions.
3419  */
3420  conflict = (RWConflict)
3423  offsetof(RWConflictData, outLink));
3424  while (conflict)
3425  {
3426  nextConflict = (RWConflict)
3428  &conflict->outLink,
3429  offsetof(RWConflictData, outLink));
3430 
3431  if (isCommit
3433  && SxactIsCommitted(conflict->sxactIn))
3434  {
3439  }
3440 
3441  if (!isCommit
3442  || SxactIsCommitted(conflict->sxactIn)
3444  ReleaseRWConflict(conflict);
3445 
3446  conflict = nextConflict;
3447  }
3448 
3449  /*
3450  * Release all inConflicts from committed and read-only transactions. If
3451  * we're rolling back, clear them all.
3452  */
3453  conflict = (RWConflict)
3456  offsetof(RWConflictData, inLink));
3457  while (conflict)
3458  {
3459  nextConflict = (RWConflict)
3461  &conflict->inLink,
3462  offsetof(RWConflictData, inLink));
3463 
3464  if (!isCommit
3465  || SxactIsCommitted(conflict->sxactOut)
3466  || SxactIsReadOnly(conflict->sxactOut))
3467  ReleaseRWConflict(conflict);
3468 
3469  conflict = nextConflict;
3470  }
3471 
3472  if (!topLevelIsDeclaredReadOnly)
3473  {
3474  /*
3475  * Remove ourselves from the list of possible conflicts for concurrent
3476  * READ ONLY transactions, flagging them as unsafe if we have a
3477  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3478  * up if they are known safe or known unsafe.
3479  */
3480  possibleUnsafeConflict = (RWConflict)
3483  offsetof(RWConflictData, outLink));
3484  while (possibleUnsafeConflict)
3485  {
3486  nextConflict = (RWConflict)
3488  &possibleUnsafeConflict->outLink,
3489  offsetof(RWConflictData, outLink));
3490 
3491  roXact = possibleUnsafeConflict->sxactIn;
3492  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3493  Assert(SxactIsReadOnly(roXact));
3494 
3495  /* Mark conflicted if necessary. */
3496  if (isCommit
3497  && MyXactDidWrite
3500  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3501  {
3502  /*
3503  * This releases possibleUnsafeConflict (as well as all other
3504  * possible conflicts for roXact)
3505  */
3506  FlagSxactUnsafe(roXact);
3507  }
3508  else
3509  {
3510  ReleaseRWConflict(possibleUnsafeConflict);
3511 
3512  /*
3513  * If we were the last possible conflict, flag it safe. The
3514  * transaction can now safely release its predicate locks (but
3515  * that transaction's backend has to do that itself).
3516  */
3517  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3518  roXact->flags |= SXACT_FLAG_RO_SAFE;
3519  }
3520 
3521  /*
3522  * Wake up the process for a waiting DEFERRABLE transaction if we
3523  * now know it's either safe or conflicted.
3524  */
3525  if (SxactIsDeferrableWaiting(roXact) &&
3526  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3527  ProcSendSignal(roXact->pid);
3528 
3529  possibleUnsafeConflict = nextConflict;
3530  }
3531  }
3532 
3533  /*
3534  * Check whether it's time to clean up old transactions. This can only be
3535  * done when the last serializable transaction with the oldest xmin among
3536  * serializable transactions completes. We then find the "new oldest"
3537  * xmin and purge any transactions which finished before this transaction
3538  * was launched.
3539  */
3540  needToClear = false;
3542  {
3544  if (--(PredXact->SxactGlobalXminCount) == 0)
3545  {
3547  needToClear = true;
3548  }
3549  }
3550 
3551  LWLockRelease(SerializableXactHashLock);
3552 
3553  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3554 
3555  /* Add this to the list of transactions to check for later cleanup. */
3556  if (isCommit)
3559 
3560  if (!isCommit)
3562 
3563  LWLockRelease(SerializableFinishedListLock);
3564 
3565  if (needToClear)
3567 
3569  MyXactDidWrite = false;
3570 
3571  /* Delete per-transaction lock table */
3573  {
3576  }
3577 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
TransactionId finishedBefore
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:810
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
struct RWConflictData * RWConflict
static void ClearOldPredicateLocks(void)
Definition: predicate.c:3584
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:726
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define SXACT_FLAG_COMMITTED
#define FirstNormalSerCommitSeqNo
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
#define SxactIsOnFinishedList(sxact)
Definition: predicate.c:254
static void FlagSxactUnsafe(SERIALIZABLEXACT *sxact)
Definition: predicate.c:734
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
SERIALIZABLEXACT * sxactIn
void ProcSendSignal(int pid)
Definition: proc.c:1777
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define SxactIsRolledBack(sxact)
Definition: predicate.c:266
SHM_QUEUE possibleUnsafeConflicts
#define SXACT_FLAG_RO_SAFE
#define InvalidSerializableXact
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define SXACT_FLAG_CONFLICT_OUT
#define SXACT_FLAG_PREPARED
SerCommitSeqNo lastCommitBeforeSnapshot
#define SxactIsROSafe(sxact)
Definition: predicate.c:278
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:270
SerCommitSeqNo commitSeqNo
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
SerCommitSeqNo CanPartialClearThrough
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
SerCommitSeqNo earliestOutConflictCommit
union SERIALIZABLEXACT::@100 SeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:276
#define NULL
Definition: c.h:229
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3741
#define Assert(condition)
Definition: c.h:676
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:277
#define SXACT_FLAG_ROLLED_BACK
SerCommitSeqNo prepareSeqNo
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define IsolationIsSerializable()
Definition: xact.h:44
#define SXACT_FLAG_READ_ONLY
static bool MyXactDidWrite
Definition: predicate.c:412
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:279
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:389
static void SetNewSxactGlobalXmin(void)
Definition: predicate.c:3216
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
void SetSerializableTransactionSnapshot ( Snapshot  snapshot,
VirtualTransactionId sourcevxid,
int  sourcepid 
)

Definition at line 1674 of file predicate.c.

References Assert, ereport, errcode(), errmsg(), ERROR, GetSerializableTransactionSnapshotInt(), IsolationIsSerializable, XactDeferrable, and XactReadOnly.

Referenced by SetTransactionSnapshot().

1677 {
1679 
1680  /*
1681  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1682  * import snapshots, since there's no way to wait for a safe snapshot when
1683  * we're using the snap we're told to. (XXX instead of throwing an error,
1684  * we could just ignore the XactDeferrable flag?)
1685  */
1687  ereport(ERROR,
1688  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1689  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1690 
1691  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1692  sourcepid);
1693 }
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:575
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1705
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:676
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3088 of file predicate.c.

References DropAllPredicateLocksFromTable().

Referenced by ATRewriteTable(), cluster_rel(), index_drop(), and reindex_index().

3089 {
3090  DropAllPredicateLocksFromTable(relation, true);
3091 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2892

Variable Documentation

int max_predicate_locks_per_page

Definition at line 363 of file predicate.c.

Referenced by MaxPredicateChildLocks().

int max_predicate_locks_per_relation

Definition at line 362 of file predicate.c.

Referenced by MaxPredicateChildLocks().

int max_predicate_locks_per_xact

Definition at line 361 of file predicate.c.

Referenced by GetSerializableTransactionSnapshotInt(), and MaxPredicateChildLocks().