PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
predicate.h File Reference
#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, TransactionId sourcexid)
 
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 30 of file predicate.h.

Referenced by OldSerXidInit(), and PredicateLockShmemSize().

Function Documentation

void AtPrepare_PredicateLocks ( void  )

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

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

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

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

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

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

Referenced by CheckPointGuts().

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

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

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

Referenced by GetTransactionSnapshot().

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

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

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

1911 {
1912  PREDICATELOCKTARGETTAG targettag;
1913  uint32 targettaghash;
1914  LWLock *partitionLock;
1915  PREDICATELOCKTARGET *target;
1916 
1918  relation->rd_node.dbNode,
1919  relation->rd_id,
1920  blkno);
1921 
1922  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1923  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1924  LWLockAcquire(partitionLock, LW_SHARED);
1925  target = (PREDICATELOCKTARGET *)
1927  &targettag, targettaghash,
1928  HASH_FIND, NULL);
1929  LWLockRelease(partitionLock);
1930 
1931  return (target != NULL);
1932 }
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 4855 of file predicate.c.

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

Referenced by PrepareTransaction().

4856 {
4858  return;
4859 
4861 
4862  MySerializableXact->pid = 0;
4863 
4866 
4868  MyXactDidWrite = false;
4869 }
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 4693 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().

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

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

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

2503 {
2505 
2506  if (!SerializationNeededForRead(relation, snapshot))
2507  return;
2508 
2510  relation->rd_node.dbNode,
2511  relation->rd_id,
2512  blkno);
2513  PredicateLockAcquire(&tag);
2514 }
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2420
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:497
void PredicateLockPageCombine ( Relation  relation,
BlockNumber  oldblkno,
BlockNumber  newblkno 
)

Definition at line 3177 of file predicate.c.

References PredicateLockPageSplit().

Referenced by _bt_mark_page_halfdead().

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

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

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

2480 {
2482 
2483  if (!SerializationNeededForRead(relation, snapshot))
2484  return;
2485 
2487  relation->rd_node.dbNode,
2488  relation->rd_id);
2489  PredicateLockAcquire(&tag);
2490 }
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2420
Oid rd_id
Definition: rel.h:116
RelFileNode rd_node
Definition: rel.h:85
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:497
Size PredicateLockShmemSize ( void  )

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

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

2525 {
2527  ItemPointer tid;
2528  TransactionId targetxmin;
2529 
2530  if (!SerializationNeededForRead(relation, snapshot))
2531  return;
2532 
2533  /*
2534  * If it's a heap tuple, return if this xact wrote it.
2535  */
2536  if (relation->rd_index == NULL)
2537  {
2538  TransactionId myxid;
2539 
2540  targetxmin = HeapTupleHeaderGetXmin(tuple->t_data);
2541 
2542  myxid = GetTopTransactionIdIfAny();
2543  if (TransactionIdIsValid(myxid))
2544  {
2546  {
2547  TransactionId xid = SubTransGetTopmostTransaction(targetxmin);
2548 
2549  if (TransactionIdEquals(xid, myxid))
2550  {
2551  /* We wrote it; we already have a write lock. */
2552  return;
2553  }
2554  }
2555  }
2556  }
2557 
2558  /*
2559  * Do quick-but-not-definitive test for a relation lock first. This will
2560  * never cause a return when the relation is *not* locked, but will
2561  * occasionally let the check continue when there really *is* a relation
2562  * level lock.
2563  */
2565  relation->rd_node.dbNode,
2566  relation->rd_id);
2567  if (PredicateLockExists(&tag))
2568  return;
2569 
2570  tid = &(tuple->t_self);
2572  relation->rd_node.dbNode,
2573  relation->rd_id,
2576  PredicateLockAcquire(&tag);
2577 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:397
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:149
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1947
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:2420
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:94
static bool SerializationNeededForRead(Relation relation, Snapshot snapshot)
Definition: predicate.c:497
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:75
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void PredicateLockTwoPhaseFinish ( TransactionId  xid,
bool  isCommit 
)

Definition at line 4877 of file predicate.c.

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

Referenced by FinishPreparedTransaction().

4878 {
4879  SERIALIZABLEXID *sxid;
4880  SERIALIZABLEXIDTAG sxidtag;
4881 
4882  sxidtag.xid = xid;
4883 
4884  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4885  sxid = (SERIALIZABLEXID *)
4887  LWLockRelease(SerializableXactHashLock);
4888 
4889  /* xid will not be found if it wasn't a serializable transaction */
4890  if (sxid == NULL)
4891  return;
4892 
4893  /* Release its locks */
4894  MySerializableXact = sxid->myXact;
4895  MyXactDidWrite = true; /* conservatively assume that we wrote
4896  * something */
4897  ReleasePredicateLocks(isCommit);
4898 }
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:3249
#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 1861 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().

1862 {
1863  SERIALIZABLEXIDTAG sxidtag;
1864  SERIALIZABLEXID *sxid;
1865  bool found;
1866 
1867  /*
1868  * If we're not tracking predicate lock data for this transaction, we
1869  * should ignore the request and return quickly.
1870  */
1872  return;
1873 
1874  /* We should have a valid XID and be at the top level. */
1876 
1877  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1878 
1879  /* This should only be done once per transaction. */
1881 
1882  MySerializableXact->topXid = xid;
1883 
1884  sxidtag.xid = xid;
1886  &sxidtag,
1887  HASH_ENTER, &found);
1888  Assert(!found);
1889 
1890  /* Initialize the structure. */
1891  sxid->myXact = MySerializableXact;
1892  LWLockRelease(SerializableXactHashLock);
1893 }
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 3249 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().

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

Definition at line 1660 of file predicate.c.

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

Referenced by SetTransactionSnapshot().

1662 {
1664 
1665  /*
1666  * We do not allow SERIALIZABLE READ ONLY DEFERRABLE transactions to
1667  * import snapshots, since there's no way to wait for a safe snapshot when
1668  * we're using the snap we're told to. (XXX instead of throwing an error,
1669  * we could just ignore the XactDeferrable flag?)
1670  */
1672  ereport(ERROR,
1673  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1674  errmsg("a snapshot-importing transaction must not be READ ONLY DEFERRABLE")));
1675 
1676  (void) GetSerializableTransactionSnapshotInt(snapshot, sourcexid);
1677 }
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, TransactionId sourcexid)
Definition: predicate.c:1689
#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 3071 of file predicate.c.

References DropAllPredicateLocksFromTable().

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

3072 {
3073  DropAllPredicateLocksFromTable(relation, true);
3074 }
static void DropAllPredicateLocksFromTable(Relation relation, bool transfer)
Definition: predicate.c:2875

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