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 4790 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().

4791 {
4792  PREDICATELOCK *predlock;
4793  SERIALIZABLEXACT *sxact;
4794  TwoPhasePredicateRecord record;
4795  TwoPhasePredicateXactRecord *xactRecord;
4796  TwoPhasePredicateLockRecord *lockRecord;
4797 
4798  sxact = MySerializableXact;
4799  xactRecord = &(record.data.xactRecord);
4800  lockRecord = &(record.data.lockRecord);
4801 
4803  return;
4804 
4805  /* Generate an xact record for our SERIALIZABLEXACT */
4807  xactRecord->xmin = MySerializableXact->xmin;
4808  xactRecord->flags = MySerializableXact->flags;
4809 
4810  /*
4811  * Note that we don't include the list of conflicts in our out in the
4812  * statefile, because new conflicts can be added even after the
4813  * transaction prepares. We'll just make a conservative assumption during
4814  * recovery instead.
4815  */
4816 
4818  &record, sizeof(record));
4819 
4820  /*
4821  * Generate a lock record for each lock.
4822  *
4823  * To do this, we need to walk the predicate lock list in our sxact rather
4824  * than using the local predicate lock table because the latter is not
4825  * guaranteed to be accurate.
4826  */
4827  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4828 
4829  predlock = (PREDICATELOCK *)
4830  SHMQueueNext(&(sxact->predicateLocks),
4831  &(sxact->predicateLocks),
4832  offsetof(PREDICATELOCK, xactLink));
4833 
4834  while (predlock != NULL)
4835  {
4837  lockRecord->target = predlock->tag.myTarget->tag;
4838 
4840  &record, sizeof(record));
4841 
4842  predlock = (PREDICATELOCK *)
4843  SHMQueueNext(&(sxact->predicateLocks),
4844  &(predlock->xactLink),
4845  offsetof(PREDICATELOCK, xactLink));
4846  }
4847 
4848  LWLockRelease(SerializablePredicateLockListLock);
4849 }
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 4311 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().

4313 {
4314  PREDICATELOCKTARGETTAG targettag;
4315 
4316  if (!SerializationNeededForWrite(relation))
4317  return;
4318 
4319  /* Check if someone else has already decided that we need to die */
4321  ereport(ERROR,
4322  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4323  errmsg("could not serialize access due to read/write dependencies among transactions"),
4324  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict in checking."),
4325  errhint("The transaction might succeed if retried.")));
4326 
4327  /*
4328  * We're doing a write which might cause rw-conflicts now or later.
4329  * Memorize that fact.
4330  */
4331  MyXactDidWrite = true;
4332 
4333  /*
4334  * It is important that we check for locks from the finest granularity to
4335  * the coarsest granularity, so that granularity promotion doesn't cause
4336  * us to miss a lock. The new (coarser) lock will be acquired before the
4337  * old (finer) locks are released.
4338  *
4339  * It is not possible to take and hold a lock across the checks for all
4340  * granularities because each target could be in a separate partition.
4341  */
4342  if (tuple != NULL)
4343  {
4345  relation->rd_node.dbNode,
4346  relation->rd_id,
4347  ItemPointerGetBlockNumber(&(tuple->t_self)),
4348  ItemPointerGetOffsetNumber(&(tuple->t_self)));
4349  CheckTargetForConflictsIn(&targettag);
4350  }
4351 
4352  if (BufferIsValid(buffer))
4353  {
4355  relation->rd_node.dbNode,
4356  relation->rd_id,
4358  CheckTargetForConflictsIn(&targettag);
4359  }
4360 
4362  relation->rd_node.dbNode,
4363  relation->rd_id);
4364  CheckTargetForConflictsIn(&targettag);
4365 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
int errhint(const char *fmt,...)
Definition: elog.c:987
static void CheckTargetForConflictsIn(PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:4133
#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 3930 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().

3933 {
3934  TransactionId xid;
3935  SERIALIZABLEXIDTAG sxidtag;
3936  SERIALIZABLEXID *sxid;
3937  SERIALIZABLEXACT *sxact;
3938  HTSV_Result htsvResult;
3939 
3940  if (!SerializationNeededForRead(relation, snapshot))
3941  return;
3942 
3943  /* Check if someone else has already decided that we need to die */
3945  {
3946  ereport(ERROR,
3947  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
3948  errmsg("could not serialize access due to read/write dependencies among transactions"),
3949  errdetail_internal("Reason code: Canceled on identification as a pivot, during conflict out checking."),
3950  errhint("The transaction might succeed if retried.")));
3951  }
3952 
3953  /*
3954  * Check to see whether the tuple has been written to by a concurrent
3955  * transaction, either to create it not visible to us, or to delete it
3956  * while it is visible to us. The "visible" bool indicates whether the
3957  * tuple is visible to us, while HeapTupleSatisfiesVacuum checks what else
3958  * is going on with it.
3959  */
3960  htsvResult = HeapTupleSatisfiesVacuum(tuple, TransactionXmin, buffer);
3961  switch (htsvResult)
3962  {
3963  case HEAPTUPLE_LIVE:
3964  if (visible)
3965  return;
3966  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3967  break;
3969  if (!visible)
3970  return;
3971  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3972  break;
3974  xid = HeapTupleHeaderGetUpdateXid(tuple->t_data);
3975  break;
3977  xid = HeapTupleHeaderGetXmin(tuple->t_data);
3978  break;
3979  case HEAPTUPLE_DEAD:
3980  return;
3981  default:
3982 
3983  /*
3984  * The only way to get to this default clause is if a new value is
3985  * added to the enum type without adding it to this switch
3986  * statement. That's a bug, so elog.
3987  */
3988  elog(ERROR, "unrecognized return value from HeapTupleSatisfiesVacuum: %u", htsvResult);
3989 
3990  /*
3991  * In spite of having all enum values covered and calling elog on
3992  * this default, some compilers think this is a code path which
3993  * allows xid to be used below without initialization. Silence
3994  * that warning.
3995  */
3996  xid = InvalidTransactionId;
3997  }
4000 
4001  /*
4002  * Find top level xid. Bail out if xid is too early to be a conflict, or
4003  * if it's our own xid.
4004  */
4006  return;
4007  xid = SubTransGetTopmostTransaction(xid);
4009  return;
4011  return;
4012 
4013  /*
4014  * Find sxact or summarized info for the top level xid.
4015  */
4016  sxidtag.xid = xid;
4017  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4018  sxid = (SERIALIZABLEXID *)
4020  if (!sxid)
4021  {
4022  /*
4023  * Transaction not found in "normal" SSI structures. Check whether it
4024  * got pushed out to SLRU storage for "old committed" transactions.
4025  */
4026  SerCommitSeqNo conflictCommitSeqNo;
4027 
4028  conflictCommitSeqNo = OldSerXidGetMinConflictCommitSeqNo(xid);
4029  if (conflictCommitSeqNo != 0)
4030  {
4031  if (conflictCommitSeqNo != InvalidSerCommitSeqNo
4033  || conflictCommitSeqNo
4035  ereport(ERROR,
4036  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4037  errmsg("could not serialize access due to read/write dependencies among transactions"),
4038  errdetail_internal("Reason code: Canceled on conflict out to old pivot %u.", xid),
4039  errhint("The transaction might succeed if retried.")));
4040 
4043  ereport(ERROR,
4044  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4045  errmsg("could not serialize access due to read/write dependencies among transactions"),
4046  errdetail_internal("Reason code: Canceled on identification as a pivot, with conflict out to old committed transaction %u.", xid),
4047  errhint("The transaction might succeed if retried.")));
4048 
4050  }
4051 
4052  /* It's not serializable or otherwise not important. */
4053  LWLockRelease(SerializableXactHashLock);
4054  return;
4055  }
4056  sxact = sxid->myXact;
4057  Assert(TransactionIdEquals(sxact->topXid, xid));
4058  if (sxact == MySerializableXact || SxactIsDoomed(sxact))
4059  {
4060  /* Can't conflict with ourself or a transaction that will roll back. */
4061  LWLockRelease(SerializableXactHashLock);
4062  return;
4063  }
4064 
4065  /*
4066  * We have a conflict out to a transaction which has a conflict out to a
4067  * summarized transaction. That summarized transaction must have
4068  * committed first, and we can't tell when it committed in relation to our
4069  * snapshot acquisition, so something needs to be canceled.
4070  */
4071  if (SxactHasSummaryConflictOut(sxact))
4072  {
4073  if (!SxactIsPrepared(sxact))
4074  {
4075  sxact->flags |= SXACT_FLAG_DOOMED;
4076  LWLockRelease(SerializableXactHashLock);
4077  return;
4078  }
4079  else
4080  {
4081  LWLockRelease(SerializableXactHashLock);
4082  ereport(ERROR,
4083  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4084  errmsg("could not serialize access due to read/write dependencies among transactions"),
4085  errdetail_internal("Reason code: Canceled on conflict out to old pivot."),
4086  errhint("The transaction might succeed if retried.")));
4087  }
4088  }
4089 
4090  /*
4091  * If this is a read-only transaction and the writing transaction has
4092  * committed, and it doesn't have a rw-conflict to a transaction which
4093  * committed before it, no conflict.
4094  */
4096  && SxactIsCommitted(sxact)
4097  && !SxactHasSummaryConflictOut(sxact)
4098  && (!SxactHasConflictOut(sxact)
4100  {
4101  /* Read-only transaction will appear to run first. No conflict. */
4102  LWLockRelease(SerializableXactHashLock);
4103  return;
4104  }
4105 
4106  if (!XidIsConcurrent(xid))
4107  {
4108  /* This write was already in our snapshot; no conflict. */
4109  LWLockRelease(SerializableXactHashLock);
4110  return;
4111  }
4112 
4114  {
4115  /* We don't want duplicate conflict records in the list. */
4116  LWLockRelease(SerializableXactHashLock);
4117  return;
4118  }
4119 
4120  /*
4121  * Flag the conflict. But first, if this conflict creates a dangerous
4122  * structure, ereport an error.
4123  */
4125  LWLockRelease(SerializableXactHashLock);
4126 }
#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:4487
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:3887
#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:885
#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:948
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:675
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 1040 of file predicate.c.

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

Referenced by CheckPointGuts().

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

4396 {
4397  HASH_SEQ_STATUS seqstat;
4398  PREDICATELOCKTARGET *target;
4399  Oid dbId;
4400  Oid heapId;
4401  int i;
4402 
4403  /*
4404  * Bail out quickly if there are no serializable transactions running.
4405  * It's safe to check this without taking locks because the caller is
4406  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4407  * would matter here can be acquired while that is held.
4408  */
4410  return;
4411 
4412  if (!SerializationNeededForWrite(relation))
4413  return;
4414 
4415  /*
4416  * We're doing a write which might cause rw-conflicts now or later.
4417  * Memorize that fact.
4418  */
4419  MyXactDidWrite = true;
4420 
4421  Assert(relation->rd_index == NULL); /* not an index relation */
4422 
4423  dbId = relation->rd_node.dbNode;
4424  heapId = relation->rd_id;
4425 
4426  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4427  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4429  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4430 
4431  /* Scan through target list */
4433 
4434  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4435  {
4436  PREDICATELOCK *predlock;
4437 
4438  /*
4439  * Check whether this is a target which needs attention.
4440  */
4441  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4442  continue; /* wrong relation id */
4443  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4444  continue; /* wrong database id */
4445 
4446  /*
4447  * Loop through locks for this target and flag conflicts.
4448  */
4449  predlock = (PREDICATELOCK *)
4450  SHMQueueNext(&(target->predicateLocks),
4451  &(target->predicateLocks),
4452  offsetof(PREDICATELOCK, targetLink));
4453  while (predlock)
4454  {
4455  PREDICATELOCK *nextpredlock;
4456 
4457  nextpredlock = (PREDICATELOCK *)
4458  SHMQueueNext(&(target->predicateLocks),
4459  &(predlock->targetLink),
4460  offsetof(PREDICATELOCK, targetLink));
4461 
4462  if (predlock->tag.myXact != MySerializableXact
4464  {
4466  }
4467 
4468  predlock = nextpredlock;
4469  }
4470  }
4471 
4472  /* Release locks in reverse order */
4473  LWLockRelease(SerializableXactHashLock);
4474  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4476  LWLockRelease(SerializablePredicateLockListLock);
4477 }
#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:4487
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:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1351
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1341
#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 1621 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

1622 {
1624 
1625  /*
1626  * Can't use serializable mode while recovery is still active, as it is,
1627  * for example, on a hot standby. We could get here despite the check in
1628  * check_XactIsoLevel() if default_transaction_isolation is set to
1629  * serializable, so phrase the hint accordingly.
1630  */
1631  if (RecoveryInProgress())
1632  ereport(ERROR,
1633  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1634  errmsg("cannot use serializable mode in a hot standby"),
1635  errdetail("\"default_transaction_isolation\" is set to \"serializable\"."),
1636  errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
1637 
1638  /*
1639  * A special optimization is available for SERIALIZABLE READ ONLY
1640  * DEFERRABLE transactions -- we can wait for a suitable snapshot and
1641  * thereby avoid all SSI overhead once it's running.
1642  */
1644  return GetSafeSnapshot(snapshot);
1645 
1646  return GetSerializableTransactionSnapshotInt(snapshot,
1647  NULL, InvalidPid);
1648 }
bool XactDeferrable
Definition: xact.c:80
int errhint(const char *fmt,...)
Definition: elog.c:987
static Snapshot GetSafeSnapshot(Snapshot snapshot)
Definition: predicate.c:1499
int errcode(int sqlerrcode)
Definition: elog.c:575
bool RecoveryInProgress(void)
Definition: xlog.c:7872
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1692
#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:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define InvalidPid
Definition: miscadmin.h:33
void InitPredicateLocks ( void  )

Definition at line 1105 of file predicate.c.

References PredXactListData::activeList, 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, HASHCTL::keysize, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, PredXactListElementData::link, max_prepared_xacts, MaxBackends, MemSet, mul_size(), NPREDICATELOCKTARGETENTS, NULL, 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().

1106 {
1107  HASHCTL info;
1108  long max_table_size;
1109  Size requestSize;
1110  bool found;
1111 
1112  /*
1113  * Compute size of predicate lock target hashtable. Note these
1114  * calculations must agree with PredicateLockShmemSize!
1115  */
1116  max_table_size = NPREDICATELOCKTARGETENTS();
1117 
1118  /*
1119  * Allocate hash table for PREDICATELOCKTARGET structs. This stores
1120  * per-predicate-lock-target information.
1121  */
1122  MemSet(&info, 0, sizeof(info));
1123  info.keysize = sizeof(PREDICATELOCKTARGETTAG);
1124  info.entrysize = sizeof(PREDICATELOCKTARGET);
1126 
1127  PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
1128  max_table_size,
1129  max_table_size,
1130  &info,
1131  HASH_ELEM | HASH_BLOBS |
1133 
1134  /* Assume an average of 2 xacts per target */
1135  max_table_size *= 2;
1136 
1137  /*
1138  * Reserve a dummy entry in the hash table; we use it to make sure there's
1139  * always one entry available when we need to split or combine a page,
1140  * because running out of space there could mean aborting a
1141  * non-serializable transaction.
1142  */
1144 
1145  /*
1146  * Allocate hash table for PREDICATELOCK structs. This stores per
1147  * xact-lock-of-a-target information.
1148  */
1149  MemSet(&info, 0, sizeof(info));
1150  info.keysize = sizeof(PREDICATELOCKTAG);
1151  info.entrysize = sizeof(PREDICATELOCK);
1152  info.hash = predicatelock_hash;
1154 
1155  PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
1156  max_table_size,
1157  max_table_size,
1158  &info,
1161 
1162  /*
1163  * Compute size for serializable transaction hashtable. Note these
1164  * calculations must agree with PredicateLockShmemSize!
1165  */
1166  max_table_size = (MaxBackends + max_prepared_xacts);
1167 
1168  /*
1169  * Allocate a list to hold information on transactions participating in
1170  * predicate locking.
1171  *
1172  * Assume an average of 10 predicate locking transactions per backend.
1173  * This allows aggressive cleanup while detail is present before data must
1174  * be summarized for storage in SLRU and the "dummy" transaction.
1175  */
1176  max_table_size *= 10;
1177 
1178  PredXact = ShmemInitStruct("PredXactList",
1180  &found);
1181  if (!found)
1182  {
1183  int i;
1184 
1193  requestSize = mul_size((Size) max_table_size,
1195  PredXact->element = ShmemAlloc(requestSize);
1196  /* Add all elements to available list, clean. */
1197  memset(PredXact->element, 0, requestSize);
1198  for (i = 0; i < max_table_size; i++)
1199  {
1201  &(PredXact->element[i].link));
1202  }
1218  }
1219  /* This never changes, so let's keep a local copy. */
1221 
1222  /*
1223  * Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
1224  * information for serializable transactions which have accessed data.
1225  */
1226  MemSet(&info, 0, sizeof(info));
1227  info.keysize = sizeof(SERIALIZABLEXIDTAG);
1228  info.entrysize = sizeof(SERIALIZABLEXID);
1229 
1230  SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
1231  max_table_size,
1232  max_table_size,
1233  &info,
1234  HASH_ELEM | HASH_BLOBS |
1235  HASH_FIXED_SIZE);
1236 
1237  /*
1238  * Allocate space for tracking rw-conflicts in lists attached to the
1239  * transactions.
1240  *
1241  * Assume an average of 5 conflicts per transaction. Calculations suggest
1242  * that this will prevent resource exhaustion in even the most pessimal
1243  * loads up to max_connections = 200 with all 200 connections pounding the
1244  * database with serializable transactions. Beyond that, there may be
1245  * occasional transactions canceled when trying to flag conflicts. That's
1246  * probably OK.
1247  */
1248  max_table_size *= 5;
1249 
1250  RWConflictPool = ShmemInitStruct("RWConflictPool",
1252  &found);
1253  if (!found)
1254  {
1255  int i;
1256 
1258  requestSize = mul_size((Size) max_table_size,
1260  RWConflictPool->element = ShmemAlloc(requestSize);
1261  /* Add all elements to available list, clean. */
1262  memset(RWConflictPool->element, 0, requestSize);
1263  for (i = 0; i < max_table_size; i++)
1264  {
1266  &(RWConflictPool->element[i].outLink));
1267  }
1268  }
1269 
1270  /*
1271  * Create or attach to the header for the list of finished serializable
1272  * transactions.
1273  */
1275  ShmemInitStruct("FinishedSerializableTransactions",
1276  sizeof(SHM_QUEUE),
1277  &found);
1278  if (!found)
1280 
1281  /*
1282  * Initialize the SLRU storage for old committed serializable
1283  * transactions.
1284  */
1285  OldSerXidInit();
1286 
1287  /* Pre-calculate the hash and partition lock of the scratch entry */
1290 }
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:1358
static HTAB * SerializableXidHash
Definition: predicate.c:386
#define MemSet(start, val, len)
Definition: c.h:857
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:885
#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
#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 NULL
Definition: c.h:229
#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 1914 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.

1915 {
1916  PREDICATELOCKTARGETTAG targettag;
1917  uint32 targettaghash;
1918  LWLock *partitionLock;
1919  PREDICATELOCKTARGET *target;
1920 
1922  relation->rd_node.dbNode,
1923  relation->rd_id,
1924  blkno);
1925 
1926  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1927  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1928  LWLockAcquire(partitionLock, LW_SHARED);
1929  target = (PREDICATELOCKTARGET *)
1931  &targettag, targettaghash,
1932  HASH_FIND, NULL);
1933  LWLockRelease(partitionLock);
1934 
1935  return (target != NULL);
1936 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
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 4859 of file predicate.c.

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

Referenced by PrepareTransaction().

4860 {
4862  return;
4863 
4865 
4866  MySerializableXact->pid = 0;
4867 
4870 
4872  MyXactDidWrite = false;
4873 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
#define SxactIsPrepared(sxact)
Definition: predicate.c:265
#define InvalidSerializableXact
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
static bool MyXactDidWrite
Definition: predicate.c:412
void PreCommit_CheckForSerializationFailure ( void  )

Definition at line 4697 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().

4698 {
4699  RWConflict nearConflict;
4700 
4702  return;
4703 
4705 
4706  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4707 
4708  /* Check if someone else has already decided that we need to die */
4710  {
4711  LWLockRelease(SerializableXactHashLock);
4712  ereport(ERROR,
4713  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4714  errmsg("could not serialize access due to read/write dependencies among transactions"),
4715  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4716  errhint("The transaction might succeed if retried.")));
4717  }
4718 
4719  nearConflict = (RWConflict)
4722  offsetof(RWConflictData, inLink));
4723  while (nearConflict)
4724  {
4725  if (!SxactIsCommitted(nearConflict->sxactOut)
4726  && !SxactIsDoomed(nearConflict->sxactOut))
4727  {
4728  RWConflict farConflict;
4729 
4730  farConflict = (RWConflict)
4731  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4732  &nearConflict->sxactOut->inConflicts,
4733  offsetof(RWConflictData, inLink));
4734  while (farConflict)
4735  {
4736  if (farConflict->sxactOut == MySerializableXact
4737  || (!SxactIsCommitted(farConflict->sxactOut)
4738  && !SxactIsReadOnly(farConflict->sxactOut)
4739  && !SxactIsDoomed(farConflict->sxactOut)))
4740  {
4741  /*
4742  * Normally, we kill the pivot transaction to make sure we
4743  * make progress if the failing transaction is retried.
4744  * However, we can't kill it if it's already prepared, so
4745  * in that case we commit suicide instead.
4746  */
4747  if (SxactIsPrepared(nearConflict->sxactOut))
4748  {
4749  LWLockRelease(SerializableXactHashLock);
4750  ereport(ERROR,
4751  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4752  errmsg("could not serialize access due to read/write dependencies among transactions"),
4753  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4754  errhint("The transaction might succeed if retried.")));
4755  }
4756  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4757  break;
4758  }
4759  farConflict = (RWConflict)
4760  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4761  &farConflict->inLink,
4762  offsetof(RWConflictData, inLink));
4763  }
4764  }
4765 
4766  nearConflict = (RWConflict)
4768  &nearConflict->inLink,
4769  offsetof(RWConflictData, inLink));
4770  }
4771 
4774 
4775  LWLockRelease(SerializableXactHashLock);
4776 }
#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:675
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 4908 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.

4910 {
4911  TwoPhasePredicateRecord *record;
4912 
4913  Assert(len == sizeof(TwoPhasePredicateRecord));
4914 
4915  record = (TwoPhasePredicateRecord *) recdata;
4916 
4917  Assert((record->type == TWOPHASEPREDICATERECORD_XACT) ||
4918  (record->type == TWOPHASEPREDICATERECORD_LOCK));
4919 
4920  if (record->type == TWOPHASEPREDICATERECORD_XACT)
4921  {
4922  /* Per-transaction record. Set up a SERIALIZABLEXACT. */
4923  TwoPhasePredicateXactRecord *xactRecord;
4924  SERIALIZABLEXACT *sxact;
4925  SERIALIZABLEXID *sxid;
4926  SERIALIZABLEXIDTAG sxidtag;
4927  bool found;
4928 
4929  xactRecord = (TwoPhasePredicateXactRecord *) &record->data.xactRecord;
4930 
4931  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4932  sxact = CreatePredXact();
4933  if (!sxact)
4934  ereport(ERROR,
4935  (errcode(ERRCODE_OUT_OF_MEMORY),
4936  errmsg("out of shared memory")));
4937 
4938  /* vxid for a prepared xact is InvalidBackendId/xid; no pid */
4939  sxact->vxid.backendId = InvalidBackendId;
4941  sxact->pid = 0;
4942 
4943  /* a prepared xact hasn't committed yet */
4947 
4949 
4950  /*
4951  * Don't need to track this; no transactions running at the time the
4952  * recovered xact started are still active, except possibly other
4953  * prepared xacts and we don't care whether those are RO_SAFE or not.
4954  */
4956 
4957  SHMQueueInit(&(sxact->predicateLocks));
4958  SHMQueueElemInit(&(sxact->finishedLink));
4959 
4960  sxact->topXid = xid;
4961  sxact->xmin = xactRecord->xmin;
4962  sxact->flags = xactRecord->flags;
4963  Assert(SxactIsPrepared(sxact));
4964  if (!SxactIsReadOnly(sxact))
4965  {
4969  }
4970 
4971  /*
4972  * We don't know whether the transaction had any conflicts or not, so
4973  * we'll conservatively assume that it had both a conflict in and a
4974  * conflict out, and represent that with the summary conflict flags.
4975  */
4976  SHMQueueInit(&(sxact->outConflicts));
4977  SHMQueueInit(&(sxact->inConflicts));
4980 
4981  /* Register the transaction's xid */
4982  sxidtag.xid = xid;
4984  &sxidtag,
4985  HASH_ENTER, &found);
4986  Assert(sxid != NULL);
4987  Assert(!found);
4988  sxid->myXact = (SERIALIZABLEXACT *) sxact;
4989 
4990  /*
4991  * Update global xmin. Note that this is a special case compared to
4992  * registering a normal transaction, because the global xmin might go
4993  * backwards. That's OK, because until recovery is over we're not
4994  * going to complete any transactions or create any non-prepared
4995  * transactions, so there's no danger of throwing away.
4996  */
4999  {
5000  PredXact->SxactGlobalXmin = sxact->xmin;
5003  }
5004  else if (TransactionIdEquals(sxact->xmin, PredXact->SxactGlobalXmin))
5005  {
5008  }
5009 
5010  LWLockRelease(SerializableXactHashLock);
5011  }
5012  else if (record->type == TWOPHASEPREDICATERECORD_LOCK)
5013  {
5014  /* Lock record. Recreate the PREDICATELOCK */
5015  TwoPhasePredicateLockRecord *lockRecord;
5016  SERIALIZABLEXID *sxid;
5017  SERIALIZABLEXACT *sxact;
5018  SERIALIZABLEXIDTAG sxidtag;
5019  uint32 targettaghash;
5020 
5021  lockRecord = (TwoPhasePredicateLockRecord *) &record->data.lockRecord;
5022  targettaghash = PredicateLockTargetTagHashCode(&lockRecord->target);
5023 
5024  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
5025  sxidtag.xid = xid;
5026  sxid = (SERIALIZABLEXID *)
5028  LWLockRelease(SerializableXactHashLock);
5029 
5030  Assert(sxid != NULL);
5031  sxact = sxid->myXact;
5032  Assert(sxact != InvalidSerializableXact);
5033 
5034  CreatePredicateLock(&lockRecord->target, targettaghash, sxact);
5035  }
5036 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
TransactionId finishedBefore
static void CreatePredicateLock(const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
Definition: predicate.c:2363
#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:885
#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:675
BackendId backendId
Definition: lock.h:65
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:989
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 2506 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().

2507 {
2509 
2510  if (!SerializationNeededForRead(relation, snapshot))
2511  return;
2512 
2514  relation->rd_node.dbNode,
2515  relation->rd_id,
2516  blkno);
2517  PredicateLockAcquire(&tag);
2518 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2424
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 3181 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead().

3183 {
3184  /*
3185  * Page combines differ from page splits in that we ought to be able to
3186  * remove the locks on the old page after transferring them to the new
3187  * page, instead of duplicating them. However, because we can't edit other
3188  * backends' local lock tables, removing the old lock would leave them
3189  * with an entry in their LocalPredicateLockHash for a lock they're not
3190  * holding, which isn't acceptable. So we wind up having to do the same
3191  * work as a page split, acquiring a lock on the new page and keeping the
3192  * old page locked too. That can lead to some false positives, but should
3193  * be rare in practice.
3194  */
3195  PredicateLockPageSplit(relation, oldblkno, newblkno);
3196 }
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
Definition: predicate.c:3096
void PredicateLockPageSplit ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3096 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().

3098 {
3099  PREDICATELOCKTARGETTAG oldtargettag;
3100  PREDICATELOCKTARGETTAG newtargettag;
3101  bool success;
3102 
3103  /*
3104  * Bail out quickly if there are no serializable transactions running.
3105  *
3106  * It's safe to do this check without taking any additional locks. Even if
3107  * a serializable transaction starts concurrently, we know it can't take
3108  * any SIREAD locks on the page being split because the caller is holding
3109  * the associated buffer page lock. Memory reordering isn't an issue; the
3110  * memory barrier in the LWLock acquisition guarantees that this read
3111  * occurs while the buffer page lock is held.
3112  */
3114  return;
3115 
3116  if (!PredicateLockingNeededForRelation(relation))
3117  return;
3118 
3119  Assert(oldblkno != newblkno);
3120  Assert(BlockNumberIsValid(oldblkno));
3121  Assert(BlockNumberIsValid(newblkno));
3122 
3123  SET_PREDICATELOCKTARGETTAG_PAGE(oldtargettag,
3124  relation->rd_node.dbNode,
3125  relation->rd_id,
3126  oldblkno);
3127  SET_PREDICATELOCKTARGETTAG_PAGE(newtargettag,
3128  relation->rd_node.dbNode,
3129  relation->rd_id,
3130  newblkno);
3131 
3132  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
3133 
3134  /*
3135  * Try copying the locks over to the new page's tag, creating it if
3136  * necessary.
3137  */
3138  success = TransferPredicateLocksToNewTarget(oldtargettag,
3139  newtargettag,
3140  false);
3141 
3142  if (!success)
3143  {
3144  /*
3145  * No more predicate lock entries are available. Failure isn't an
3146  * option here, so promote the page lock to a relation lock.
3147  */
3148 
3149  /* Get the parent relation lock's lock tag */
3150  success = GetParentPredicateLockTag(&oldtargettag,
3151  &newtargettag);
3152  Assert(success);
3153 
3154  /*
3155  * Move the locks to the parent. This shouldn't fail.
3156  *
3157  * Note that here we are removing locks held by other backends,
3158  * leading to a possible inconsistency in their local lock hash table.
3159  * This is OK because we're replacing it with a lock that covers the
3160  * old one.
3161  */
3162  success = TransferPredicateLocksToNewTarget(oldtargettag,
3163  newtargettag,
3164  true);
3165  Assert(success);
3166  }
3167 
3168  LWLockRelease(SerializablePredicateLockListLock);
3169 }
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:479
static bool TransferPredicateLocksToNewTarget(PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
Definition: predicate.c:2663
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:1978
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:85
#define Assert(condition)
Definition: c.h:675
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 2483 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().

2484 {
2486 
2487  if (!SerializationNeededForRead(relation, snapshot))
2488  return;
2489 
2491  relation->rd_node.dbNode,
2492  relation->rd_id);
2493  PredicateLockAcquire(&tag);
2494 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2424
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 1296 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().

1297 {
1298  Size size = 0;
1299  long max_table_size;
1300 
1301  /* predicate lock target hash table */
1302  max_table_size = NPREDICATELOCKTARGETENTS();
1303  size = add_size(size, hash_estimate_size(max_table_size,
1304  sizeof(PREDICATELOCKTARGET)));
1305 
1306  /* predicate lock hash table */
1307  max_table_size *= 2;
1308  size = add_size(size, hash_estimate_size(max_table_size,
1309  sizeof(PREDICATELOCK)));
1310 
1311  /*
1312  * Since NPREDICATELOCKTARGETENTS is only an estimate, add 10% safety
1313  * margin.
1314  */
1315  size = add_size(size, size / 10);
1316 
1317  /* transaction list */
1318  max_table_size = MaxBackends + max_prepared_xacts;
1319  max_table_size *= 10;
1320  size = add_size(size, PredXactListDataSize);
1321  size = add_size(size, mul_size((Size) max_table_size,
1323 
1324  /* transaction xid table */
1325  size = add_size(size, hash_estimate_size(max_table_size,
1326  sizeof(SERIALIZABLEXID)));
1327 
1328  /* rw-conflict pool */
1329  max_table_size *= 5;
1330  size = add_size(size, RWConflictPoolHeaderDataSize);
1331  size = add_size(size, mul_size((Size) max_table_size,
1333 
1334  /* Head for list of finished serializable transactions. */
1335  size = add_size(size, sizeof(SHM_QUEUE));
1336 
1337  /* Shared memory structures for SLRU tracking of old committed xids. */
1338  size = add_size(size, sizeof(OldSerXidControlData));
1340 
1341  return size;
1342 }
#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:711
#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 2528 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().

2529 {
2531  ItemPointer tid;
2532  TransactionId targetxmin;
2533 
2534  if (!SerializationNeededForRead(relation, snapshot))
2535  return;
2536 
2537  /*
2538  * If it's a heap tuple, return if this xact wrote it.
2539  */
2540  if (relation->rd_index == NULL)
2541  {
2542  TransactionId myxid;
2543 
2544  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2545 
2546  myxid = GetTopTransactionIdIfAny();
2547  if (TransactionIdIsValid(myxid))
2548  {
2550  {
2551  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2552 
2553  if (TransactionIdEquals(xid, myxid))
2554  {
2555  /* We wrote it; we already have a write lock. */
2556  return;
2557  }
2558  }
2559  }
2560  }
2561 
2562  /*
2563  * Do quick-but-not-definitive test for a relation lock first. This will
2564  * never cause a return when the relation is *not* locked, but will
2565  * occasionally let the check continue when there really *is* a relation
2566  * level lock.
2567  */
2569  relation->rd_node.dbNode,
2570  relation->rd_id);
2571  if (PredicateLockExists(&tag))
2572  return;
2573 
2574  tid = &(tuple->t_self);
2576  relation->rd_node.dbNode,
2577  relation->rd_id,
2580  PredicateLockAcquire(&tag);
2581 }
#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:1951
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:2424
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 4881 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

4882 {
4883  SERIALIZABLEXID *sxid;
4884  SERIALIZABLEXIDTAG sxidtag;
4885 
4886  sxidtag.xid = xid;
4887 
4888  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4889  sxid = (SERIALIZABLEXID *)
4891  LWLockRelease(SerializableXactHashLock);
4892 
4893  /* xid will not be found if it wasn't a serializable transaction */
4894  if (sxid == NULL)
4895  return;
4896 
4897  /* Release its locks */
4898  MySerializableXact = sxid->myXact;
4899  MyXactDidWrite = true; /* conservatively assume that we wrote
4900  * something */
4901  ReleasePredicateLocks(isCommit);
4902 }
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:885
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3253
#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 1865 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().

1866 {
1867  SERIALIZABLEXIDTAG sxidtag;
1868  SERIALIZABLEXID *sxid;
1869  bool found;
1870 
1871  /*
1872  * If we're not tracking predicate lock data for this transaction, we
1873  * should ignore the request and return quickly.
1874  */
1876  return;
1877 
1878  /* We should have a valid XID and be at the top level. */
1880 
1881  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1882 
1883  /* This should only be done once per transaction. */
1885 
1886  MySerializableXact->topXid = xid;
1887 
1888  sxidtag.xid = xid;
1890  &sxidtag,
1891  HASH_ENTER, &found);
1892  Assert(!found);
1893 
1894  /* Initialize the structure. */
1895  sxid->myXact = MySerializableXact;
1896  LWLockRelease(SerializableXactHashLock);
1897 }
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:885
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define InvalidSerializableXact
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void ReleasePredicateLocks ( bool  isCommit)

Definition at line 3253 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().

3254 {
3255  bool needToClear;
3256  RWConflict conflict,
3257  nextConflict,
3258  possibleUnsafeConflict;
3259  SERIALIZABLEXACT *roXact;
3260 
3261  /*
3262  * We can't trust XactReadOnly here, because a transaction which started
3263  * as READ WRITE can show as READ ONLY later, e.g., within
3264  * subtransactions. We want to flag a transaction as READ ONLY if it
3265  * commits without writing so that de facto READ ONLY transactions get the
3266  * benefit of some RO optimizations, so we will use this local variable to
3267  * get some cleanup logic right which is based on whether the transaction
3268  * was declared READ ONLY at the top level.
3269  */
3270  bool topLevelIsDeclaredReadOnly;
3271 
3273  {
3275  return;
3276  }
3277 
3278  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
3279 
3280  Assert(!isCommit || SxactIsPrepared(MySerializableXact));
3281  Assert(!isCommit || !SxactIsDoomed(MySerializableXact));
3284 
3285  /* may not be serializable during COMMIT/ROLLBACK PREPARED */
3287 
3288  /* We'd better not already be on the cleanup list. */
3290 
3291  topLevelIsDeclaredReadOnly = SxactIsReadOnly(MySerializableXact);
3292 
3293  /*
3294  * We don't hold XidGenLock lock here, assuming that TransactionId is
3295  * atomic!
3296  *
3297  * If this value is changing, we don't care that much whether we get the
3298  * old or new value -- it is just used to determine how far
3299  * GlobalSerializableXmin must advance before this transaction can be
3300  * fully cleaned up. The worst that could happen is we wait for one more
3301  * transaction to complete before freeing some RAM; correctness of visible
3302  * behavior is not affected.
3303  */
3305 
3306  /*
3307  * If it's not a commit it's a rollback, and we can clear our locks
3308  * immediately.
3309  */
3310  if (isCommit)
3311  {
3314  /* Recognize implicit read-only transaction (commit without write). */
3315  if (!MyXactDidWrite)
3317  }
3318  else
3319  {
3320  /*
3321  * The DOOMED flag indicates that we intend to roll back this
3322  * transaction and so it should not cause serialization failures for
3323  * other transactions that conflict with it. Note that this flag might
3324  * already be set, if another backend marked this transaction for
3325  * abort.
3326  *
3327  * The ROLLED_BACK flag further indicates that ReleasePredicateLocks
3328  * has been called, and so the SerializableXact is eligible for
3329  * cleanup. This means it should not be considered when calculating
3330  * SxactGlobalXmin.
3331  */
3334 
3335  /*
3336  * If the transaction was previously prepared, but is now failing due
3337  * to a ROLLBACK PREPARED or (hopefully very rare) error after the
3338  * prepare, clear the prepared flag. This simplifies conflict
3339  * checking.
3340  */
3342  }
3343 
3344  if (!topLevelIsDeclaredReadOnly)
3345  {
3347  if (--(PredXact->WritableSxactCount) == 0)
3348  {
3349  /*
3350  * Release predicate locks and rw-conflicts in for all committed
3351  * transactions. There are no longer any transactions which might
3352  * conflict with the locks and no chance for new transactions to
3353  * overlap. Similarly, existing conflicts in can't cause pivots,
3354  * and any conflicts in which could have completed a dangerous
3355  * structure would already have caused a rollback, so any
3356  * remaining ones must be benign.
3357  */
3359  }
3360  }
3361  else
3362  {
3363  /*
3364  * Read-only transactions: clear the list of transactions that might
3365  * make us unsafe. Note that we use 'inLink' for the iteration as
3366  * opposed to 'outLink' for the r/w xacts.
3367  */
3368  possibleUnsafeConflict = (RWConflict)
3371  offsetof(RWConflictData, inLink));
3372  while (possibleUnsafeConflict)
3373  {
3374  nextConflict = (RWConflict)
3376  &possibleUnsafeConflict->inLink,
3377  offsetof(RWConflictData, inLink));
3378 
3379  Assert(!SxactIsReadOnly(possibleUnsafeConflict->sxactOut));
3380  Assert(MySerializableXact == possibleUnsafeConflict->sxactIn);
3381 
3382  ReleaseRWConflict(possibleUnsafeConflict);
3383 
3384  possibleUnsafeConflict = nextConflict;
3385  }
3386  }
3387 
3388  /* Check for conflict out to old committed transactions. */
3389  if (isCommit
3392  {
3393  /*
3394  * we don't know which old committed transaction we conflicted with,
3395  * so be conservative and use FirstNormalSerCommitSeqNo here
3396  */
3400  }
3401 
3402  /*
3403  * Release all outConflicts to committed transactions. If we're rolling
3404  * back clear them all. Set SXACT_FLAG_CONFLICT_OUT if any point to
3405  * previously committed transactions.
3406  */
3407  conflict = (RWConflict)
3410  offsetof(RWConflictData, outLink));
3411  while (conflict)
3412  {
3413  nextConflict = (RWConflict)
3415  &conflict->outLink,
3416  offsetof(RWConflictData, outLink));
3417 
3418  if (isCommit
3420  && SxactIsCommitted(conflict->sxactIn))
3421  {
3426  }
3427 
3428  if (!isCommit
3429  || SxactIsCommitted(conflict->sxactIn)
3431  ReleaseRWConflict(conflict);
3432 
3433  conflict = nextConflict;
3434  }
3435 
3436  /*
3437  * Release all inConflicts from committed and read-only transactions. If
3438  * we're rolling back, clear them all.
3439  */
3440  conflict = (RWConflict)
3443  offsetof(RWConflictData, inLink));
3444  while (conflict)
3445  {
3446  nextConflict = (RWConflict)
3448  &conflict->inLink,
3449  offsetof(RWConflictData, inLink));
3450 
3451  if (!isCommit
3452  || SxactIsCommitted(conflict->sxactOut)
3453  || SxactIsReadOnly(conflict->sxactOut))
3454  ReleaseRWConflict(conflict);
3455 
3456  conflict = nextConflict;
3457  }
3458 
3459  if (!topLevelIsDeclaredReadOnly)
3460  {
3461  /*
3462  * Remove ourselves from the list of possible conflicts for concurrent
3463  * READ ONLY transactions, flagging them as unsafe if we have a
3464  * conflict out. If any are waiting DEFERRABLE transactions, wake them
3465  * up if they are known safe or known unsafe.
3466  */
3467  possibleUnsafeConflict = (RWConflict)
3470  offsetof(RWConflictData, outLink));
3471  while (possibleUnsafeConflict)
3472  {
3473  nextConflict = (RWConflict)
3475  &possibleUnsafeConflict->outLink,
3476  offsetof(RWConflictData, outLink));
3477 
3478  roXact = possibleUnsafeConflict->sxactIn;
3479  Assert(MySerializableXact == possibleUnsafeConflict->sxactOut);
3480  Assert(SxactIsReadOnly(roXact));
3481 
3482  /* Mark conflicted if necessary. */
3483  if (isCommit
3484  && MyXactDidWrite
3487  <= roXact->SeqNo.lastCommitBeforeSnapshot))
3488  {
3489  /*
3490  * This releases possibleUnsafeConflict (as well as all other
3491  * possible conflicts for roXact)
3492  */
3493  FlagSxactUnsafe(roXact);
3494  }
3495  else
3496  {
3497  ReleaseRWConflict(possibleUnsafeConflict);
3498 
3499  /*
3500  * If we were the last possible conflict, flag it safe. The
3501  * transaction can now safely release its predicate locks (but
3502  * that transaction's backend has to do that itself).
3503  */
3504  if (SHMQueueEmpty(&roXact->possibleUnsafeConflicts))
3505  roXact->flags |= SXACT_FLAG_RO_SAFE;
3506  }
3507 
3508  /*
3509  * Wake up the process for a waiting DEFERRABLE transaction if we
3510  * now know it's either safe or conflicted.
3511  */
3512  if (SxactIsDeferrableWaiting(roXact) &&
3513  (SxactIsROUnsafe(roXact) || SxactIsROSafe(roXact)))
3514  ProcSendSignal(roXact->pid);
3515 
3516  possibleUnsafeConflict = nextConflict;
3517  }
3518  }
3519 
3520  /*
3521  * Check whether it's time to clean up old transactions. This can only be
3522  * done when the last serializable transaction with the oldest xmin among
3523  * serializable transactions completes. We then find the "new oldest"
3524  * xmin and purge any transactions which finished before this transaction
3525  * was launched.
3526  */
3527  needToClear = false;
3529  {
3531  if (--(PredXact->SxactGlobalXminCount) == 0)
3532  {
3534  needToClear = true;
3535  }
3536  }
3537 
3538  LWLockRelease(SerializableXactHashLock);
3539 
3540  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3541 
3542  /* Add this to the list of transactions to check for later cleanup. */
3543  if (isCommit)
3546 
3547  if (!isCommit)
3549 
3550  LWLockRelease(SerializableFinishedListLock);
3551 
3552  if (needToClear)
3554 
3556  MyXactDidWrite = false;
3557 
3558  /* Delete per-transaction lock table */
3560  {
3563  }
3564 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
TransactionId finishedBefore
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
#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:3571
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:3728
#define Assert(condition)
Definition: c.h:675
#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:3203
#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 1661 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

1664 {
1666 
1667  /*
1668  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1669  * import snapshots, since there's no way to wait for a safe snapshot when
1670  * we're using the snap we're told to. (XXX instead of throwing an error,
1671  * we could just ignore the XactDeferrable flag?)
1672  */
1674  ereport(ERROR,
1675  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1676  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1677 
1678  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcevxid,
1679  sourcepid);
1680 }
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:1692
#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:675
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
void TransferPredicateLocksToHeapRelation ( Relation  relation)

Definition at line 3075 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3076 {
3077  DropAllPredicateLocksFromTable(relation, true);
3078 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2879

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().