PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
predicate.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/slru.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/twophase_rmgr.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/predicate.h"
#include "storage/predicate_internals.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/tqual.h"
Include dependency graph for predicate.c:

Go to the source code of this file.

Data Structures

struct  OldSerXidControlData
 

Macros

#define TargetTagIsCoveredBy(covered_target, covering_target)
 
#define PredicateLockHashPartition(hashcode)   ((hashcode) % NUM_PREDICATELOCK_PARTITIONS)
 
#define PredicateLockHashPartitionLock(hashcode)
 
#define PredicateLockHashPartitionLockByIndex(i)   (&MainLWLockArray[PREDICATELOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
 
#define NPREDICATELOCKTARGETENTS()   mul_size(max_predicate_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
 
#define SxactIsOnFinishedList(sxact)   (!SHMQueueIsDetached(&((sxact)->finishedLink)))
 
#define SxactIsCommitted(sxact)   (((sxact)->flags & SXACT_FLAG_COMMITTED) != 0)
 
#define SxactIsPrepared(sxact)   (((sxact)->flags & SXACT_FLAG_PREPARED) != 0)
 
#define SxactIsRolledBack(sxact)   (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 0)
 
#define SxactIsDoomed(sxact)   (((sxact)->flags & SXACT_FLAG_DOOMED) != 0)
 
#define SxactIsReadOnly(sxact)   (((sxact)->flags & SXACT_FLAG_READ_ONLY) != 0)
 
#define SxactHasSummaryConflictIn(sxact)   (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
 
#define SxactHasSummaryConflictOut(sxact)   (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0)
 
#define SxactHasConflictOut(sxact)   (((sxact)->flags & SXACT_FLAG_CONFLICT_OUT) != 0)
 
#define SxactIsDeferrableWaiting(sxact)   (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)
 
#define SxactIsROSafe(sxact)   (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0)
 
#define SxactIsROUnsafe(sxact)   (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)
 
#define PredicateLockTargetTagHashCode(predicatelocktargettag)   get_hash_value(PredicateLockTargetHash, predicatelocktargettag)
 
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
 
#define OldSerXidSlruCtl   (&OldSerXidSlruCtlData)
 
#define OLDSERXID_PAGESIZE   BLCKSZ
 
#define OLDSERXID_ENTRYSIZE   sizeof(SerCommitSeqNo)
 
#define OLDSERXID_ENTRIESPERPAGE   (OLDSERXID_PAGESIZE / OLDSERXID_ENTRYSIZE)
 
#define OLDSERXID_MAX_PAGE
 
#define OldSerXidNextPage(page)   (((page) >= OLDSERXID_MAX_PAGE) ? 0 : (page) + 1)
 
#define OldSerXidValue(slotno, xid)
 
#define OldSerXidPage(xid)   ((((uint32) (xid)) / OLDSERXID_ENTRIESPERPAGE) % (OLDSERXID_MAX_PAGE + 1))
 
#define OldSerXidSegment(page)   ((page) / SLRU_PAGES_PER_SEGMENT)
 

Typedefs

typedef struct OldSerXidControlData OldSerXidControlData
 
typedef struct
OldSerXidControlData
OldSerXidControl
 

Functions

static SERIALIZABLEXACTCreatePredXact (void)
 
static void ReleasePredXact (SERIALIZABLEXACT *sxact)
 
static SERIALIZABLEXACTFirstPredXact (void)
 
static SERIALIZABLEXACTNextPredXact (SERIALIZABLEXACT *sxact)
 
static bool RWConflictExists (const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
 
static void SetRWConflict (SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
 
static void SetPossibleUnsafeConflict (SERIALIZABLEXACT *roXact, SERIALIZABLEXACT *activeXact)
 
static void ReleaseRWConflict (RWConflict conflict)
 
static void FlagSxactUnsafe (SERIALIZABLEXACT *sxact)
 
static bool OldSerXidPagePrecedesLogically (int p, int q)
 
static void OldSerXidInit (void)
 
static void OldSerXidAdd (TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
 
static SerCommitSeqNo OldSerXidGetMinConflictCommitSeqNo (TransactionId xid)
 
static void OldSerXidSetActiveSerXmin (TransactionId xid)
 
static uint32 predicatelock_hash (const void *key, Size keysize)
 
static void SummarizeOldestCommittedSxact (void)
 
static Snapshot GetSafeSnapshot (Snapshot snapshot)
 
static Snapshot GetSerializableTransactionSnapshotInt (Snapshot snapshot, TransactionId sourcexid)
 
static bool PredicateLockExists (const PREDICATELOCKTARGETTAG *targettag)
 
static bool GetParentPredicateLockTag (const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
 
static bool CoarserLockCovers (const PREDICATELOCKTARGETTAG *newtargettag)
 
static void RemoveScratchTarget (bool lockheld)
 
static void RestoreScratchTarget (bool lockheld)
 
static void RemoveTargetIfNoLongerUsed (PREDICATELOCKTARGET *target, uint32 targettaghash)
 
static void DeleteChildTargetLocks (const PREDICATELOCKTARGETTAG *newtargettag)
 
static int MaxPredicateChildLocks (const PREDICATELOCKTARGETTAG *tag)
 
static bool CheckAndPromotePredicateLockRequest (const PREDICATELOCKTARGETTAG *reqtag)
 
static void DecrementParentLocks (const PREDICATELOCKTARGETTAG *targettag)
 
static void CreatePredicateLock (const PREDICATELOCKTARGETTAG *targettag, uint32 targettaghash, SERIALIZABLEXACT *sxact)
 
static void DeleteLockTarget (PREDICATELOCKTARGET *target, uint32 targettaghash)
 
static bool TransferPredicateLocksToNewTarget (PREDICATELOCKTARGETTAG oldtargettag, PREDICATELOCKTARGETTAG newtargettag, bool removeOld)
 
static void PredicateLockAcquire (const PREDICATELOCKTARGETTAG *targettag)
 
static void DropAllPredicateLocksFromTable (Relation relation, bool transfer)
 
static void SetNewSxactGlobalXmin (void)
 
static void ClearOldPredicateLocks (void)
 
static void ReleaseOneSerializableXact (SERIALIZABLEXACT *sxact, bool partial, bool summarize)
 
static bool XidIsConcurrent (TransactionId xid)
 
static void CheckTargetForConflictsIn (PREDICATELOCKTARGETTAG *targettag)
 
static void FlagRWConflict (SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
 
static void OnConflict_CheckForSerializationFailure (const SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
 
static bool PredicateLockingNeededForRelation (Relation relation)
 
static bool SerializationNeededForRead (Relation relation, Snapshot snapshot)
 
static bool SerializationNeededForWrite (Relation relation)
 
void CheckPointPredicate (void)
 
void InitPredicateLocks (void)
 
Size PredicateLockShmemSize (void)
 
PredicateLockDataGetPredicateLockStatusData (void)
 
int GetSafeSnapshotBlockingPids (int blocked_pid, int *output, int output_size)
 
Snapshot GetSerializableTransactionSnapshot (Snapshot snapshot)
 
void SetSerializableTransactionSnapshot (Snapshot snapshot, TransactionId sourcexid)
 
void RegisterPredicateLockingXid (TransactionId xid)
 
bool PageIsPredicateLocked (Relation relation, BlockNumber blkno)
 
void PredicateLockRelation (Relation relation, Snapshot snapshot)
 
void PredicateLockPage (Relation relation, BlockNumber blkno, Snapshot snapshot)
 
void PredicateLockTuple (Relation relation, HeapTuple tuple, Snapshot snapshot)
 
void TransferPredicateLocksToHeapRelation (Relation relation)
 
void PredicateLockPageSplit (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void PredicateLockPageCombine (Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
 
void ReleasePredicateLocks (bool isCommit)
 
void CheckForSerializableConflictOut (bool visible, 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

static SlruCtlData OldSerXidSlruCtlData
 
static OldSerXidControl oldSerXidControl
 
static SERIALIZABLEXACTOldCommittedSxact
 
int max_predicate_locks_per_xact
 
int max_predicate_locks_per_relation
 
int max_predicate_locks_per_page
 
static PredXactList PredXact
 
static RWConflictPoolHeader RWConflictPool
 
static HTABSerializableXidHash
 
static HTABPredicateLockTargetHash
 
static HTABPredicateLockHash
 
static SHM_QUEUEFinishedSerializableTransactions
 
static const PREDICATELOCKTARGETTAG ScratchTargetTag = {0, 0, 0, 0}
 
static uint32 ScratchTargetTagHash
 
static LWLockScratchPartitionLock
 
static HTABLocalPredicateLockHash = NULL
 
static SERIALIZABLEXACTMySerializableXact = InvalidSerializableXact
 
static bool MyXactDidWrite = false
 

Macro Definition Documentation

#define NPREDICATELOCKTARGETENTS ( )    mul_size(max_predicate_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))

Definition at line 251 of file predicate.c.

Referenced by InitPredicateLocks(), and PredicateLockShmemSize().

#define OLDSERXID_ENTRIESPERPAGE   (OLDSERXID_PAGESIZE / OLDSERXID_ENTRYSIZE)

Definition at line 316 of file predicate.c.

#define OLDSERXID_ENTRYSIZE   sizeof(SerCommitSeqNo)

Definition at line 315 of file predicate.c.

#define OLDSERXID_MAX_PAGE
Value:
Min(SLRU_PAGES_PER_SEGMENT * 0x10000 - 1, \
#define Min(x, y)
Definition: c.h:806
#define OLDSERXID_ENTRIESPERPAGE
Definition: predicate.c:316
#define MaxTransactionId
Definition: transam.h:35
#define SLRU_PAGES_PER_SEGMENT
Definition: slru.h:37

Definition at line 322 of file predicate.c.

Referenced by OldSerXidPagePrecedesLogically().

#define OLDSERXID_PAGESIZE   BLCKSZ

Definition at line 314 of file predicate.c.

#define OldSerXidNextPage (   page)    (((page) >= OLDSERXID_MAX_PAGE) ? 0 : (page) + 1)

Definition at line 325 of file predicate.c.

Referenced by OldSerXidAdd().

#define OldSerXidPage (   xid)    ((((uint32) (xid)) / OLDSERXID_ENTRIESPERPAGE) % (OLDSERXID_MAX_PAGE + 1))
#define OldSerXidSegment (   page)    ((page) / SLRU_PAGES_PER_SEGMENT)

Definition at line 332 of file predicate.c.

#define OldSerXidSlruCtl   (&OldSerXidSlruCtlData)
#define OldSerXidValue (   slotno,
  xid 
)
Value:
(OldSerXidSlruCtl->shared->page_buffer[slotno] + \
#define OLDSERXID_ENTRYSIZE
Definition: predicate.c:315
#define OldSerXidSlruCtl
Definition: predicate.c:312
#define OLDSERXID_ENTRIESPERPAGE
Definition: predicate.c:316
unsigned int uint32
Definition: c.h:268
uint64 SerCommitSeqNo

Definition at line 327 of file predicate.c.

Referenced by OldSerXidAdd(), and OldSerXidGetMinConflictCommitSeqNo().

#define PredicateLockHashCodeFromTargetHashCode (   predicatelocktag,
  targethash 
)
#define PredicateLockHashPartition (   hashcode)    ((hashcode) % NUM_PREDICATELOCK_PARTITIONS)

Definition at line 243 of file predicate.c.

#define PredicateLockHashPartitionLock (   hashcode)
#define PredicateLockHashPartitionLockByIndex (   i)    (&MainLWLockArray[PREDICATELOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
#define SxactHasConflictOut (   sxact)    (((sxact)->flags & SXACT_FLAG_CONFLICT_OUT) != 0)
#define SxactHasSummaryConflictIn (   sxact)    (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_IN) != 0)
#define SxactHasSummaryConflictOut (   sxact)    (((sxact)->flags & SXACT_FLAG_SUMMARY_CONFLICT_OUT) != 0)
#define SxactIsDeferrableWaiting (   sxact)    (((sxact)->flags & SXACT_FLAG_DEFERRABLE_WAITING) != 0)

Definition at line 277 of file predicate.c.

Referenced by GetSafeSnapshotBlockingPids(), and ReleasePredicateLocks().

#define SxactIsOnFinishedList (   sxact)    (!SHMQueueIsDetached(&((sxact)->finishedLink)))

Definition at line 254 of file predicate.c.

Referenced by ReleaseOneSerializableXact(), and ReleasePredicateLocks().

#define SxactIsRolledBack (   sxact)    (((sxact)->flags & SXACT_FLAG_ROLLED_BACK) != 0)
#define SxactIsROSafe (   sxact)    (((sxact)->flags & SXACT_FLAG_RO_SAFE) != 0)
#define SxactIsROUnsafe (   sxact)    (((sxact)->flags & SXACT_FLAG_RO_UNSAFE) != 0)

Definition at line 279 of file predicate.c.

Referenced by GetSafeSnapshot(), and ReleasePredicateLocks().

#define TargetTagIsCoveredBy (   covered_target,
  covering_target 
)
Value:
((GET_PREDICATELOCKTARGETTAG_RELATION(covered_target) == /* (2) */ \
&& (GET_PREDICATELOCKTARGETTAG_OFFSET(covering_target) == \
&& (((GET_PREDICATELOCKTARGETTAG_OFFSET(covered_target) != \
InvalidOffsetNumber) /* (4a) */ \
&& (GET_PREDICATELOCKTARGETTAG_PAGE(covering_target) == \
GET_PREDICATELOCKTARGETTAG_PAGE(covered_target))) \
|| ((GET_PREDICATELOCKTARGETTAG_PAGE(covering_target) == \
InvalidBlockNumber) /* (4b) */ \
&& (GET_PREDICATELOCKTARGETTAG_PAGE(covered_target) \
&& (GET_PREDICATELOCKTARGETTAG_DB(covered_target) == /* (1) */ \
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag)
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag)
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define InvalidOffsetNumber
Definition: off.h:26
#define InvalidBlockNumber
Definition: block.h:33

Definition at line 220 of file predicate.c.

Referenced by DeleteChildTargetLocks().

Typedef Documentation

Definition at line 342 of file predicate.c.

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
static bool CheckAndPromotePredicateLockRequest ( const PREDICATELOCKTARGETTAG reqtag)
static

Definition at line 2232 of file predicate.c.

References LOCALPREDICATELOCK::childLocks, GetParentPredicateLockTag(), HASH_ENTER, hash_search(), LOCALPREDICATELOCK::held, MaxPredicateChildLocks(), and PredicateLockAcquire().

Referenced by PredicateLockAcquire().

2233 {
2234  PREDICATELOCKTARGETTAG targettag,
2235  nexttag,
2236  promotiontag;
2237  LOCALPREDICATELOCK *parentlock;
2238  bool found,
2239  promote;
2240 
2241  promote = false;
2242 
2243  targettag = *reqtag;
2244 
2245  /* check parents iteratively */
2246  while (GetParentPredicateLockTag(&targettag, &nexttag))
2247  {
2248  targettag = nexttag;
2250  &targettag,
2251  HASH_ENTER,
2252  &found);
2253  if (!found)
2254  {
2255  parentlock->held = false;
2256  parentlock->childLocks = 1;
2257  }
2258  else
2259  parentlock->childLocks++;
2260 
2261  if (parentlock->childLocks >
2262  MaxPredicateChildLocks(&targettag))
2263  {
2264  /*
2265  * We should promote to this parent lock. Continue to check its
2266  * ancestors, however, both to get their child counts right and to
2267  * check whether we should just go ahead and promote to one of
2268  * them.
2269  */
2270  promotiontag = targettag;
2271  promote = true;
2272  }
2273  }
2274 
2275  if (promote)
2276  {
2277  /* acquire coarsest ancestor eligible for promotion */
2278  PredicateLockAcquire(&promotiontag);
2279  return true;
2280  }
2281  else
2282  return false;
2283 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2420
static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag)
Definition: predicate.c:2195
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1974
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
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:211
#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  visible,
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:211
#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
static void CheckTargetForConflictsIn ( PREDICATELOCKTARGETTAG targettag)
static

Definition at line 4129 of file predicate.c.

References Assert, DecrementParentLocks(), SERIALIZABLEXACT::finishedBefore, FlagRWConflict(), GET_PREDICATELOCKTARGETTAG_OFFSET, GetTransactionSnapshot(), HASH_FIND, HASH_REMOVE, hash_search_with_hash_value(), InvalidSerializableXact, IsSubTransaction(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myXact, NULL, offsetof, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLock, PREDICATELOCKTARGET::predicateLocks, PredicateLockTargetTagHashCode, RemoveTargetIfNoLongerUsed(), RWConflictExists(), SHMQueueDelete(), SHMQueueNext(), SxactIsCommitted, SxactIsDoomed, PREDICATELOCK::tag, PREDICATELOCK::targetLink, TransactionIdPrecedes(), and PREDICATELOCK::xactLink.

Referenced by CheckForSerializableConflictIn().

4130 {
4131  uint32 targettaghash;
4132  LWLock *partitionLock;
4133  PREDICATELOCKTARGET *target;
4134  PREDICATELOCK *predlock;
4135  PREDICATELOCK *mypredlock = NULL;
4136  PREDICATELOCKTAG mypredlocktag;
4137 
4139 
4140  /*
4141  * The same hash and LW lock apply to the lock target and the lock itself.
4142  */
4143  targettaghash = PredicateLockTargetTagHashCode(targettag);
4144  partitionLock = PredicateLockHashPartitionLock(targettaghash);
4145  LWLockAcquire(partitionLock, LW_SHARED);
4146  target = (PREDICATELOCKTARGET *)
4148  targettag, targettaghash,
4149  HASH_FIND, NULL);
4150  if (!target)
4151  {
4152  /* Nothing has this target locked; we're done here. */
4153  LWLockRelease(partitionLock);
4154  return;
4155  }
4156 
4157  /*
4158  * Each lock for an overlapping transaction represents a conflict: a
4159  * rw-dependency in to this transaction.
4160  */
4161  predlock = (PREDICATELOCK *)
4162  SHMQueueNext(&(target->predicateLocks),
4163  &(target->predicateLocks),
4164  offsetof(PREDICATELOCK, targetLink));
4165  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4166  while (predlock)
4167  {
4168  SHM_QUEUE *predlocktargetlink;
4169  PREDICATELOCK *nextpredlock;
4170  SERIALIZABLEXACT *sxact;
4171 
4172  predlocktargetlink = &(predlock->targetLink);
4173  nextpredlock = (PREDICATELOCK *)
4174  SHMQueueNext(&(target->predicateLocks),
4175  predlocktargetlink,
4176  offsetof(PREDICATELOCK, targetLink));
4177 
4178  sxact = predlock->tag.myXact;
4179  if (sxact == MySerializableXact)
4180  {
4181  /*
4182  * If we're getting a write lock on a tuple, we don't need a
4183  * predicate (SIREAD) lock on the same tuple. We can safely remove
4184  * our SIREAD lock, but we'll defer doing so until after the loop
4185  * because that requires upgrading to an exclusive partition lock.
4186  *
4187  * We can't use this optimization within a subtransaction because
4188  * the subtransaction could roll back, and we would be left
4189  * without any lock at the top level.
4190  */
4191  if (!IsSubTransaction()
4192  && GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
4193  {
4194  mypredlock = predlock;
4195  mypredlocktag = predlock->tag;
4196  }
4197  }
4198  else if (!SxactIsDoomed(sxact)
4199  && (!SxactIsCommitted(sxact)
4201  sxact->finishedBefore))
4203  {
4204  LWLockRelease(SerializableXactHashLock);
4205  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4206 
4207  /*
4208  * Re-check after getting exclusive lock because the other
4209  * transaction may have flagged a conflict.
4210  */
4211  if (!SxactIsDoomed(sxact)
4212  && (!SxactIsCommitted(sxact)
4214  sxact->finishedBefore))
4216  {
4218  }
4219 
4220  LWLockRelease(SerializableXactHashLock);
4221  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4222  }
4223 
4224  predlock = nextpredlock;
4225  }
4226  LWLockRelease(SerializableXactHashLock);
4227  LWLockRelease(partitionLock);
4228 
4229  /*
4230  * If we found one of our own SIREAD locks to remove, remove it now.
4231  *
4232  * At this point our transaction already has an ExclusiveRowLock on the
4233  * relation, so we are OK to drop the predicate lock on the tuple, if
4234  * found, without fearing that another write against the tuple will occur
4235  * before the MVCC information makes it to the buffer.
4236  */
4237  if (mypredlock != NULL)
4238  {
4239  uint32 predlockhashcode;
4240  PREDICATELOCK *rmpredlock;
4241 
4242  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4243  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4244  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4245 
4246  /*
4247  * Remove the predicate lock from shared memory, if it wasn't removed
4248  * while the locks were released. One way that could happen is from
4249  * autovacuum cleaning up an index.
4250  */
4251  predlockhashcode = PredicateLockHashCodeFromTargetHashCode
4252  (&mypredlocktag, targettaghash);
4253  rmpredlock = (PREDICATELOCK *)
4255  &mypredlocktag,
4256  predlockhashcode,
4257  HASH_FIND, NULL);
4258  if (rmpredlock != NULL)
4259  {
4260  Assert(rmpredlock == mypredlock);
4261 
4262  SHMQueueDelete(&(mypredlock->targetLink));
4263  SHMQueueDelete(&(mypredlock->xactLink));
4264 
4265  rmpredlock = (PREDICATELOCK *)
4267  &mypredlocktag,
4268  predlockhashcode,
4269  HASH_REMOVE, NULL);
4270  Assert(rmpredlock == mypredlock);
4271 
4272  RemoveTargetIfNoLongerUsed(target, targettaghash);
4273  }
4274 
4275  LWLockRelease(SerializableXactHashLock);
4276  LWLockRelease(partitionLock);
4277  LWLockRelease(SerializablePredicateLockListLock);
4278 
4279  if (rmpredlock != NULL)
4280  {
4281  /*
4282  * Remove entry in local lock table if it exists. It's OK if it
4283  * doesn't exist; that means the lock was transferred to a new
4284  * target by a different backend.
4285  */
4287  targettag, targettaghash,
4288  HASH_REMOVE, NULL);
4289 
4290  DecrementParentLocks(targettag);
4291  }
4292  }
4293 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
TransactionId finishedBefore
Definition: lwlock.h:32
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 void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2085
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag)
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
static HTAB * PredicateLockHash
Definition: predicate.c:388
#define InvalidSerializableXact
unsigned int uint32
Definition: c.h:268
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2297
PREDICATELOCKTAG tag
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
bool IsSubTransaction(void)
Definition: xact.c:4378
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
SERIALIZABLEXACT * myXact
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
#define offsetof(type, field)
Definition: c.h:555
static void ClearOldPredicateLocks ( void  )
static

Definition at line 3567 of file predicate.c.

References Assert, PredXactListData::CanPartialClearThrough, SERIALIZABLEXACT::commitSeqNo, PREDICATELOCK::commitSeqNo, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, HASH_REMOVE, hash_search_with_hash_value(), PredXactListData::HavePartialClearedThrough, InvalidSerCommitSeqNo, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myTarget, NULL, offsetof, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, ReleaseOneSerializableXact(), RemoveTargetIfNoLongerUsed(), SHMQueueDelete(), SHMQueueNext(), PredXactListData::SxactGlobalXmin, SxactIsReadOnly, PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, PREDICATELOCK::targetLink, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), and PREDICATELOCK::xactLink.

Referenced by ReleasePredicateLocks().

3568 {
3569  SERIALIZABLEXACT *finishedSxact;
3570  PREDICATELOCK *predlock;
3571 
3572  /*
3573  * Loop through finished transactions. They are in commit order, so we can
3574  * stop as soon as we find one that's still interesting.
3575  */
3576  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3577  finishedSxact = (SERIALIZABLEXACT *)
3580  offsetof(SERIALIZABLEXACT, finishedLink));
3581  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3582  while (finishedSxact)
3583  {
3584  SERIALIZABLEXACT *nextSxact;
3585 
3586  nextSxact = (SERIALIZABLEXACT *)
3588  &(finishedSxact->finishedLink),
3589  offsetof(SERIALIZABLEXACT, finishedLink));
3593  {
3594  /*
3595  * This transaction committed before any in-progress transaction
3596  * took its snapshot. It's no longer interesting.
3597  */
3598  LWLockRelease(SerializableXactHashLock);
3599  SHMQueueDelete(&(finishedSxact->finishedLink));
3600  ReleaseOneSerializableXact(finishedSxact, false, false);
3601  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3602  }
3603  else if (finishedSxact->commitSeqNo > PredXact->HavePartialClearedThrough
3604  && finishedSxact->commitSeqNo <= PredXact->CanPartialClearThrough)
3605  {
3606  /*
3607  * Any active transactions that took their snapshot before this
3608  * transaction committed are read-only, so we can clear part of
3609  * its state.
3610  */
3611  LWLockRelease(SerializableXactHashLock);
3612 
3613  if (SxactIsReadOnly(finishedSxact))
3614  {
3615  /* A read-only transaction can be removed entirely */
3616  SHMQueueDelete(&(finishedSxact->finishedLink));
3617  ReleaseOneSerializableXact(finishedSxact, false, false);
3618  }
3619  else
3620  {
3621  /*
3622  * A read-write transaction can only be partially cleared. We
3623  * need to keep the SERIALIZABLEXACT but can release the
3624  * SIREAD locks and conflicts in.
3625  */
3626  ReleaseOneSerializableXact(finishedSxact, true, false);
3627  }
3628 
3630  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3631  }
3632  else
3633  {
3634  /* Still interesting. */
3635  break;
3636  }
3637  finishedSxact = nextSxact;
3638  }
3639  LWLockRelease(SerializableXactHashLock);
3640 
3641  /*
3642  * Loop through predicate locks on dummy transaction for summarized data.
3643  */
3644  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
3645  predlock = (PREDICATELOCK *)
3648  offsetof(PREDICATELOCK, xactLink));
3649  while (predlock)
3650  {
3651  PREDICATELOCK *nextpredlock;
3652  bool canDoPartialCleanup;
3653 
3654  nextpredlock = (PREDICATELOCK *)
3656  &predlock->xactLink,
3657  offsetof(PREDICATELOCK, xactLink));
3658 
3659  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3660  Assert(predlock->commitSeqNo != 0);
3662  canDoPartialCleanup = (predlock->commitSeqNo <= PredXact->CanPartialClearThrough);
3663  LWLockRelease(SerializableXactHashLock);
3664 
3665  /*
3666  * If this lock originally belonged to an old enough transaction, we
3667  * can release it.
3668  */
3669  if (canDoPartialCleanup)
3670  {
3671  PREDICATELOCKTAG tag;
3672  PREDICATELOCKTARGET *target;
3673  PREDICATELOCKTARGETTAG targettag;
3674  uint32 targettaghash;
3675  LWLock *partitionLock;
3676 
3677  tag = predlock->tag;
3678  target = tag.myTarget;
3679  targettag = target->tag;
3680  targettaghash = PredicateLockTargetTagHashCode(&targettag);
3681  partitionLock = PredicateLockHashPartitionLock(targettaghash);
3682 
3683  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3684 
3685  SHMQueueDelete(&(predlock->targetLink));
3686  SHMQueueDelete(&(predlock->xactLink));
3687 
3690  targettaghash),
3691  HASH_REMOVE, NULL);
3692  RemoveTargetIfNoLongerUsed(target, targettaghash);
3693 
3694  LWLockRelease(partitionLock);
3695  }
3696 
3697  predlock = nextpredlock;
3698  }
3699 
3700  LWLockRelease(SerializablePredicateLockListLock);
3701  LWLockRelease(SerializableFinishedListLock);
3702 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
TransactionId finishedBefore
Definition: lwlock.h:32
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2085
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static HTAB * PredicateLockHash
Definition: predicate.c:388
unsigned int uint32
Definition: c.h:268
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
SerCommitSeqNo HavePartialClearedThrough
PREDICATELOCKTAG tag
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
SerCommitSeqNo commitSeqNo
#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
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:352
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:389
#define offsetof(type, field)
Definition: c.h:555
PREDICATELOCKTARGET * myTarget
static bool CoarserLockCovers ( const PREDICATELOCKTARGETTAG newtargettag)
static

Definition at line 2013 of file predicate.c.

References GetParentPredicateLockTag(), and PredicateLockExists().

Referenced by PredicateLockAcquire().

2014 {
2015  PREDICATELOCKTARGETTAG targettag,
2016  parenttag;
2017 
2018  targettag = *newtargettag;
2019 
2020  /* check parents iteratively until no more */
2021  while (GetParentPredicateLockTag(&targettag, &parenttag))
2022  {
2023  targettag = parenttag;
2024  if (PredicateLockExists(&targettag))
2025  return true;
2026  }
2027 
2028  /* no more parents to check; lock is not covered */
2029  return false;
2030 }
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1947
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1974
static void CreatePredicateLock ( const PREDICATELOCKTARGETTAG targettag,
uint32  targettaghash,
SERIALIZABLEXACT sxact 
)
static

Definition at line 2359 of file predicate.c.

References PREDICATELOCK::commitSeqNo, ereport, errcode(), errhint(), errmsg(), ERROR, HASH_ENTER_NULL, hash_search_with_hash_value(), InvalidSerCommitSeqNo, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myTarget, PREDICATELOCKTAG::myXact, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PREDICATELOCKTARGET::predicateLocks, SHMQueueInit(), SHMQueueInsertBefore(), PREDICATELOCK::targetLink, and PREDICATELOCK::xactLink.

Referenced by predicatelock_twophase_recover(), and PredicateLockAcquire().

2362 {
2363  PREDICATELOCKTARGET *target;
2364  PREDICATELOCKTAG locktag;
2365  PREDICATELOCK *lock;
2366  LWLock *partitionLock;
2367  bool found;
2368 
2369  partitionLock = PredicateLockHashPartitionLock(targettaghash);
2370 
2371  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
2372  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2373 
2374  /* Make sure that the target is represented. */
2375  target = (PREDICATELOCKTARGET *)
2377  targettag, targettaghash,
2378  HASH_ENTER_NULL, &found);
2379  if (!target)
2380  ereport(ERROR,
2381  (errcode(ERRCODE_OUT_OF_MEMORY),
2382  errmsg("out of shared memory"),
2383  errhint("You might need to increase max_pred_locks_per_transaction.")));
2384  if (!found)
2385  SHMQueueInit(&(target->predicateLocks));
2386 
2387  /* We've got the sxact and target, make sure they're joined. */
2388  locktag.myTarget = target;
2389  locktag.myXact = sxact;
2390  lock = (PREDICATELOCK *)
2392  PredicateLockHashCodeFromTargetHashCode(&locktag, targettaghash),
2393  HASH_ENTER_NULL, &found);
2394  if (!lock)
2395  ereport(ERROR,
2396  (errcode(ERRCODE_OUT_OF_MEMORY),
2397  errmsg("out of shared memory"),
2398  errhint("You might need to increase max_pred_locks_per_transaction.")));
2399 
2400  if (!found)
2401  {
2402  SHMQueueInsertBefore(&(target->predicateLocks), &(lock->targetLink));
2404  &(lock->xactLink));
2406  }
2407 
2408  LWLockRelease(partitionLock);
2409  LWLockRelease(SerializablePredicateLockListLock);
2410 }
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
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
#define ERROR
Definition: elog.h:43
static HTAB * PredicateLockHash
Definition: predicate.c:388
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
SERIALIZABLEXACT * myXact
PREDICATELOCKTARGET * myTarget
static SERIALIZABLEXACT * CreatePredXact ( void  )
static

Definition at line 563 of file predicate.c.

References PredXactListData::activeList, PredXactListData::availableList, PredXactListElementData::link, NULL, offsetof, SHMQueueDelete(), SHMQueueInsertBefore(), SHMQueueNext(), and PredXactListElementData::sxact.

Referenced by GetSerializableTransactionSnapshotInt(), InitPredicateLocks(), and predicatelock_twophase_recover().

564 {
565  PredXactListElement ptle;
566 
567  ptle = (PredXactListElement)
571  if (!ptle)
572  return NULL;
573 
574  SHMQueueDelete(&ptle->link);
576  return &ptle->sxact;
577 }
static PredXactList PredXact
Definition: predicate.c:374
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define NULL
Definition: c.h:229
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
struct PredXactListElementData * PredXactListElement
#define offsetof(type, field)
Definition: c.h:555
static void DecrementParentLocks ( const PREDICATELOCKTARGETTAG targettag)
static

Definition at line 2297 of file predicate.c.

References Assert, LOCALPREDICATELOCK::childLocks, GetParentPredicateLockTag(), HASH_FIND, HASH_REMOVE, hash_search_with_hash_value(), LOCALPREDICATELOCK::held, NULL, PG_USED_FOR_ASSERTS_ONLY, and PredicateLockTargetTagHashCode.

Referenced by CheckTargetForConflictsIn(), and DeleteChildTargetLocks().

2298 {
2299  PREDICATELOCKTARGETTAG parenttag,
2300  nexttag;
2301 
2302  parenttag = *targettag;
2303 
2304  while (GetParentPredicateLockTag(&parenttag, &nexttag))
2305  {
2306  uint32 targettaghash;
2307  LOCALPREDICATELOCK *parentlock,
2308  *rmlock PG_USED_FOR_ASSERTS_ONLY;
2309 
2310  parenttag = nexttag;
2311  targettaghash = PredicateLockTargetTagHashCode(&parenttag);
2312  parentlock = (LOCALPREDICATELOCK *)
2314  &parenttag, targettaghash,
2315  HASH_FIND, NULL);
2316 
2317  /*
2318  * There's a small chance the parent lock doesn't exist in the lock
2319  * table. This can happen if we prematurely removed it because an
2320  * index split caused the child refcount to be off.
2321  */
2322  if (parentlock == NULL)
2323  continue;
2324 
2325  parentlock->childLocks--;
2326 
2327  /*
2328  * Under similar circumstances the parent lock's refcount might be
2329  * zero. This only happens if we're holding that lock (otherwise we
2330  * would have removed the entry).
2331  */
2332  if (parentlock->childLocks < 0)
2333  {
2334  Assert(parentlock->held);
2335  parentlock->childLocks = 0;
2336  }
2337 
2338  if ((parentlock->childLocks == 0) && (!parentlock->held))
2339  {
2340  rmlock = (LOCALPREDICATELOCK *)
2342  &parenttag, targettaghash,
2343  HASH_REMOVE, NULL);
2344  Assert(rmlock == parentlock);
2345  }
2346  }
2347 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
unsigned int uint32
Definition: c.h:268
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1974
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:990
static void DeleteChildTargetLocks ( const PREDICATELOCKTARGETTAG newtargettag)
static

Definition at line 2114 of file predicate.c.

References Assert, DecrementParentLocks(), HASH_REMOVE, hash_search_with_hash_value(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myTarget, PREDICATELOCKTAG::myXact, NULL, offsetof, PG_USED_FOR_ASSERTS_ONLY, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLock, SERIALIZABLEXACT::predicateLocks, PredicateLockTargetTagHashCode, RemoveTargetIfNoLongerUsed(), SHMQueueDelete(), SHMQueueNext(), PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, PREDICATELOCK::targetLink, TargetTagIsCoveredBy, and PREDICATELOCK::xactLink.

Referenced by PredicateLockAcquire().

2115 {
2116  SERIALIZABLEXACT *sxact;
2117  PREDICATELOCK *predlock;
2118 
2119  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
2120  sxact = MySerializableXact;
2121  predlock = (PREDICATELOCK *)
2122  SHMQueueNext(&(sxact->predicateLocks),
2123  &(sxact->predicateLocks),
2124  offsetof(PREDICATELOCK, xactLink));
2125  while (predlock)
2126  {
2127  SHM_QUEUE *predlocksxactlink;
2128  PREDICATELOCK *nextpredlock;
2129  PREDICATELOCKTAG oldlocktag;
2130  PREDICATELOCKTARGET *oldtarget;
2131  PREDICATELOCKTARGETTAG oldtargettag;
2132 
2133  predlocksxactlink = &(predlock->xactLink);
2134  nextpredlock = (PREDICATELOCK *)
2135  SHMQueueNext(&(sxact->predicateLocks),
2136  predlocksxactlink,
2137  offsetof(PREDICATELOCK, xactLink));
2138 
2139  oldlocktag = predlock->tag;
2140  Assert(oldlocktag.myXact == sxact);
2141  oldtarget = oldlocktag.myTarget;
2142  oldtargettag = oldtarget->tag;
2143 
2144  if (TargetTagIsCoveredBy(oldtargettag, *newtargettag))
2145  {
2146  uint32 oldtargettaghash;
2147  LWLock *partitionLock;
2149 
2150  oldtargettaghash = PredicateLockTargetTagHashCode(&oldtargettag);
2151  partitionLock = PredicateLockHashPartitionLock(oldtargettaghash);
2152 
2153  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2154 
2155  SHMQueueDelete(predlocksxactlink);
2156  SHMQueueDelete(&(predlock->targetLink));
2157  rmpredlock = hash_search_with_hash_value
2159  &oldlocktag,
2161  oldtargettaghash),
2162  HASH_REMOVE, NULL);
2163  Assert(rmpredlock == predlock);
2164 
2165  RemoveTargetIfNoLongerUsed(oldtarget, oldtargettaghash);
2166 
2167  LWLockRelease(partitionLock);
2168 
2169  DecrementParentLocks(&oldtargettag);
2170  }
2171 
2172  predlock = nextpredlock;
2173  }
2174  LWLockRelease(SerializablePredicateLockListLock);
2175 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
Definition: lwlock.h:32
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2085
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
static HTAB * PredicateLockHash
Definition: predicate.c:388
unsigned int uint32
Definition: c.h:268
static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2297
PREDICATELOCKTAG tag
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TargetTagIsCoveredBy(covered_target, covering_target)
Definition: predicate.c:220
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
SERIALIZABLEXACT * myXact
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:990
#define offsetof(type, field)
Definition: c.h:555
PREDICATELOCKTARGET * myTarget
static void DeleteLockTarget ( PREDICATELOCKTARGET target,
uint32  targettaghash 
)
static

Definition at line 2589 of file predicate.c.

References Assert, HASH_REMOVE, hash_search_with_hash_value(), LW_EXCLUSIVE, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), offsetof, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLock, PREDICATELOCKTARGET::predicateLocks, RemoveTargetIfNoLongerUsed(), SHMQueueDelete(), SHMQueueNext(), PREDICATELOCK::tag, PREDICATELOCK::targetLink, and PREDICATELOCK::xactLink.

Referenced by TransferPredicateLocksToNewTarget().

2590 {
2591  PREDICATELOCK *predlock;
2592  SHM_QUEUE *predlocktargetlink;
2593  PREDICATELOCK *nextpredlock;
2594  bool found;
2595 
2596  Assert(LWLockHeldByMe(SerializablePredicateLockListLock));
2598 
2599  predlock = (PREDICATELOCK *)
2600  SHMQueueNext(&(target->predicateLocks),
2601  &(target->predicateLocks),
2602  offsetof(PREDICATELOCK, targetLink));
2603  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
2604  while (predlock)
2605  {
2606  predlocktargetlink = &(predlock->targetLink);
2607  nextpredlock = (PREDICATELOCK *)
2608  SHMQueueNext(&(target->predicateLocks),
2609  predlocktargetlink,
2610  offsetof(PREDICATELOCK, targetLink));
2611 
2612  SHMQueueDelete(&(predlock->xactLink));
2613  SHMQueueDelete(&(predlock->targetLink));
2614 
2617  &predlock->tag,
2619  targettaghash),
2620  HASH_REMOVE, &found);
2621  Assert(found);
2622 
2623  predlock = nextpredlock;
2624  }
2625  LWLockRelease(SerializableXactHashLock);
2626 
2627  /* Remove the target itself, if possible. */
2628  RemoveTargetIfNoLongerUsed(target, targettaghash);
2629 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1831
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2085
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
static HTAB * PredicateLockHash
Definition: predicate.c:388
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define offsetof(type, field)
Definition: c.h:555
static void DropAllPredicateLocksFromTable ( Relation  relation,
bool  transfer 
)
static

Definition at line 2875 of file predicate.c.

References Assert, PREDICATELOCK::commitSeqNo, RelFileNode::dbNode, GET_PREDICATELOCKTARGETTAG_DB, GET_PREDICATELOCKTARGETTAG_RELATION, GET_PREDICATELOCKTARGETTAG_TYPE, HASH_ENTER, HASH_REMOVE, hash_search(), hash_search_with_hash_value(), hash_seq_init(), hash_seq_search(), i, InvalidOid, InvalidSerCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myTarget, PREDICATELOCKTAG::myXact, NULL, NUM_PREDICATELOCK_PARTITIONS, offsetof, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLockByIndex, PredicateLockingNeededForRelation(), SERIALIZABLEXACT::predicateLocks, PREDICATELOCKTARGET::predicateLocks, PredicateLockTargetTagHashCode, PREDLOCKTAG_RELATION, RelationData::rd_id, RelationData::rd_index, RelationData::rd_node, RemoveScratchTarget(), RestoreScratchTarget(), SET_PREDICATELOCKTARGETTAG_RELATION, SHMQueueDelete(), SHMQueueInit(), SHMQueueInsertBefore(), SHMQueueNext(), PredXactListData::SxactGlobalXmin, PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, PREDICATELOCK::targetLink, TransactionIdIsValid, and PREDICATELOCK::xactLink.

Referenced by TransferPredicateLocksToHeapRelation().

2876 {
2877  HASH_SEQ_STATUS seqstat;
2878  PREDICATELOCKTARGET *oldtarget;
2879  PREDICATELOCKTARGET *heaptarget;
2880  Oid dbId;
2881  Oid relId;
2882  Oid heapId;
2883  int i;
2884  bool isIndex;
2885  bool found;
2886  uint32 heaptargettaghash;
2887 
2888  /*
2889  * Bail out quickly if there are no serializable transactions running.
2890  * It's safe to check this without taking locks because the caller is
2891  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
2892  * would matter here can be acquired while that is held.
2893  */
2895  return;
2896 
2897  if (!PredicateLockingNeededForRelation(relation))
2898  return;
2899 
2900  dbId = relation->rd_node.dbNode;
2901  relId = relation->rd_id;
2902  if (relation->rd_index == NULL)
2903  {
2904  isIndex = false;
2905  heapId = relId;
2906  }
2907  else
2908  {
2909  isIndex = true;
2910  heapId = relation->rd_index->indrelid;
2911  }
2912  Assert(heapId != InvalidOid);
2913  Assert(transfer || !isIndex); /* index OID only makes sense with
2914  * transfer */
2915 
2916  /* Retrieve first time needed, then keep. */
2917  heaptargettaghash = 0;
2918  heaptarget = NULL;
2919 
2920  /* Acquire locks on all lock partitions */
2921  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
2922  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
2924  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
2925 
2926  /*
2927  * Remove the dummy entry to give us scratch space, so we know we'll be
2928  * able to create the new lock target.
2929  */
2930  if (transfer)
2931  RemoveScratchTarget(true);
2932 
2933  /* Scan through target map */
2935 
2936  while ((oldtarget = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
2937  {
2938  PREDICATELOCK *oldpredlock;
2939 
2940  /*
2941  * Check whether this is a target which needs attention.
2942  */
2943  if (GET_PREDICATELOCKTARGETTAG_RELATION(oldtarget->tag) != relId)
2944  continue; /* wrong relation id */
2945  if (GET_PREDICATELOCKTARGETTAG_DB(oldtarget->tag) != dbId)
2946  continue; /* wrong database id */
2947  if (transfer && !isIndex
2949  continue; /* already the right lock */
2950 
2951  /*
2952  * If we made it here, we have work to do. We make sure the heap
2953  * relation lock exists, then we walk the list of predicate locks for
2954  * the old target we found, moving all locks to the heap relation lock
2955  * -- unless they already hold that.
2956  */
2957 
2958  /*
2959  * First make sure we have the heap relation target. We only need to
2960  * do this once.
2961  */
2962  if (transfer && heaptarget == NULL)
2963  {
2964  PREDICATELOCKTARGETTAG heaptargettag;
2965 
2966  SET_PREDICATELOCKTARGETTAG_RELATION(heaptargettag, dbId, heapId);
2967  heaptargettaghash = PredicateLockTargetTagHashCode(&heaptargettag);
2969  &heaptargettag,
2970  heaptargettaghash,
2971  HASH_ENTER, &found);
2972  if (!found)
2973  SHMQueueInit(&heaptarget->predicateLocks);
2974  }
2975 
2976  /*
2977  * Loop through all the locks on the old target, replacing them with
2978  * locks on the new target.
2979  */
2980  oldpredlock = (PREDICATELOCK *)
2981  SHMQueueNext(&(oldtarget->predicateLocks),
2982  &(oldtarget->predicateLocks),
2983  offsetof(PREDICATELOCK, targetLink));
2984  while (oldpredlock)
2985  {
2986  PREDICATELOCK *nextpredlock;
2987  PREDICATELOCK *newpredlock;
2988  SerCommitSeqNo oldCommitSeqNo;
2989  SERIALIZABLEXACT *oldXact;
2990 
2991  nextpredlock = (PREDICATELOCK *)
2992  SHMQueueNext(&(oldtarget->predicateLocks),
2993  &(oldpredlock->targetLink),
2994  offsetof(PREDICATELOCK, targetLink));
2995 
2996  /*
2997  * Remove the old lock first. This avoids the chance of running
2998  * out of lock structure entries for the hash table.
2999  */
3000  oldCommitSeqNo = oldpredlock->commitSeqNo;
3001  oldXact = oldpredlock->tag.myXact;
3002 
3003  SHMQueueDelete(&(oldpredlock->xactLink));
3004 
3005  /*
3006  * No need for retail delete from oldtarget list, we're removing
3007  * the whole target anyway.
3008  */
3010  &oldpredlock->tag,
3011  HASH_REMOVE, &found);
3012  Assert(found);
3013 
3014  if (transfer)
3015  {
3016  PREDICATELOCKTAG newpredlocktag;
3017 
3018  newpredlocktag.myTarget = heaptarget;
3019  newpredlocktag.myXact = oldXact;
3020  newpredlock = (PREDICATELOCK *)
3022  &newpredlocktag,
3024  heaptargettaghash),
3025  HASH_ENTER,
3026  &found);
3027  if (!found)
3028  {
3029  SHMQueueInsertBefore(&(heaptarget->predicateLocks),
3030  &(newpredlock->targetLink));
3031  SHMQueueInsertBefore(&(newpredlocktag.myXact->predicateLocks),
3032  &(newpredlock->xactLink));
3033  newpredlock->commitSeqNo = oldCommitSeqNo;
3034  }
3035  else
3036  {
3037  if (newpredlock->commitSeqNo < oldCommitSeqNo)
3038  newpredlock->commitSeqNo = oldCommitSeqNo;
3039  }
3040 
3041  Assert(newpredlock->commitSeqNo != 0);
3042  Assert((newpredlock->commitSeqNo == InvalidSerCommitSeqNo)
3043  || (newpredlock->tag.myXact == OldCommittedSxact));
3044  }
3045 
3046  oldpredlock = nextpredlock;
3047  }
3048 
3050  &found);
3051  Assert(found);
3052  }
3053 
3054  /* Put the scratch entry back */
3055  if (transfer)
3056  RestoreScratchTarget(true);
3057 
3058  /* Release locks in reverse order */
3059  LWLockRelease(SerializableXactHashLock);
3060  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
3062  LWLockRelease(SerializablePredicateLockListLock);
3063 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:898
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:478
static HTAB * PredicateLockTargetHash
Definition: predicate.c:387
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
unsigned int Oid
Definition: postgres_ext.h:31
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void RemoveScratchTarget(bool lockheld)
Definition: predicate.c:2042
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
Form_pg_index rd_index
Definition: rel.h:159
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
static HTAB * PredicateLockHash
Definition: predicate.c:388
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
unsigned int uint32
Definition: c.h:268
Oid rd_id
Definition: rel.h:116
#define InvalidSerCommitSeqNo
static void RestoreScratchTarget(bool lockheld)
Definition: predicate.c:2063
PREDICATELOCKTAG tag
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define InvalidOid
Definition: postgres_ext.h:36
PREDICATELOCKTARGETTAG tag
RelFileNode rd_node
Definition: rel.h:85
SerCommitSeqNo commitSeqNo
uint64 SerCommitSeqNo
#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
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:352
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:248
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int i
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
SERIALIZABLEXACT * myXact
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:555
PREDICATELOCKTARGET * myTarget
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
static SERIALIZABLEXACT * FirstPredXact ( void  )
static

Definition at line 595 of file predicate.c.

References PredXactListData::activeList, NULL, offsetof, SHMQueueNext(), and PredXactListElementData::sxact.

Referenced by GetSafeSnapshotBlockingPids(), GetSerializableTransactionSnapshotInt(), and SetNewSxactGlobalXmin().

596 {
597  PredXactListElement ptle;
598 
599  ptle = (PredXactListElement)
603  if (!ptle)
604  return NULL;
605 
606  return &ptle->sxact;
607 }
static PredXactList PredXact
Definition: predicate.c:374
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define NULL
Definition: c.h:229
struct PredXactListElementData * PredXactListElement
#define offsetof(type, field)
Definition: c.h:555
static void FlagRWConflict ( SERIALIZABLEXACT reader,
SERIALIZABLEXACT writer 
)
static

Definition at line 4483 of file predicate.c.

References Assert, SERIALIZABLEXACT::flags, OnConflict_CheckForSerializationFailure(), SetRWConflict(), SXACT_FLAG_SUMMARY_CONFLICT_IN, and SXACT_FLAG_SUMMARY_CONFLICT_OUT.

Referenced by CheckForSerializableConflictOut(), CheckTableForSerializableConflictIn(), and CheckTargetForConflictsIn().

4484 {
4485  Assert(reader != writer);
4486 
4487  /* First, see if this conflict causes failure. */
4489 
4490  /* Actually do the conflict flagging. */
4491  if (reader == OldCommittedSxact)
4493  else if (writer == OldCommittedSxact)
4495  else
4496  SetRWConflict(reader, writer);
4497 }
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
static void SetRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:669
static void OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4518
#define Assert(condition)
Definition: c.h:675
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:352
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static void FlagSxactUnsafe ( SERIALIZABLEXACT sxact)
static

Definition at line 733 of file predicate.c.

References Assert, SERIALIZABLEXACT::flags, RWConflictData::inLink, offsetof, SERIALIZABLEXACT::possibleUnsafeConflicts, ReleaseRWConflict(), SHMQueueNext(), SXACT_FLAG_RO_UNSAFE, RWConflictData::sxactIn, SxactIsReadOnly, SxactIsROSafe, and RWConflictData::sxactOut.

Referenced by ReleasePredicateLocks().

734 {
735  RWConflict conflict,
736  nextConflict;
737 
738  Assert(SxactIsReadOnly(sxact));
739  Assert(!SxactIsROSafe(sxact));
740 
741  sxact->flags |= SXACT_FLAG_RO_UNSAFE;
742 
743  /*
744  * We know this isn't a safe snapshot, so we can stop looking for other
745  * potential conflicts.
746  */
747  conflict = (RWConflict)
749  &sxact->possibleUnsafeConflicts,
750  offsetof(RWConflictData, inLink));
751  while (conflict)
752  {
753  nextConflict = (RWConflict)
755  &conflict->inLink,
756  offsetof(RWConflictData, inLink));
757 
758  Assert(!SxactIsReadOnly(conflict->sxactOut));
759  Assert(sxact == conflict->sxactIn);
760 
761  ReleaseRWConflict(conflict);
762 
763  conflict = nextConflict;
764  }
765 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
struct RWConflictData * RWConflict
static void ReleaseRWConflict(RWConflict conflict)
Definition: predicate.c:725
SERIALIZABLEXACT * sxactIn
SHM_QUEUE possibleUnsafeConflicts
#define SxactIsROSafe(sxact)
Definition: predicate.c:278
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:675
#define SXACT_FLAG_RO_UNSAFE
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
static bool GetParentPredicateLockTag ( const PREDICATELOCKTARGETTAG tag,
PREDICATELOCKTARGETTAG parent 
)
static

Definition at line 1974 of file predicate.c.

References Assert, GET_PREDICATELOCKTARGETTAG_DB, GET_PREDICATELOCKTARGETTAG_PAGE, GET_PREDICATELOCKTARGETTAG_RELATION, GET_PREDICATELOCKTARGETTAG_TYPE, PREDLOCKTAG_PAGE, PREDLOCKTAG_RELATION, PREDLOCKTAG_TUPLE, SET_PREDICATELOCKTARGETTAG_PAGE, and SET_PREDICATELOCKTARGETTAG_RELATION.

Referenced by CheckAndPromotePredicateLockRequest(), CoarserLockCovers(), DecrementParentLocks(), and PredicateLockPageSplit().

1976 {
1977  switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag))
1978  {
1979  case PREDLOCKTAG_RELATION:
1980  /* relation locks have no parent lock */
1981  return false;
1982 
1983  case PREDLOCKTAG_PAGE:
1984  /* parent lock is relation lock */
1988 
1989  return true;
1990 
1991  case PREDLOCKTAG_TUPLE:
1992  /* parent lock is page lock */
1997  return true;
1998  }
1999 
2000  /* not reachable */
2001  Assert(false);
2002  return false;
2003 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag)
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define Assert(condition)
Definition: c.h:675
PredicateLockData* GetPredicateLockStatusData ( void  )

Definition at line 1383 of file predicate.c.

References Assert, hash_get_num_entries(), hash_seq_init(), hash_seq_search(), i, PredicateLockData::locktags, LW_SHARED, LWLockAcquire(), LWLockRelease(), PREDICATELOCKTAG::myTarget, PREDICATELOCKTAG::myXact, PredicateLockData::nelements, NUM_PREDICATELOCK_PARTITIONS, palloc(), PredicateLockHashPartitionLockByIndex, PREDICATELOCKTARGET::tag, PREDICATELOCK::tag, and PredicateLockData::xacts.

Referenced by pg_lock_status().

1384 {
1385  PredicateLockData *data;
1386  int i;
1387  int els,
1388  el;
1389  HASH_SEQ_STATUS seqstat;
1390  PREDICATELOCK *predlock;
1391 
1392  data = (PredicateLockData *) palloc(sizeof(PredicateLockData));
1393 
1394  /*
1395  * To ensure consistency, take simultaneous locks on all partition locks
1396  * in ascending order, then SerializableXactHashLock.
1397  */
1398  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
1400  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
1401 
1402  /* Get number of locks and allocate appropriately-sized arrays. */
1404  data->nelements = els;
1405  data->locktags = (PREDICATELOCKTARGETTAG *)
1406  palloc(sizeof(PREDICATELOCKTARGETTAG) * els);
1407  data->xacts = (SERIALIZABLEXACT *)
1408  palloc(sizeof(SERIALIZABLEXACT) * els);
1409 
1410 
1411  /* Scan through PredicateLockHash and copy contents */
1412  hash_seq_init(&seqstat, PredicateLockHash);
1413 
1414  el = 0;
1415 
1416  while ((predlock = (PREDICATELOCK *) hash_seq_search(&seqstat)))
1417  {
1418  data->locktags[el] = predlock->tag.myTarget->tag;
1419  data->xacts[el] = *predlock->tag.myXact;
1420  el++;
1421  }
1422 
1423  Assert(el == els);
1424 
1425  /* Release locks in reverse order */
1426  LWLockRelease(SerializableXactHashLock);
1427  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
1429 
1430  return data;
1431 }
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1297
SERIALIZABLEXACT * xacts
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
static HTAB * PredicateLockHash
Definition: predicate.c:388
PREDICATELOCKTARGETTAG * locktags
PREDICATELOCKTAG tag
PREDICATELOCKTARGETTAG tag
#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
void * palloc(Size size)
Definition: mcxt.c:849
int i
SERIALIZABLEXACT * myXact
PREDICATELOCKTARGET * myTarget
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
static Snapshot GetSafeSnapshot ( Snapshot  snapshot)
static

Definition at line 1498 of file predicate.c.

References Assert, DEBUG2, ereport, errcode(), errmsg(), SERIALIZABLEXACT::flags, GetSerializableTransactionSnapshotInt(), InvalidSerializableXact, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SERIALIZABLEXACT::possibleUnsafeConflicts, ProcWaitForSignal(), ReleasePredicateLocks(), SHMQueueEmpty(), SXACT_FLAG_DEFERRABLE_WAITING, SxactIsROSafe, SxactIsROUnsafe, WAIT_EVENT_SAFE_SNAPSHOT, XactDeferrable, and XactReadOnly.

Referenced by GetSerializableTransactionSnapshot().

1499 {
1500  Snapshot snapshot;
1501 
1503 
1504  while (true)
1505  {
1506  /*
1507  * GetSerializableTransactionSnapshotInt is going to call
1508  * GetSnapshotData, so we need to provide it the static snapshot area
1509  * our caller passed to us. The pointer returned is actually the same
1510  * one passed to it, but we avoid assuming that here.
1511  */
1512  snapshot = GetSerializableTransactionSnapshotInt(origSnapshot,
1514 
1516  return snapshot; /* no concurrent r/w xacts; it's safe */
1517 
1518  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1519 
1520  /*
1521  * Wait for concurrent transactions to finish. Stop early if one of
1522  * them marked us as conflicted.
1523  */
1527  {
1528  LWLockRelease(SerializableXactHashLock);
1530  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1531  }
1533 
1535  {
1536  LWLockRelease(SerializableXactHashLock);
1537  break; /* success */
1538  }
1539 
1540  LWLockRelease(SerializableXactHashLock);
1541 
1542  /* else, need to retry... */
1543  ereport(DEBUG2,
1544  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1545  errmsg("deferrable snapshot was unsafe; trying a new one")));
1546  ReleasePredicateLocks(false);
1547  }
1548 
1549  /*
1550  * Now we have a safe snapshot, so we don't need to do any further checks.
1551  */
1553  ReleasePredicateLocks(false);
1554 
1555  return snapshot;
1556 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:575
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
SHM_QUEUE possibleUnsafeConflicts
#define InvalidSerializableXact
#define SXACT_FLAG_DEFERRABLE_WAITING
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, TransactionId sourcexid)
Definition: predicate.c:1689
#define DEBUG2
Definition: elog.h:24
#define InvalidTransactionId
Definition: transam.h:31
#define SxactIsROSafe(sxact)
Definition: predicate.c:278
#define ereport(elevel, rest)
Definition: elog.h:122
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1766
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3249
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:279
int GetSafeSnapshotBlockingPids ( int  blocked_pid,
int *  output,
int  output_size 
)

Definition at line 1568 of file predicate.c.

References FirstPredXact(), RWConflictData::inLink, LW_SHARED, LWLockAcquire(), LWLockRelease(), NextPredXact(), NULL, offsetof, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SHMQueueNext(), SxactIsDeferrableWaiting, and RWConflictData::sxactOut.

Referenced by pg_isolation_test_session_is_blocked(), and pg_safe_snapshot_blocking_pids().

1569 {
1570  int num_written = 0;
1571  SERIALIZABLEXACT *sxact;
1572 
1573  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
1574 
1575  /* Find blocked_pid's SERIALIZABLEXACT by linear search. */
1576  for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
1577  {
1578  if (sxact->pid == blocked_pid)
1579  break;
1580  }
1581 
1582  /* Did we find it, and is it currently waiting in GetSafeSnapshot? */
1583  if (sxact != NULL && SxactIsDeferrableWaiting(sxact))
1584  {
1585  RWConflict possibleUnsafeConflict;
1586 
1587  /* Traverse the list of possible unsafe conflicts collecting PIDs. */
1588  possibleUnsafeConflict = (RWConflict)
1590  &sxact->possibleUnsafeConflicts,
1591  offsetof(RWConflictData, inLink));
1592 
1593  while (possibleUnsafeConflict != NULL && num_written < output_size)
1594  {
1595  output[num_written++] = possibleUnsafeConflict->sxactOut->pid;
1596  possibleUnsafeConflict = (RWConflict)
1598  &possibleUnsafeConflict->inLink,
1599  offsetof(RWConflictData, inLink));
1600  }
1601  }
1602 
1603  LWLockRelease(SerializableXactHashLock);
1604 
1605  return num_written;
1606 }
static void output(uint64 loop_count)
struct RWConflictData * RWConflict
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
SHM_QUEUE possibleUnsafeConflicts
static SERIALIZABLEXACT * NextPredXact(SERIALIZABLEXACT *sxact)
Definition: predicate.c:610
static SERIALIZABLEXACT * FirstPredXact(void)
Definition: predicate.c:595
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define NULL
Definition: c.h:229
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:277
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
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:7873
#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
static Snapshot GetSerializableTransactionSnapshotInt ( Snapshot  snapshot,
TransactionId  sourcexid 
)
static

Definition at line 1689 of file predicate.c.

References Assert, SERIALIZABLEXACT::commitSeqNo, CreatePredXact(), elog, HASHCTL::entrysize, ereport, errcode(), errdetail(), errmsg(), ERROR, SERIALIZABLEXACT::finishedBefore, SERIALIZABLEXACT::finishedLink, FirstPredXact(), SERIALIZABLEXACT::flags, GET_VXID_FROM_PGPROC, GetSnapshotData(), GetTopTransactionIdIfAny(), HASH_BLOBS, hash_create(), HASH_ELEM, SERIALIZABLEXACT::inConflicts, InvalidSerCommitSeqNo, InvalidSerializableXact, InvalidTransactionId, IsInParallelMode(), HASHCTL::keysize, SERIALIZABLEXACT::lastCommitBeforeSnapshot, PredXactListData::LastSxactCommitSeqNo, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), max_predicate_locks_per_xact, max_prepared_xacts, MaxBackends, MemSet, MyProc, MyProcPid, MyXactDidWrite, NextPredXact(), NULL, OldSerXidSetActiveSerXmin(), SERIALIZABLEXACT::outConflicts, SERIALIZABLEXACT::pid, SERIALIZABLEXACT::possibleUnsafeConflicts, SERIALIZABLEXACT::predicateLocks, SERIALIZABLEXACT::prepareSeqNo, ProcArrayInstallImportedXmin(), RecoveryInProgress(), ReleasePredXact(), SERIALIZABLEXACT::SeqNo, SetPossibleUnsafeConflict(), SHMQueueElemInit(), SHMQueueInit(), SummarizeOldestCommittedSxact(), SXACT_FLAG_READ_ONLY, PredXactListData::SxactGlobalXmin, PredXactListData::SxactGlobalXminCount, SxactIsCommitted, SxactIsDoomed, SxactIsReadOnly, SERIALIZABLEXACT::topXid, TransactionIdEquals, TransactionIdFollows(), TransactionIdIsValid, SERIALIZABLEXACT::vxid, PredXactListData::WritableSxactCount, XactReadOnly, SnapshotData::xmin, and SERIALIZABLEXACT::xmin.

Referenced by GetSafeSnapshot(), GetSerializableTransactionSnapshot(), and SetSerializableTransactionSnapshot().

1691 {
1692  PGPROC *proc;
1693  VirtualTransactionId vxid;
1694  SERIALIZABLEXACT *sxact,
1695  *othersxact;
1696  HASHCTL hash_ctl;
1697 
1698  /* We only do this for serializable transactions. Once. */
1700 
1702 
1703  /*
1704  * Since all parts of a serializable transaction must use the same
1705  * snapshot, it is too late to establish one after a parallel operation
1706  * has begun.
1707  */
1708  if (IsInParallelMode())
1709  elog(ERROR, "cannot establish serializable snapshot during a parallel operation");
1710 
1711  proc = MyProc;
1712  Assert(proc != NULL);
1713  GET_VXID_FROM_PGPROC(vxid, *proc);
1714 
1715  /*
1716  * First we get the sxact structure, which may involve looping and access
1717  * to the "finished" list to free a structure for use.
1718  *
1719  * We must hold SerializableXactHashLock when taking/checking the snapshot
1720  * to avoid race conditions, for much the same reasons that
1721  * GetSnapshotData takes the ProcArrayLock. Since we might have to
1722  * release SerializableXactHashLock to call SummarizeOldestCommittedSxact,
1723  * this means we have to create the sxact first, which is a bit annoying
1724  * (in particular, an elog(ERROR) in procarray.c would cause us to leak
1725  * the sxact). Consider refactoring to avoid this.
1726  */
1727 #ifdef TEST_OLDSERXID
1729 #endif
1730  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1731  do
1732  {
1733  sxact = CreatePredXact();
1734  /* If null, push out committed sxact to SLRU summary & retry. */
1735  if (!sxact)
1736  {
1737  LWLockRelease(SerializableXactHashLock);
1739  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1740  }
1741  } while (!sxact);
1742 
1743  /* Get the snapshot, or check that it's safe to use */
1744  if (!TransactionIdIsValid(sourcexid))
1745  snapshot = GetSnapshotData(snapshot);
1746  else if (!ProcArrayInstallImportedXmin(snapshot->xmin, sourcexid))
1747  {
1748  ReleasePredXact(sxact);
1749  LWLockRelease(SerializableXactHashLock);
1750  ereport(ERROR,
1751  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1752  errmsg("could not import the requested snapshot"),
1753  errdetail("The source transaction %u is not running anymore.",
1754  sourcexid)));
1755  }
1756 
1757  /*
1758  * If there are no serializable transactions which are not read-only, we
1759  * can "opt out" of predicate locking and conflict checking for a
1760  * read-only transaction.
1761  *
1762  * The reason this is safe is that a read-only transaction can only become
1763  * part of a dangerous structure if it overlaps a writable transaction
1764  * which in turn overlaps a writable transaction which committed before
1765  * the read-only transaction started. A new writable transaction can
1766  * overlap this one, but it can't meet the other condition of overlapping
1767  * a transaction which committed before this one started.
1768  */
1770  {
1771  ReleasePredXact(sxact);
1772  LWLockRelease(SerializableXactHashLock);
1773  return snapshot;
1774  }
1775 
1776  /* Maintain serializable global xmin info. */
1778  {
1780  PredXact->SxactGlobalXmin = snapshot->xmin;
1782  OldSerXidSetActiveSerXmin(snapshot->xmin);
1783  }
1784  else if (TransactionIdEquals(snapshot->xmin, PredXact->SxactGlobalXmin))
1785  {
1788  }
1789  else
1790  {
1792  }
1793 
1794  /* Initialize the structure. */
1795  sxact->vxid = vxid;
1799  SHMQueueInit(&(sxact->outConflicts));
1800  SHMQueueInit(&(sxact->inConflicts));
1802  sxact->topXid = GetTopTransactionIdIfAny();
1804  sxact->xmin = snapshot->xmin;
1805  sxact->pid = MyProcPid;
1806  SHMQueueInit(&(sxact->predicateLocks));
1807  SHMQueueElemInit(&(sxact->finishedLink));
1808  sxact->flags = 0;
1809  if (XactReadOnly)
1810  {
1811  sxact->flags |= SXACT_FLAG_READ_ONLY;
1812 
1813  /*
1814  * Register all concurrent r/w transactions as possible conflicts; if
1815  * all of them commit without any outgoing conflicts to earlier
1816  * transactions then this snapshot can be deemed safe (and we can run
1817  * without tracking predicate locks).
1818  */
1819  for (othersxact = FirstPredXact();
1820  othersxact != NULL;
1821  othersxact = NextPredXact(othersxact))
1822  {
1823  if (!SxactIsCommitted(othersxact)
1824  && !SxactIsDoomed(othersxact)
1825  && !SxactIsReadOnly(othersxact))
1826  {
1827  SetPossibleUnsafeConflict(sxact, othersxact);
1828  }
1829  }
1830  }
1831  else
1832  {
1836  }
1837 
1838  MySerializableXact = sxact;
1839  MyXactDidWrite = false; /* haven't written anything yet */
1840 
1841  LWLockRelease(SerializableXactHashLock);
1842 
1843  /* Initialize the backend-local hash table of parent locks */
1845  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
1846  hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
1847  hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
1848  LocalPredicateLockHash = hash_create("Local predicate lock",
1850  &hash_ctl,
1851  HASH_ELEM | HASH_BLOBS);
1852 
1853  return snapshot;
1854 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
TransactionId finishedBefore
bool ProcArrayInstallImportedXmin(TransactionId xmin, TransactionId sourcexid)
Definition: procarray.c:1796
int MyProcPid
Definition: globals.c:38
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:81
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
#define HASH_ELEM
Definition: hsearch.h:87
PGPROC * MyProc
Definition: proc.c:67
static PredXactList PredXact
Definition: predicate.c:374
TransactionId SxactGlobalXmin
Size entrysize
Definition: hsearch.h:73
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
bool RecoveryInProgress(void)
Definition: xlog.c:7873
int max_predicate_locks_per_xact
Definition: predicate.c:361
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
bool IsInParallelMode(void)
Definition: xact.c:913
SHM_QUEUE possibleUnsafeConflicts
#define ERROR
Definition: elog.h:43
int max_prepared_xacts
Definition: twophase.c:117
#define InvalidSerializableXact
static void ReleasePredXact(SERIALIZABLEXACT *sxact)
Definition: predicate.c:580
int MaxBackends
Definition: globals.c:126
struct LOCALPREDICATELOCK LOCALPREDICATELOCK
VirtualTransactionId vxid
static SERIALIZABLEXACT * NextPredXact(SERIALIZABLEXACT *sxact)
Definition: predicate.c:610
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define InvalidTransactionId
Definition: transam.h:31
TransactionId xmin
Definition: snapshot.h:66
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:404
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
static SERIALIZABLEXACT * FirstPredXact(void)
Definition: predicate.c:595
SerCommitSeqNo commitSeqNo
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
union SERIALIZABLEXACT::@100 SeqNo
bool XactReadOnly
Definition: xact.c:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:988
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1508
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
SerCommitSeqNo LastSxactCommitSeqNo
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
static void SetPossibleUnsafeConflict(SERIALIZABLEXACT *roXact, SERIALIZABLEXACT *activeXact)
Definition: predicate.c:695
#define SXACT_FLAG_READ_ONLY
static void SummarizeOldestCommittedSxact(void)
Definition: predicate.c:1441
static bool MyXactDidWrite
Definition: predicate.c:412
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:94
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:563
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
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
static int MaxPredicateChildLocks ( const PREDICATELOCKTARGETTAG tag)
static

Definition at line 2195 of file predicate.c.

References Assert, GET_PREDICATELOCKTARGETTAG_TYPE, max_predicate_locks_per_page, max_predicate_locks_per_relation, max_predicate_locks_per_xact, PREDLOCKTAG_PAGE, PREDLOCKTAG_RELATION, and PREDLOCKTAG_TUPLE.

Referenced by CheckAndPromotePredicateLockRequest().

2196 {
2197  switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag))
2198  {
2199  case PREDLOCKTAG_RELATION:
2204 
2205  case PREDLOCKTAG_PAGE:
2207 
2208  case PREDLOCKTAG_TUPLE:
2209 
2210  /*
2211  * not reachable: nothing is finer-granularity than a tuple, so we
2212  * should never try to promote to it.
2213  */
2214  Assert(false);
2215  return 0;
2216  }
2217 
2218  /* not reachable */
2219  Assert(false);
2220  return 0;
2221 }
int max_predicate_locks_per_xact
Definition: predicate.c:361
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define Assert(condition)
Definition: c.h:675
int max_predicate_locks_per_relation
Definition: predicate.c:362
int max_predicate_locks_per_page
Definition: predicate.c:363
static SERIALIZABLEXACT * NextPredXact ( SERIALIZABLEXACT sxact)
static

Definition at line 610 of file predicate.c.

References PredXactListData::activeList, Assert, PredXactListElementData::link, NULL, offsetof, ShmemAddrIsValid(), SHMQueueNext(), and PredXactListElementData::sxact.

Referenced by GetSafeSnapshotBlockingPids(), GetSerializableTransactionSnapshotInt(), and SetNewSxactGlobalXmin().

611 {
612  PredXactListElement ptle;
613 
614  Assert(ShmemAddrIsValid(sxact));
615 
616  ptle = (PredXactListElement)
617  (((char *) sxact)
620  ptle = (PredXactListElement)
622  &ptle->link,
624  if (!ptle)
625  return NULL;
626 
627  return &ptle->sxact;
628 }
static PredXactList PredXact
Definition: predicate.c:374
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
bool ShmemAddrIsValid(const void *addr)
Definition: shmem.c:263
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
struct PredXactListElementData * PredXactListElement
#define offsetof(type, field)
Definition: c.h:555
static void OldSerXidAdd ( TransactionId  xid,
SerCommitSeqNo  minConflictCommitSeqNo 
)
static

Definition at line 835 of file predicate.c.

References Assert, ereport, errhint(), errmsg(), FirstNormalTransactionId, OldSerXidControlData::headPage, OldSerXidControlData::headXid, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), OldSerXidNextPage, OldSerXidPage, OldSerXidPagePrecedesLogically(), OldSerXidSlruCtl, OldSerXidValue, SimpleLruReadPage(), SimpleLruZeroPage(), OldSerXidControlData::tailXid, TransactionIdFollows(), TransactionIdIsValid, TransactionIdPrecedes(), WARNING, and OldSerXidControlData::warningIssued.

Referenced by SummarizeOldestCommittedSxact().

836 {
837  TransactionId tailXid;
838  int targetPage;
839  int slotno;
840  int firstZeroPage;
841  bool isNewPage;
842 
844 
845  targetPage = OldSerXidPage(xid);
846 
847  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
848 
849  /*
850  * If no serializable transactions are active, there shouldn't be anything
851  * to push out to the SLRU. Hitting this assert would mean there's
852  * something wrong with the earlier cleanup logic.
853  */
854  tailXid = oldSerXidControl->tailXid;
855  Assert(TransactionIdIsValid(tailXid));
856 
857  /*
858  * If the SLRU is currently unused, zero out the whole active region from
859  * tailXid to headXid before taking it into use. Otherwise zero out only
860  * any new pages that enter the tailXid-headXid range as we advance
861  * headXid.
862  */
863  if (oldSerXidControl->headPage < 0)
864  {
865  firstZeroPage = OldSerXidPage(tailXid);
866  isNewPage = true;
867  }
868  else
869  {
870  firstZeroPage = OldSerXidNextPage(oldSerXidControl->headPage);
872  targetPage);
873  }
874 
877  oldSerXidControl->headXid = xid;
878  if (isNewPage)
879  oldSerXidControl->headPage = targetPage;
880 
881  /*
882  * Give a warning if we're about to run out of SLRU pages.
883  *
884  * slru.c has a maximum of 64k segments, with 32 (SLRU_PAGES_PER_SEGMENT)
885  * pages each. We need to store a 64-bit integer for each Xid, and with
886  * default 8k block size, 65536*32 pages is only enough to cover 2^30
887  * XIDs. If we're about to hit that limit and wrap around, warn the user.
888  *
889  * To avoid spamming the user, we only give one warning when we've used 1
890  * billion XIDs, and stay silent until the situation is fixed and the
891  * number of XIDs used falls below 800 million again.
892  *
893  * XXX: We have no safeguard to actually *prevent* the wrap-around,
894  * though. All you get is a warning.
895  */
897  {
898  TransactionId lowWatermark;
899 
900  lowWatermark = tailXid + 800000000;
901  if (lowWatermark < FirstNormalTransactionId)
902  lowWatermark = FirstNormalTransactionId;
903  if (TransactionIdPrecedes(xid, lowWatermark))
905  }
906  else
907  {
908  TransactionId highWatermark;
909 
910  highWatermark = tailXid + 1000000000;
911  if (highWatermark < FirstNormalTransactionId)
912  highWatermark = FirstNormalTransactionId;
913  if (TransactionIdFollows(xid, highWatermark))
914  {
917  (errmsg("memory for serializable conflict tracking is nearly exhausted"),
918  errhint("There might be an idle transaction or a forgotten prepared transaction causing this.")));
919  }
920  }
921 
922  if (isNewPage)
923  {
924  /* Initialize intervening pages. */
925  while (firstZeroPage != targetPage)
926  {
927  (void) SimpleLruZeroPage(OldSerXidSlruCtl, firstZeroPage);
928  firstZeroPage = OldSerXidNextPage(firstZeroPage);
929  }
930  slotno = SimpleLruZeroPage(OldSerXidSlruCtl, targetPage);
931  }
932  else
933  slotno = SimpleLruReadPage(OldSerXidSlruCtl, targetPage, true, xid);
934 
935  OldSerXidValue(slotno, xid) = minConflictCommitSeqNo;
936  OldSerXidSlruCtl->shared->page_dirty[slotno] = true;
937 
938  LWLockRelease(OldSerXidLock);
939 }
int errhint(const char *fmt,...)
Definition: elog.c:987
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:397
#define OldSerXidPage(xid)
Definition: predicate.c:331
#define OldSerXidSlruCtl
Definition: predicate.c:312
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define FirstNormalTransactionId
Definition: transam.h:34
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:371
TransactionId headXid
Definition: predicate.c:337
#define ereport(elevel, rest)
Definition: elog.h:122
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define WARNING
Definition: elog.h:40
#define Assert(condition)
Definition: c.h:675
static bool OldSerXidPagePrecedesLogically(int p, int q)
Definition: predicate.c:774
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static OldSerXidControl oldSerXidControl
Definition: predicate.c:344
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define OldSerXidValue(slotno, xid)
Definition: predicate.c:327
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
Definition: slru.c:259
#define OldSerXidNextPage(page)
Definition: predicate.c:325
TransactionId tailXid
Definition: predicate.c:338
static SerCommitSeqNo OldSerXidGetMinConflictCommitSeqNo ( TransactionId  xid)
static

Definition at line 947 of file predicate.c.

References Assert, OldSerXidControlData::headXid, LW_SHARED, LWLockAcquire(), LWLockRelease(), OldSerXidPage, OldSerXidSlruCtl, OldSerXidValue, SimpleLruReadPage_ReadOnly(), OldSerXidControlData::tailXid, TransactionIdFollows(), TransactionIdIsValid, TransactionIdPrecedes(), and val.

Referenced by CheckForSerializableConflictOut().

948 {
949  TransactionId headXid;
950  TransactionId tailXid;
952  int slotno;
953 
955 
956  LWLockAcquire(OldSerXidLock, LW_SHARED);
957  headXid = oldSerXidControl->headXid;
958  tailXid = oldSerXidControl->tailXid;
959  LWLockRelease(OldSerXidLock);
960 
961  if (!TransactionIdIsValid(headXid))
962  return 0;
963 
964  Assert(TransactionIdIsValid(tailXid));
965 
966  if (TransactionIdPrecedes(xid, tailXid)
967  || TransactionIdFollows(xid, headXid))
968  return 0;
969 
970  /*
971  * The following function must be called without holding OldSerXidLock,
972  * but will return with that lock held, which must then be released.
973  */
975  OldSerXidPage(xid), xid);
976  val = OldSerXidValue(slotno, xid);
977  LWLockRelease(OldSerXidLock);
978  return val;
979 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:397
#define OldSerXidPage(xid)
Definition: predicate.c:331
#define OldSerXidSlruCtl
Definition: predicate.c:312
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
TransactionId headXid
Definition: predicate.c:337
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:463
uint64 SerCommitSeqNo
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static OldSerXidControl oldSerXidControl
Definition: predicate.c:344
#define OldSerXidValue(slotno, xid)
Definition: predicate.c:327
#define TransactionIdIsValid(xid)
Definition: transam.h:41
long val
Definition: informix.c:689
TransactionId tailXid
Definition: predicate.c:338
static void OldSerXidInit ( void  )
static

Definition at line 797 of file predicate.c.

References OldSerXidControlData::headPage, OldSerXidControlData::headXid, InvalidTransactionId, LWTRANCHE_OLDSERXID_BUFFERS, NUM_OLDSERXID_BUFFERS, OldSerXidPagePrecedesLogically(), OldSerXidSlruCtl, ShmemInitStruct(), SimpleLruInit(), OldSerXidControlData::tailXid, and OldSerXidControlData::warningIssued.

Referenced by InitPredicateLocks().

798 {
799  bool found;
800 
801  /*
802  * Set up SLRU management of the pg_serial data.
803  */
805  SimpleLruInit(OldSerXidSlruCtl, "oldserxid",
806  NUM_OLDSERXID_BUFFERS, 0, OldSerXidLock, "pg_serial",
808  /* Override default assumption that writes should be fsync'd */
809  OldSerXidSlruCtl->do_fsync = false;
810 
811  /*
812  * Create or attach to the OldSerXidControl structure.
813  */
815  ShmemInitStruct("OldSerXidControlData", sizeof(OldSerXidControlData), &found);
816 
817  if (!found)
818  {
819  /*
820  * Set control information to reflect empty SLRU.
821  */
826  }
827 }
struct OldSerXidControlData * OldSerXidControl
Definition: predicate.c:342
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:30
#define OldSerXidSlruCtl
Definition: predicate.c:312
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
#define InvalidTransactionId
Definition: transam.h:31
TransactionId headXid
Definition: predicate.c:337
static bool OldSerXidPagePrecedesLogically(int p, int q)
Definition: predicate.c:774
static OldSerXidControl oldSerXidControl
Definition: predicate.c:344
TransactionId tailXid
Definition: predicate.c:338
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
Definition: slru.c:165
static bool OldSerXidPagePrecedesLogically ( int  p,
int  q 
)
static

Definition at line 774 of file predicate.c.

References Assert, and OLDSERXID_MAX_PAGE.

Referenced by OldSerXidAdd(), and OldSerXidInit().

775 {
776  int diff;
777 
778  /*
779  * We have to compare modulo (OLDSERXID_MAX_PAGE+1)/2. Both inputs should
780  * be in the range 0..OLDSERXID_MAX_PAGE.
781  */
782  Assert(p >= 0 && p <= OLDSERXID_MAX_PAGE);
783  Assert(q >= 0 && q <= OLDSERXID_MAX_PAGE);
784 
785  diff = p - q;
786  if (diff >= ((OLDSERXID_MAX_PAGE + 1) / 2))
787  diff -= OLDSERXID_MAX_PAGE + 1;
788  else if (diff < -((int) (OLDSERXID_MAX_PAGE + 1) / 2))
789  diff += OLDSERXID_MAX_PAGE + 1;
790  return diff < 0;
791 }
#define OLDSERXID_MAX_PAGE
Definition: predicate.c:322
#define Assert(condition)
Definition: c.h:675
static void OldSerXidSetActiveSerXmin ( TransactionId  xid)
static

Definition at line 988 of file predicate.c.

References Assert, OldSerXidControlData::headPage, OldSerXidControlData::headXid, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), RecoveryInProgress(), OldSerXidControlData::tailXid, TransactionIdFollows(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by GetSerializableTransactionSnapshotInt(), predicatelock_twophase_recover(), and SetNewSxactGlobalXmin().

989 {
990  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
991 
992  /*
993  * When no sxacts are active, nothing overlaps, set the xid values to
994  * invalid to show that there are no valid entries. Don't clear headPage,
995  * though. A new xmin might still land on that page, and we don't want to
996  * repeatedly zero out the same page.
997  */
998  if (!TransactionIdIsValid(xid))
999  {
1002  LWLockRelease(OldSerXidLock);
1003  return;
1004  }
1005 
1006  /*
1007  * When we're recovering prepared transactions, the global xmin might move
1008  * backwards depending on the order they're recovered. Normally that's not
1009  * OK, but during recovery no serializable transactions will commit, so
1010  * the SLRU is empty and we can get away with it.
1011  */
1012  if (RecoveryInProgress())
1013  {
1017  {
1018  oldSerXidControl->tailXid = xid;
1019  }
1020  LWLockRelease(OldSerXidLock);
1021  return;
1022  }
1023 
1026 
1027  oldSerXidControl->tailXid = xid;
1028 
1029  LWLockRelease(OldSerXidLock);
1030 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
bool RecoveryInProgress(void)
Definition: xlog.c:7873
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define InvalidTransactionId
Definition: transam.h:31
TransactionId headXid
Definition: predicate.c:337
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:675
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
static void OnConflict_CheckForSerializationFailure ( const SERIALIZABLEXACT reader,
SERIALIZABLEXACT writer 
)
static

Definition at line 4518 of file predicate.c.

References Assert, SERIALIZABLEXACT::commitSeqNo, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, SERIALIZABLEXACT::flags, SERIALIZABLEXACT::inConflicts, RWConflictData::inLink, SERIALIZABLEXACT::lastCommitBeforeSnapshot, LWLockHeldByMe(), LWLockRelease(), NULL, offsetof, SERIALIZABLEXACT::outConflicts, RWConflictData::outLink, SERIALIZABLEXACT::prepareSeqNo, SERIALIZABLEXACT::SeqNo, SHMQueueNext(), SXACT_FLAG_DOOMED, SxactHasConflictOut, SxactHasSummaryConflictIn, SxactHasSummaryConflictOut, RWConflictData::sxactIn, SxactIsCommitted, SxactIsDoomed, SxactIsPrepared, SxactIsReadOnly, RWConflictData::sxactOut, and SERIALIZABLEXACT::topXid.

Referenced by FlagRWConflict().

4520 {
4521  bool failure;
4522  RWConflict conflict;
4523 
4524  Assert(LWLockHeldByMe(SerializableXactHashLock));
4525 
4526  failure = false;
4527 
4528  /*------------------------------------------------------------------------
4529  * Check for already-committed writer with rw-conflict out flagged
4530  * (conflict-flag on W means that T2 committed before W):
4531  *
4532  * R ------> W ------> T2
4533  * rw rw
4534  *
4535  * That is a dangerous structure, so we must abort. (Since the writer
4536  * has already committed, we must be the reader)
4537  *------------------------------------------------------------------------
4538  */
4539  if (SxactIsCommitted(writer)
4540  && (SxactHasConflictOut(writer) || SxactHasSummaryConflictOut(writer)))
4541  failure = true;
4542 
4543  /*------------------------------------------------------------------------
4544  * Check whether the writer has become a pivot with an out-conflict
4545  * committed transaction (T2), and T2 committed first:
4546  *
4547  * R ------> W ------> T2
4548  * rw rw
4549  *
4550  * Because T2 must've committed first, there is no anomaly if:
4551  * - the reader committed before T2
4552  * - the writer committed before T2
4553  * - the reader is a READ ONLY transaction and the reader was concurrent
4554  * with T2 (= reader acquired its snapshot before T2 committed)
4555  *
4556  * We also handle the case that T2 is prepared but not yet committed
4557  * here. In that case T2 has already checked for conflicts, so if it
4558  * commits first, making the above conflict real, it's too late for it
4559  * to abort.
4560  *------------------------------------------------------------------------
4561  */
4562  if (!failure)
4563  {
4564  if (SxactHasSummaryConflictOut(writer))
4565  {
4566  failure = true;
4567  conflict = NULL;
4568  }
4569  else
4570  conflict = (RWConflict)
4571  SHMQueueNext(&writer->outConflicts,
4572  &writer->outConflicts,
4573  offsetof(RWConflictData, outLink));
4574  while (conflict)
4575  {
4576  SERIALIZABLEXACT *t2 = conflict->sxactIn;
4577 
4578  if (SxactIsPrepared(t2)
4579  && (!SxactIsCommitted(reader)
4580  || t2->prepareSeqNo <= reader->commitSeqNo)
4581  && (!SxactIsCommitted(writer)
4582  || t2->prepareSeqNo <= writer->commitSeqNo)
4583  && (!SxactIsReadOnly(reader)
4584  || t2->prepareSeqNo <= reader->SeqNo.lastCommitBeforeSnapshot))
4585  {
4586  failure = true;
4587  break;
4588  }
4589  conflict = (RWConflict)
4590  SHMQueueNext(&writer->outConflicts,
4591  &conflict->outLink,
4592  offsetof(RWConflictData, outLink));
4593  }
4594  }
4595 
4596  /*------------------------------------------------------------------------
4597  * Check whether the reader has become a pivot with a writer
4598  * that's committed (or prepared):
4599  *
4600  * T0 ------> R ------> W
4601  * rw rw
4602  *
4603  * Because W must've committed first for an anomaly to occur, there is no
4604  * anomaly if:
4605  * - T0 committed before the writer
4606  * - T0 is READ ONLY, and overlaps the writer
4607  *------------------------------------------------------------------------
4608  */
4609  if (!failure && SxactIsPrepared(writer) && !SxactIsReadOnly(reader))
4610  {
4611  if (SxactHasSummaryConflictIn(reader))
4612  {
4613  failure = true;
4614  conflict = NULL;
4615  }
4616  else
4617  conflict = (RWConflict)
4618  SHMQueueNext(&reader->inConflicts,
4619  &reader->inConflicts,
4620  offsetof(RWConflictData, inLink));
4621  while (conflict)
4622  {
4623  SERIALIZABLEXACT *t0 = conflict->sxactOut;
4624 
4625  if (!SxactIsDoomed(t0)
4626  && (!SxactIsCommitted(t0)
4627  || t0->commitSeqNo >= writer->prepareSeqNo)
4628  && (!SxactIsReadOnly(t0)
4629  || t0->SeqNo.lastCommitBeforeSnapshot >= writer->prepareSeqNo))
4630  {
4631  failure = true;
4632  break;
4633  }
4634  conflict = (RWConflict)
4635  SHMQueueNext(&reader->inConflicts,
4636  &conflict->inLink,
4637  offsetof(RWConflictData, inLink));
4638  }
4639  }
4640 
4641  if (failure)
4642  {
4643  /*
4644  * We have to kill a transaction to avoid a possible anomaly from
4645  * occurring. If the writer is us, we can just ereport() to cause a
4646  * transaction abort. Otherwise we flag the writer for termination,
4647  * causing it to abort when it tries to commit. However, if the writer
4648  * is a prepared transaction, already prepared, we can't abort it
4649  * anymore, so we have to kill the reader instead.
4650  */
4651  if (MySerializableXact == writer)
4652  {
4653  LWLockRelease(SerializableXactHashLock);
4654  ereport(ERROR,
4655  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4656  errmsg("could not serialize access due to read/write dependencies among transactions"),
4657  errdetail_internal("Reason code: Canceled on identification as a pivot, during write."),
4658  errhint("The transaction might succeed if retried.")));
4659  }
4660  else if (SxactIsPrepared(writer))
4661  {
4662  LWLockRelease(SerializableXactHashLock);
4663 
4664  /* if we're not the writer, we have to be the reader */
4665  Assert(MySerializableXact == reader);
4666  ereport(ERROR,
4667  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4668  errmsg("could not serialize access due to read/write dependencies among transactions"),
4669  errdetail_internal("Reason code: Canceled on conflict out to pivot %u, during read.", writer->topXid),
4670  errhint("The transaction might succeed if retried.")));
4671  }
4672  writer->flags |= SXACT_FLAG_DOOMED;
4673  }
4674 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:268
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:411
int errhint(const char *fmt,...)
Definition: elog.c:987
#define SxactHasSummaryConflictIn(sxact)
Definition: predicate.c:269
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1831
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
SERIALIZABLEXACT * sxactIn
#define SxactIsDoomed(sxact)
Definition: predicate.c:267
#define ERROR
Definition: elog.h:43
SerCommitSeqNo lastCommitBeforeSnapshot
#define ereport(elevel, rest)
Definition: elog.h:122
#define SxactHasSummaryConflictOut(sxact)
Definition: predicate.c:270
SerCommitSeqNo commitSeqNo
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
union SERIALIZABLEXACT::@100 SeqNo
#define SXACT_FLAG_DOOMED
#define SxactHasConflictOut(sxact)
Definition: predicate.c:276
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
SerCommitSeqNo prepareSeqNo
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SxactIsCommitted(sxact)
Definition: predicate.c:264
#define offsetof(type, field)
Definition: c.h:555
SERIALIZABLEXACT * sxactOut
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
static uint32 predicatelock_hash ( const void *  key,
Size  keysize 
)
static

Definition at line 1357 of file predicate.c.

References Assert, PREDICATELOCKTAG::myTarget, PredicateLockHashCodeFromTargetHashCode, PredicateLockTargetTagHashCode, and PREDICATELOCKTARGET::tag.

Referenced by InitPredicateLocks().

1358 {
1359  const PREDICATELOCKTAG *predicatelocktag = (const PREDICATELOCKTAG *) key;
1360  uint32 targethash;
1361 
1362  Assert(keysize == sizeof(PREDICATELOCKTAG));
1363 
1364  /* Look into the associated target object, and compute its hash code */
1365  targethash = PredicateLockTargetTagHashCode(&predicatelocktag->myTarget->tag);
1366 
1367  return PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash);
1368 }
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:302
unsigned int uint32
Definition: c.h:268
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
PREDICATELOCKTARGETTAG tag
#define Assert(condition)
Definition: c.h:675
PREDICATELOCKTARGET * myTarget
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