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, VirtualTransactionId *sourcevxid, int sourcepid)
 
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, VirtualTransactionId *sourcevxid, int sourcepid)
 
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 253 of file predicate.c.

Referenced by InitPredicateLocks(), and PredicateLockShmemSize().

#define OLDSERXID_ENTRIESPERPAGE   (OLDSERXID_PAGESIZE / OLDSERXID_ENTRYSIZE)

Definition at line 318 of file predicate.c.

#define OLDSERXID_ENTRYSIZE   sizeof(SerCommitSeqNo)

Definition at line 317 of file predicate.c.

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

Definition at line 324 of file predicate.c.

Referenced by OldSerXidPagePrecedesLogically().

#define OLDSERXID_PAGESIZE   BLCKSZ

Definition at line 316 of file predicate.c.

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

Definition at line 327 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 334 of file predicate.c.

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

Definition at line 329 of file predicate.c.

Referenced by OldSerXidAdd(), and OldSerXidGetMinConflictCommitSeqNo().

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

Definition at line 245 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 279 of file predicate.c.

Referenced by GetSafeSnapshotBlockingPids(), and ReleasePredicateLocks().

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

Definition at line 256 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 281 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 222 of file predicate.c.

Referenced by DeleteChildTargetLocks().

Typedef Documentation

Definition at line 344 of file predicate.c.

Function Documentation

void AtPrepare_PredicateLocks ( void  )

Definition at line 4805 of file predicate.c.

References TwoPhasePredicateRecord::data, SERIALIZABLEXACT::flags, TwoPhasePredicateXactRecord::flags, InvalidSerializableXact, TwoPhasePredicateRecord::lockRecord, LW_SHARED, LWLockAcquire(), LWLockRelease(), MySerializableXact, PREDICATELOCKTAG::myTarget, 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().

4806 {
4807  PREDICATELOCK *predlock;
4808  SERIALIZABLEXACT *sxact;
4809  TwoPhasePredicateRecord record;
4810  TwoPhasePredicateXactRecord *xactRecord;
4811  TwoPhasePredicateLockRecord *lockRecord;
4812 
4813  sxact = MySerializableXact;
4814  xactRecord = &(record.data.xactRecord);
4815  lockRecord = &(record.data.lockRecord);
4816 
4818  return;
4819 
4820  /* Generate an xact record for our SERIALIZABLEXACT */
4822  xactRecord->xmin = MySerializableXact->xmin;
4823  xactRecord->flags = MySerializableXact->flags;
4824 
4825  /*
4826  * Note that we don't include the list of conflicts in our out in the
4827  * statefile, because new conflicts can be added even after the
4828  * transaction prepares. We'll just make a conservative assumption during
4829  * recovery instead.
4830  */
4831 
4833  &record, sizeof(record));
4834 
4835  /*
4836  * Generate a lock record for each lock.
4837  *
4838  * To do this, we need to walk the predicate lock list in our sxact rather
4839  * than using the local predicate lock table because the latter is not
4840  * guaranteed to be accurate.
4841  */
4842  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4843 
4844  predlock = (PREDICATELOCK *)
4845  SHMQueueNext(&(sxact->predicateLocks),
4846  &(sxact->predicateLocks),
4847  offsetof(PREDICATELOCK, xactLink));
4848 
4849  while (predlock != NULL)
4850  {
4852  lockRecord->target = predlock->tag.myTarget->tag;
4853 
4855  &record, sizeof(record));
4856 
4857  predlock = (PREDICATELOCK *)
4858  SHMQueueNext(&(sxact->predicateLocks),
4859  &(predlock->xactLink),
4860  offsetof(PREDICATELOCK, xactLink));
4861  }
4862 
4863  LWLockRelease(SerializablePredicateLockListLock);
4864 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
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:1721
#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
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
union TwoPhasePredicateRecord::@101 data
TwoPhasePredicateLockRecord lockRecord
#define offsetof(type, field)
Definition: c.h:549
PREDICATELOCKTARGET * myTarget
static bool CheckAndPromotePredicateLockRequest ( const PREDICATELOCKTARGETTAG reqtag)
static

Definition at line 2251 of file predicate.c.

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

Referenced by PredicateLockAcquire().

2252 {
2253  PREDICATELOCKTARGETTAG targettag,
2254  nexttag,
2255  promotiontag;
2256  LOCALPREDICATELOCK *parentlock;
2257  bool found,
2258  promote;
2259 
2260  promote = false;
2261 
2262  targettag = *reqtag;
2263 
2264  /* check parents iteratively */
2265  while (GetParentPredicateLockTag(&targettag, &nexttag))
2266  {
2267  targettag = nexttag;
2269  &targettag,
2270  HASH_ENTER,
2271  &found);
2272  if (!found)
2273  {
2274  parentlock->held = false;
2275  parentlock->childLocks = 1;
2276  }
2277  else
2278  parentlock->childLocks++;
2279 
2280  if (parentlock->childLocks >
2281  MaxPredicateChildLocks(&targettag))
2282  {
2283  /*
2284  * We should promote to this parent lock. Continue to check its
2285  * ancestors, however, both to get their child counts right and to
2286  * check whether we should just go ahead and promote to one of
2287  * them.
2288  */
2289  promotiontag = targettag;
2290  promote = true;
2291  }
2292  }
2293 
2294  if (promote)
2295  {
2296  /* acquire coarsest ancestor eligible for promotion */
2297  PredicateLockAcquire(&promotiontag);
2298  return true;
2299  }
2300  else
2301  return false;
2302 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2439
static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag)
Definition: predicate.c:2214
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1993
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
void CheckForSerializableConflictIn ( Relation  relation,
HeapTuple  tuple,
Buffer  buffer 
)

Definition at line 4326 of file predicate.c.

References BufferGetBlockNumber(), BufferIsValid, CheckTargetForConflictsIn(), RelFileNode::dbNode, ereport, errcode(), errdetail_internal(), errhint(), errmsg(), ERROR, ItemPointerGetBlockNumber, ItemPointerGetOffsetNumber, MyXactDidWrite, 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().

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

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

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

Definition at line 1043 of file predicate.c.

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

Referenced by CheckPointGuts().

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

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

4411 {
4412  HASH_SEQ_STATUS seqstat;
4413  PREDICATELOCKTARGET *target;
4414  Oid dbId;
4415  Oid heapId;
4416  int i;
4417 
4418  /*
4419  * Bail out quickly if there are no serializable transactions running.
4420  * It's safe to check this without taking locks because the caller is
4421  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
4422  * would matter here can be acquired while that is held.
4423  */
4425  return;
4426 
4427  if (!SerializationNeededForWrite(relation))
4428  return;
4429 
4430  /*
4431  * We're doing a write which might cause rw-conflicts now or later.
4432  * Memorize that fact.
4433  */
4434  MyXactDidWrite = true;
4435 
4436  Assert(relation->rd_index == NULL); /* not an index relation */
4437 
4438  dbId = relation->rd_node.dbNode;
4439  heapId = relation->rd_id;
4440 
4441  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
4442  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
4444  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4445 
4446  /* Scan through target list */
4448 
4449  while ((target = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
4450  {
4451  PREDICATELOCK *predlock;
4452 
4453  /*
4454  * Check whether this is a target which needs attention.
4455  */
4456  if (GET_PREDICATELOCKTARGETTAG_RELATION(target->tag) != heapId)
4457  continue; /* wrong relation id */
4458  if (GET_PREDICATELOCKTARGETTAG_DB(target->tag) != dbId)
4459  continue; /* wrong database id */
4460 
4461  /*
4462  * Loop through locks for this target and flag conflicts.
4463  */
4464  predlock = (PREDICATELOCK *)
4465  SHMQueueNext(&(target->predicateLocks),
4466  &(target->predicateLocks),
4467  offsetof(PREDICATELOCK, targetLink));
4468  while (predlock)
4469  {
4470  PREDICATELOCK *nextpredlock;
4471 
4472  nextpredlock = (PREDICATELOCK *)
4473  SHMQueueNext(&(target->predicateLocks),
4474  &(predlock->targetLink),
4475  offsetof(PREDICATELOCK, targetLink));
4476 
4477  if (predlock->tag.myXact != MySerializableXact
4479  {
4481  }
4482 
4483  predlock = nextpredlock;
4484  }
4485  }
4486 
4487  /* Release locks in reverse order */
4488  LWLockRelease(SerializableXactHashLock);
4489  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
4491  LWLockRelease(SerializablePredicateLockListLock);
4492 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:639
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4502
static PredXactList PredXact
Definition: predicate.c:376
TransactionId SxactGlobalXmin
static bool SerializationNeededForWrite(Relation relation)
Definition: predicate.c:544
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
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 Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:250
int i
SERIALIZABLEXACT * myXact
static bool MyXactDidWrite
Definition: predicate.c:414
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define offsetof(type, field)
Definition: c.h:549
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
static void CheckTargetForConflictsIn ( PREDICATELOCKTARGETTAG targettag)
static

Definition at line 4148 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, offsetof, PredicateLockHashCodeFromTargetHashCode, PredicateLockHashPartitionLock, PREDICATELOCKTARGET::predicateLocks, PredicateLockTargetTagHashCode, RemoveTargetIfNoLongerUsed(), RWConflictExists(), SHMQueueDelete(), SHMQueueNext(), SxactIsCommitted, SxactIsDoomed, PREDICATELOCK::tag, PREDICATELOCK::targetLink, TransactionIdPrecedes(), and PREDICATELOCK::xactLink.

Referenced by CheckForSerializableConflictIn().

4149 {
4150  uint32 targettaghash;
4151  LWLock *partitionLock;
4152  PREDICATELOCKTARGET *target;
4153  PREDICATELOCK *predlock;
4154  PREDICATELOCK *mypredlock = NULL;
4155  PREDICATELOCKTAG mypredlocktag;
4156 
4158 
4159  /*
4160  * The same hash and LW lock apply to the lock target and the lock itself.
4161  */
4162  targettaghash = PredicateLockTargetTagHashCode(targettag);
4163  partitionLock = PredicateLockHashPartitionLock(targettaghash);
4164  LWLockAcquire(partitionLock, LW_SHARED);
4165  target = (PREDICATELOCKTARGET *)
4167  targettag, targettaghash,
4168  HASH_FIND, NULL);
4169  if (!target)
4170  {
4171  /* Nothing has this target locked; we're done here. */
4172  LWLockRelease(partitionLock);
4173  return;
4174  }
4175 
4176  /*
4177  * Each lock for an overlapping transaction represents a conflict: a
4178  * rw-dependency in to this transaction.
4179  */
4180  predlock = (PREDICATELOCK *)
4181  SHMQueueNext(&(target->predicateLocks),
4182  &(target->predicateLocks),
4183  offsetof(PREDICATELOCK, targetLink));
4184  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4185  while (predlock)
4186  {
4187  SHM_QUEUE *predlocktargetlink;
4188  PREDICATELOCK *nextpredlock;
4189  SERIALIZABLEXACT *sxact;
4190 
4191  predlocktargetlink = &(predlock->targetLink);
4192  nextpredlock = (PREDICATELOCK *)
4193  SHMQueueNext(&(target->predicateLocks),
4194  predlocktargetlink,
4195  offsetof(PREDICATELOCK, targetLink));
4196 
4197  sxact = predlock->tag.myXact;
4198  if (sxact == MySerializableXact)
4199  {
4200  /*
4201  * If we're getting a write lock on a tuple, we don't need a
4202  * predicate (SIREAD) lock on the same tuple. We can safely remove
4203  * our SIREAD lock, but we'll defer doing so until after the loop
4204  * because that requires upgrading to an exclusive partition lock.
4205  *
4206  * We can't use this optimization within a subtransaction because
4207  * the subtransaction could roll back, and we would be left
4208  * without any lock at the top level.
4209  */
4210  if (!IsSubTransaction()
4211  && GET_PREDICATELOCKTARGETTAG_OFFSET(*targettag))
4212  {
4213  mypredlock = predlock;
4214  mypredlocktag = predlock->tag;
4215  }
4216  }
4217  else if (!SxactIsDoomed(sxact)
4218  && (!SxactIsCommitted(sxact)
4220  sxact->finishedBefore))
4222  {
4223  LWLockRelease(SerializableXactHashLock);
4224  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4225 
4226  /*
4227  * Re-check after getting exclusive lock because the other
4228  * transaction may have flagged a conflict.
4229  */
4230  if (!SxactIsDoomed(sxact)
4231  && (!SxactIsCommitted(sxact)
4233  sxact->finishedBefore))
4235  {
4237  }
4238 
4239  LWLockRelease(SerializableXactHashLock);
4240  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
4241  }
4242 
4243  predlock = nextpredlock;
4244  }
4245  LWLockRelease(SerializableXactHashLock);
4246  LWLockRelease(partitionLock);
4247 
4248  /*
4249  * If we found one of our own SIREAD locks to remove, remove it now.
4250  *
4251  * At this point our transaction already has an ExclusiveRowLock on the
4252  * relation, so we are OK to drop the predicate lock on the tuple, if
4253  * found, without fearing that another write against the tuple will occur
4254  * before the MVCC information makes it to the buffer.
4255  */
4256  if (mypredlock != NULL)
4257  {
4258  uint32 predlockhashcode;
4259  PREDICATELOCK *rmpredlock;
4260 
4261  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
4262  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4263  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4264 
4265  /*
4266  * Remove the predicate lock from shared memory, if it wasn't removed
4267  * while the locks were released. One way that could happen is from
4268  * autovacuum cleaning up an index.
4269  */
4270  predlockhashcode = PredicateLockHashCodeFromTargetHashCode
4271  (&mypredlocktag, targettaghash);
4272  rmpredlock = (PREDICATELOCK *)
4274  &mypredlocktag,
4275  predlockhashcode,
4276  HASH_FIND, NULL);
4277  if (rmpredlock != NULL)
4278  {
4279  Assert(rmpredlock == mypredlock);
4280 
4281  SHMQueueDelete(&(mypredlock->targetLink));
4282  SHMQueueDelete(&(mypredlock->xactLink));
4283 
4284  rmpredlock = (PREDICATELOCK *)
4286  &mypredlocktag,
4287  predlockhashcode,
4288  HASH_REMOVE, NULL);
4289  Assert(rmpredlock == mypredlock);
4290 
4291  RemoveTargetIfNoLongerUsed(target, targettaghash);
4292  }
4293 
4294  LWLockRelease(SerializableXactHashLock);
4295  LWLockRelease(partitionLock);
4296  LWLockRelease(SerializablePredicateLockListLock);
4297 
4298  if (rmpredlock != NULL)
4299  {
4300  /*
4301  * Remove entry in local lock table if it exists. It's OK if it
4302  * doesn't exist; that means the lock was transferred to a new
4303  * target by a different backend.
4304  */
4306  targettag, targettaghash,
4307  HASH_REMOVE, NULL);
4308 
4309  DecrementParentLocks(targettag);
4310  }
4311  }
4312 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
TransactionId finishedBefore
Definition: lwlock.h:32
static bool RWConflictExists(const SERIALIZABLEXACT *reader, const SERIALIZABLEXACT *writer)
Definition: predicate.c:639
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
static void FlagRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4502
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2104
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag)
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
static HTAB * PredicateLockHash
Definition: predicate.c:390
#define InvalidSerializableXact
unsigned int uint32
Definition: c.h:258
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2316
PREDICATELOCKTAG tag
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:664
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
bool IsSubTransaction(void)
Definition: xact.c:4528
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
SERIALIZABLEXACT * myXact
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
#define offsetof(type, field)
Definition: c.h:549
static void ClearOldPredicateLocks ( void  )
static

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

3587 {
3588  SERIALIZABLEXACT *finishedSxact;
3589  PREDICATELOCK *predlock;
3590 
3591  /*
3592  * Loop through finished transactions. They are in commit order, so we can
3593  * stop as soon as we find one that's still interesting.
3594  */
3595  LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
3596  finishedSxact = (SERIALIZABLEXACT *)
3599  offsetof(SERIALIZABLEXACT, finishedLink));
3600  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3601  while (finishedSxact)
3602  {
3603  SERIALIZABLEXACT *nextSxact;
3604 
3605  nextSxact = (SERIALIZABLEXACT *)
3607  &(finishedSxact->finishedLink),
3608  offsetof(SERIALIZABLEXACT, finishedLink));
3612  {
3613  /*
3614  * This transaction committed before any in-progress transaction
3615  * took its snapshot. It's no longer interesting.
3616  */
3617  LWLockRelease(SerializableXactHashLock);
3618  SHMQueueDelete(&(finishedSxact->finishedLink));
3619  ReleaseOneSerializableXact(finishedSxact, false, false);
3620  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3621  }
3622  else if (finishedSxact->commitSeqNo > PredXact->HavePartialClearedThrough
3623  && finishedSxact->commitSeqNo <= PredXact->CanPartialClearThrough)
3624  {
3625  /*
3626  * Any active transactions that took their snapshot before this
3627  * transaction committed are read-only, so we can clear part of
3628  * its state.
3629  */
3630  LWLockRelease(SerializableXactHashLock);
3631 
3632  if (SxactIsReadOnly(finishedSxact))
3633  {
3634  /* A read-only transaction can be removed entirely */
3635  SHMQueueDelete(&(finishedSxact->finishedLink));
3636  ReleaseOneSerializableXact(finishedSxact, false, false);
3637  }
3638  else
3639  {
3640  /*
3641  * A read-write transaction can only be partially cleared. We
3642  * need to keep the SERIALIZABLEXACT but can release the
3643  * SIREAD locks and conflicts in.
3644  */
3645  ReleaseOneSerializableXact(finishedSxact, true, false);
3646  }
3647 
3649  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3650  }
3651  else
3652  {
3653  /* Still interesting. */
3654  break;
3655  }
3656  finishedSxact = nextSxact;
3657  }
3658  LWLockRelease(SerializableXactHashLock);
3659 
3660  /*
3661  * Loop through predicate locks on dummy transaction for summarized data.
3662  */
3663  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
3664  predlock = (PREDICATELOCK *)
3667  offsetof(PREDICATELOCK, xactLink));
3668  while (predlock)
3669  {
3670  PREDICATELOCK *nextpredlock;
3671  bool canDoPartialCleanup;
3672 
3673  nextpredlock = (PREDICATELOCK *)
3675  &predlock->xactLink,
3676  offsetof(PREDICATELOCK, xactLink));
3677 
3678  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
3679  Assert(predlock->commitSeqNo != 0);
3681  canDoPartialCleanup = (predlock->commitSeqNo <= PredXact->CanPartialClearThrough);
3682  LWLockRelease(SerializableXactHashLock);
3683 
3684  /*
3685  * If this lock originally belonged to an old enough transaction, we
3686  * can release it.
3687  */
3688  if (canDoPartialCleanup)
3689  {
3690  PREDICATELOCKTAG tag;
3691  PREDICATELOCKTARGET *target;
3692  PREDICATELOCKTARGETTAG targettag;
3693  uint32 targettaghash;
3694  LWLock *partitionLock;
3695 
3696  tag = predlock->tag;
3697  target = tag.myTarget;
3698  targettag = target->tag;
3699  targettaghash = PredicateLockTargetTagHashCode(&targettag);
3700  partitionLock = PredicateLockHashPartitionLock(targettaghash);
3701 
3702  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3703 
3704  SHMQueueDelete(&(predlock->targetLink));
3705  SHMQueueDelete(&(predlock->xactLink));
3706 
3709  targettaghash),
3710  HASH_REMOVE, NULL);
3711  RemoveTargetIfNoLongerUsed(target, targettaghash);
3712 
3713  LWLockRelease(partitionLock);
3714  }
3715 
3716  predlock = nextpredlock;
3717  }
3718 
3719  LWLockRelease(SerializablePredicateLockListLock);
3720  LWLockRelease(SerializableFinishedListLock);
3721 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
TransactionId finishedBefore
Definition: lwlock.h:32
static PredXactList PredXact
Definition: predicate.c:376
TransactionId SxactGlobalXmin
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2104
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
static HTAB * PredicateLockHash
Definition: predicate.c:390
unsigned int uint32
Definition: c.h:258
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
SerCommitSeqNo HavePartialClearedThrough
PREDICATELOCKTAG tag
SerCommitSeqNo CanPartialClearThrough
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
SerCommitSeqNo commitSeqNo
static void ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial, bool summarize)
Definition: predicate.c:3743
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:354
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static SHM_QUEUE * FinishedSerializableTransactions
Definition: predicate.c:391
#define offsetof(type, field)
Definition: c.h:549
PREDICATELOCKTARGET * myTarget
static bool CoarserLockCovers ( const PREDICATELOCKTARGETTAG newtargettag)
static

Definition at line 2032 of file predicate.c.

References GetParentPredicateLockTag(), and PredicateLockExists().

Referenced by PredicateLockAcquire().

2033 {
2034  PREDICATELOCKTARGETTAG targettag,
2035  parenttag;
2036 
2037  targettag = *newtargettag;
2038 
2039  /* check parents iteratively until no more */
2040  while (GetParentPredicateLockTag(&targettag, &parenttag))
2041  {
2042  targettag = parenttag;
2043  if (PredicateLockExists(&targettag))
2044  return true;
2045  }
2046 
2047  /* no more parents to check; lock is not covered */
2048  return false;
2049 }
static bool PredicateLockExists(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:1966
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1993
static void CreatePredicateLock ( const PREDICATELOCKTARGETTAG targettag,
uint32  targettaghash,
SERIALIZABLEXACT sxact 
)
static

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

2381 {
2382  PREDICATELOCKTARGET *target;
2383  PREDICATELOCKTAG locktag;
2384  PREDICATELOCK *lock;
2385  LWLock *partitionLock;
2386  bool found;
2387 
2388  partitionLock = PredicateLockHashPartitionLock(targettaghash);
2389 
2390  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
2391  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2392 
2393  /* Make sure that the target is represented. */
2394  target = (PREDICATELOCKTARGET *)
2396  targettag, targettaghash,
2397  HASH_ENTER_NULL, &found);
2398  if (!target)
2399  ereport(ERROR,
2400  (errcode(ERRCODE_OUT_OF_MEMORY),
2401  errmsg("out of shared memory"),
2402  errhint("You might need to increase max_pred_locks_per_transaction.")));
2403  if (!found)
2404  SHMQueueInit(&(target->predicateLocks));
2405 
2406  /* We've got the sxact and target, make sure they're joined. */
2407  locktag.myTarget = target;
2408  locktag.myXact = sxact;
2409  lock = (PREDICATELOCK *)
2411  PredicateLockHashCodeFromTargetHashCode(&locktag, targettaghash),
2412  HASH_ENTER_NULL, &found);
2413  if (!lock)
2414  ereport(ERROR,
2415  (errcode(ERRCODE_OUT_OF_MEMORY),
2416  errmsg("out of shared memory"),
2417  errhint("You might need to increase max_pred_locks_per_transaction.")));
2418 
2419  if (!found)
2420  {
2421  SHMQueueInsertBefore(&(target->predicateLocks), &(lock->targetLink));
2423  &(lock->xactLink));
2425  }
2426 
2427  LWLockRelease(partitionLock);
2428  LWLockRelease(SerializablePredicateLockListLock);
2429 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
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:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
#define ERROR
Definition: elog.h:43
static HTAB * PredicateLockHash
Definition: predicate.c:390
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
SerCommitSeqNo commitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
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 566 of file predicate.c.

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

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

567 {
568  PredXactListElement ptle;
569 
570  ptle = (PredXactListElement)
574  if (!ptle)
575  return NULL;
576 
577  SHMQueueDelete(&ptle->link);
579  return &ptle->sxact;
580 }
static PredXactList PredXact
Definition: predicate.c:376
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
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
struct PredXactListElementData * PredXactListElement
#define offsetof(type, field)
Definition: c.h:549
static void DecrementParentLocks ( const PREDICATELOCKTARGETTAG targettag)
static

Definition at line 2316 of file predicate.c.

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

Referenced by CheckTargetForConflictsIn(), and DeleteChildTargetLocks().

2317 {
2318  PREDICATELOCKTARGETTAG parenttag,
2319  nexttag;
2320 
2321  parenttag = *targettag;
2322 
2323  while (GetParentPredicateLockTag(&parenttag, &nexttag))
2324  {
2325  uint32 targettaghash;
2326  LOCALPREDICATELOCK *parentlock,
2327  *rmlock PG_USED_FOR_ASSERTS_ONLY;
2328 
2329  parenttag = nexttag;
2330  targettaghash = PredicateLockTargetTagHashCode(&parenttag);
2331  parentlock = (LOCALPREDICATELOCK *)
2333  &parenttag, targettaghash,
2334  HASH_FIND, NULL);
2335 
2336  /*
2337  * There's a small chance the parent lock doesn't exist in the lock
2338  * table. This can happen if we prematurely removed it because an
2339  * index split caused the child refcount to be off.
2340  */
2341  if (parentlock == NULL)
2342  continue;
2343 
2344  parentlock->childLocks--;
2345 
2346  /*
2347  * Under similar circumstances the parent lock's refcount might be
2348  * zero. This only happens if we're holding that lock (otherwise we
2349  * would have removed the entry).
2350  */
2351  if (parentlock->childLocks < 0)
2352  {
2353  Assert(parentlock->held);
2354  parentlock->childLocks = 0;
2355  }
2356 
2357  if ((parentlock->childLocks == 0) && (!parentlock->held))
2358  {
2359  rmlock = (LOCALPREDICATELOCK *)
2361  &parenttag, targettaghash,
2362  HASH_REMOVE, NULL);
2363  Assert(rmlock == parentlock);
2364  }
2365  }
2366 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
unsigned int uint32
Definition: c.h:258
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1993
#define Assert(condition)
Definition: c.h:664
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:979
static void DeleteChildTargetLocks ( const PREDICATELOCKTARGETTAG newtargettag)
static

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

2134 {
2135  SERIALIZABLEXACT *sxact;
2136  PREDICATELOCK *predlock;
2137 
2138  LWLockAcquire(SerializablePredicateLockListLock, LW_SHARED);
2139  sxact = MySerializableXact;
2140  predlock = (PREDICATELOCK *)
2141  SHMQueueNext(&(sxact->predicateLocks),
2142  &(sxact->predicateLocks),
2143  offsetof(PREDICATELOCK, xactLink));
2144  while (predlock)
2145  {
2146  SHM_QUEUE *predlocksxactlink;
2147  PREDICATELOCK *nextpredlock;
2148  PREDICATELOCKTAG oldlocktag;
2149  PREDICATELOCKTARGET *oldtarget;
2150  PREDICATELOCKTARGETTAG oldtargettag;
2151 
2152  predlocksxactlink = &(predlock->xactLink);
2153  nextpredlock = (PREDICATELOCK *)
2154  SHMQueueNext(&(sxact->predicateLocks),
2155  predlocksxactlink,
2156  offsetof(PREDICATELOCK, xactLink));
2157 
2158  oldlocktag = predlock->tag;
2159  Assert(oldlocktag.myXact == sxact);
2160  oldtarget = oldlocktag.myTarget;
2161  oldtargettag = oldtarget->tag;
2162 
2163  if (TargetTagIsCoveredBy(oldtargettag, *newtargettag))
2164  {
2165  uint32 oldtargettaghash;
2166  LWLock *partitionLock;
2168 
2169  oldtargettaghash = PredicateLockTargetTagHashCode(&oldtargettag);
2170  partitionLock = PredicateLockHashPartitionLock(oldtargettaghash);
2171 
2172  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2173 
2174  SHMQueueDelete(predlocksxactlink);
2175  SHMQueueDelete(&(predlock->targetLink));
2176  rmpredlock = hash_search_with_hash_value
2178  &oldlocktag,
2180  oldtargettaghash),
2181  HASH_REMOVE, NULL);
2182  Assert(rmpredlock == predlock);
2183 
2184  RemoveTargetIfNoLongerUsed(oldtarget, oldtargettaghash);
2185 
2186  LWLockRelease(partitionLock);
2187 
2188  DecrementParentLocks(&oldtargettag);
2189  }
2190 
2191  predlock = nextpredlock;
2192  }
2193  LWLockRelease(SerializablePredicateLockListLock);
2194 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
Definition: lwlock.h:32
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2104
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
static HTAB * PredicateLockHash
Definition: predicate.c:390
unsigned int uint32
Definition: c.h:258
static void DecrementParentLocks(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2316
PREDICATELOCKTAG tag
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
PREDICATELOCKTARGETTAG tag
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
#define TargetTagIsCoveredBy(covered_target, covering_target)
Definition: predicate.c:222
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
SERIALIZABLEXACT * myXact
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:979
#define offsetof(type, field)
Definition: c.h:549
PREDICATELOCKTARGET * myTarget
static void DeleteLockTarget ( PREDICATELOCKTARGET target,
uint32  targettaghash 
)
static

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

2609 {
2610  PREDICATELOCK *predlock;
2611  SHM_QUEUE *predlocktargetlink;
2612  PREDICATELOCK *nextpredlock;
2613  bool found;
2614 
2615  Assert(LWLockHeldByMe(SerializablePredicateLockListLock));
2617 
2618  predlock = (PREDICATELOCK *)
2619  SHMQueueNext(&(target->predicateLocks),
2620  &(target->predicateLocks),
2621  offsetof(PREDICATELOCK, targetLink));
2622  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
2623  while (predlock)
2624  {
2625  predlocktargetlink = &(predlock->targetLink);
2626  nextpredlock = (PREDICATELOCK *)
2627  SHMQueueNext(&(target->predicateLocks),
2628  predlocktargetlink,
2629  offsetof(PREDICATELOCK, targetLink));
2630 
2631  SHMQueueDelete(&(predlock->xactLink));
2632  SHMQueueDelete(&(predlock->targetLink));
2633 
2636  &predlock->tag,
2638  targettaghash),
2639  HASH_REMOVE, &found);
2640  Assert(found);
2641 
2642  predlock = nextpredlock;
2643  }
2644  LWLockRelease(SerializableXactHashLock);
2645 
2646  /* Remove the target itself, if possible. */
2647  RemoveTargetIfNoLongerUsed(target, targettaghash);
2648 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1837
static void RemoveTargetIfNoLongerUsed(PREDICATELOCKTARGET *target, uint32 targettaghash)
Definition: predicate.c:2104
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:247
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
static HTAB * PredicateLockHash
Definition: predicate.c:390
PREDICATELOCKTAG tag
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define offsetof(type, field)
Definition: c.h:549
static void DropAllPredicateLocksFromTable ( Relation  relation,
bool  transfer 
)
static

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

2895 {
2896  HASH_SEQ_STATUS seqstat;
2897  PREDICATELOCKTARGET *oldtarget;
2898  PREDICATELOCKTARGET *heaptarget;
2899  Oid dbId;
2900  Oid relId;
2901  Oid heapId;
2902  int i;
2903  bool isIndex;
2904  bool found;
2905  uint32 heaptargettaghash;
2906 
2907  /*
2908  * Bail out quickly if there are no serializable transactions running.
2909  * It's safe to check this without taking locks because the caller is
2910  * holding an ACCESS EXCLUSIVE lock on the relation. No new locks which
2911  * would matter here can be acquired while that is held.
2912  */
2914  return;
2915 
2916  if (!PredicateLockingNeededForRelation(relation))
2917  return;
2918 
2919  dbId = relation->rd_node.dbNode;
2920  relId = relation->rd_id;
2921  if (relation->rd_index == NULL)
2922  {
2923  isIndex = false;
2924  heapId = relId;
2925  }
2926  else
2927  {
2928  isIndex = true;
2929  heapId = relation->rd_index->indrelid;
2930  }
2931  Assert(heapId != InvalidOid);
2932  Assert(transfer || !isIndex); /* index OID only makes sense with
2933  * transfer */
2934 
2935  /* Retrieve first time needed, then keep. */
2936  heaptargettaghash = 0;
2937  heaptarget = NULL;
2938 
2939  /* Acquire locks on all lock partitions */
2940  LWLockAcquire(SerializablePredicateLockListLock, LW_EXCLUSIVE);
2941  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
2943  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
2944 
2945  /*
2946  * Remove the dummy entry to give us scratch space, so we know we'll be
2947  * able to create the new lock target.
2948  */
2949  if (transfer)
2950  RemoveScratchTarget(true);
2951 
2952  /* Scan through target map */
2954 
2955  while ((oldtarget = (PREDICATELOCKTARGET *) hash_seq_search(&seqstat)))
2956  {
2957  PREDICATELOCK *oldpredlock;
2958 
2959  /*
2960  * Check whether this is a target which needs attention.
2961  */
2962  if (GET_PREDICATELOCKTARGETTAG_RELATION(oldtarget->tag) != relId)
2963  continue; /* wrong relation id */
2964  if (GET_PREDICATELOCKTARGETTAG_DB(oldtarget->tag) != dbId)
2965  continue; /* wrong database id */
2966  if (transfer && !isIndex
2968  continue; /* already the right lock */
2969 
2970  /*
2971  * If we made it here, we have work to do. We make sure the heap
2972  * relation lock exists, then we walk the list of predicate locks for
2973  * the old target we found, moving all locks to the heap relation lock
2974  * -- unless they already hold that.
2975  */
2976 
2977  /*
2978  * First make sure we have the heap relation target. We only need to
2979  * do this once.
2980  */
2981  if (transfer && heaptarget == NULL)
2982  {
2983  PREDICATELOCKTARGETTAG heaptargettag;
2984 
2985  SET_PREDICATELOCKTARGETTAG_RELATION(heaptargettag, dbId, heapId);
2986  heaptargettaghash = PredicateLockTargetTagHashCode(&heaptargettag);
2988  &heaptargettag,
2989  heaptargettaghash,
2990  HASH_ENTER, &found);
2991  if (!found)
2992  SHMQueueInit(&heaptarget->predicateLocks);
2993  }
2994 
2995  /*
2996  * Loop through all the locks on the old target, replacing them with
2997  * locks on the new target.
2998  */
2999  oldpredlock = (PREDICATELOCK *)
3000  SHMQueueNext(&(oldtarget->predicateLocks),
3001  &(oldtarget->predicateLocks),
3002  offsetof(PREDICATELOCK, targetLink));
3003  while (oldpredlock)
3004  {
3005  PREDICATELOCK *nextpredlock;
3006  PREDICATELOCK *newpredlock;
3007  SerCommitSeqNo oldCommitSeqNo;
3008  SERIALIZABLEXACT *oldXact;
3009 
3010  nextpredlock = (PREDICATELOCK *)
3011  SHMQueueNext(&(oldtarget->predicateLocks),
3012  &(oldpredlock->targetLink),
3013  offsetof(PREDICATELOCK, targetLink));
3014 
3015  /*
3016  * Remove the old lock first. This avoids the chance of running
3017  * out of lock structure entries for the hash table.
3018  */
3019  oldCommitSeqNo = oldpredlock->commitSeqNo;
3020  oldXact = oldpredlock->tag.myXact;
3021 
3022  SHMQueueDelete(&(oldpredlock->xactLink));
3023 
3024  /*
3025  * No need for retail delete from oldtarget list, we're removing
3026  * the whole target anyway.
3027  */
3029  &oldpredlock->tag,
3030  HASH_REMOVE, &found);
3031  Assert(found);
3032 
3033  if (transfer)
3034  {
3035  PREDICATELOCKTAG newpredlocktag;
3036 
3037  newpredlocktag.myTarget = heaptarget;
3038  newpredlocktag.myXact = oldXact;
3039  newpredlock = (PREDICATELOCK *)
3041  &newpredlocktag,
3043  heaptargettaghash),
3044  HASH_ENTER,
3045  &found);
3046  if (!found)
3047  {
3048  SHMQueueInsertBefore(&(heaptarget->predicateLocks),
3049  &(newpredlock->targetLink));
3050  SHMQueueInsertBefore(&(newpredlocktag.myXact->predicateLocks),
3051  &(newpredlock->xactLink));
3052  newpredlock->commitSeqNo = oldCommitSeqNo;
3053  }
3054  else
3055  {
3056  if (newpredlock->commitSeqNo < oldCommitSeqNo)
3057  newpredlock->commitSeqNo = oldCommitSeqNo;
3058  }
3059 
3060  Assert(newpredlock->commitSeqNo != 0);
3061  Assert((newpredlock->commitSeqNo == InvalidSerCommitSeqNo)
3062  || (newpredlock->tag.myXact == OldCommittedSxact));
3063  }
3064 
3065  oldpredlock = nextpredlock;
3066  }
3067 
3069  &found);
3070  Assert(found);
3071  }
3072 
3073  /* Put the scratch entry back */
3074  if (transfer)
3075  RestoreScratchTarget(true);
3076 
3077  /* Release locks in reverse order */
3078  LWLockRelease(SerializableXactHashLock);
3079  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
3081  LWLockRelease(SerializablePredicateLockListLock);
3082 }
#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:915
static bool PredicateLockingNeededForRelation(Relation relation)
Definition: predicate.c:481
static HTAB * PredicateLockTargetHash
Definition: predicate.c:389
static PredXactList PredXact
Definition: predicate.c:376
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:902
unsigned int Oid
Definition: postgres_ext.h:31
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
static void RemoveScratchTarget(bool lockheld)
Definition: predicate.c:2061
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
Form_pg_index rd_index
Definition: rel.h:159
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
static HTAB * PredicateLockHash
Definition: predicate.c:390
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
unsigned int uint32
Definition: c.h:258
Oid rd_id
Definition: rel.h:116
#define InvalidSerCommitSeqNo
static void RestoreScratchTarget(bool lockheld)
Definition: predicate.c:2082
PREDICATELOCKTAG tag
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
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 Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:354
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:250
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:549
PREDICATELOCKTARGET * myTarget
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
static SERIALIZABLEXACT * FirstPredXact ( void  )
static

Definition at line 598 of file predicate.c.

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

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

599 {
600  PredXactListElement ptle;
601 
602  ptle = (PredXactListElement)
606  if (!ptle)
607  return NULL;
608 
609  return &ptle->sxact;
610 }
static PredXactList PredXact
Definition: predicate.c:376
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
struct PredXactListElementData * PredXactListElement
#define offsetof(type, field)
Definition: c.h:549
static void FlagRWConflict ( SERIALIZABLEXACT reader,
SERIALIZABLEXACT writer 
)
static

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

4503 {
4504  Assert(reader != writer);
4505 
4506  /* First, see if this conflict causes failure. */
4508 
4509  /* Actually do the conflict flagging. */
4510  if (reader == OldCommittedSxact)
4512  else if (writer == OldCommittedSxact)
4514  else
4515  SetRWConflict(reader, writer);
4516 }
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
static void SetRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:672
static void OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4537
#define Assert(condition)
Definition: c.h:664
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:354
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static void FlagSxactUnsafe ( SERIALIZABLEXACT sxact)
static

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

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

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

1995 {
1996  switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag))
1997  {
1998  case PREDLOCKTAG_RELATION:
1999  /* relation locks have no parent lock */
2000  return false;
2001 
2002  case PREDLOCKTAG_PAGE:
2003  /* parent lock is relation lock */
2007 
2008  return true;
2009 
2010  case PREDLOCKTAG_TUPLE:
2011  /* parent lock is page lock */
2016  return true;
2017  }
2018 
2019  /* not reachable */
2020  Assert(false);
2021  return false;
2022 }
#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:664
PredicateLockData* GetPredicateLockStatusData ( void  )

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

1400 {
1401  PredicateLockData *data;
1402  int i;
1403  int els,
1404  el;
1405  HASH_SEQ_STATUS seqstat;
1406  PREDICATELOCK *predlock;
1407 
1408  data = (PredicateLockData *) palloc(sizeof(PredicateLockData));
1409 
1410  /*
1411  * To ensure consistency, take simultaneous locks on all partition locks
1412  * in ascending order, then SerializableXactHashLock.
1413  */
1414  for (i = 0; i < NUM_PREDICATELOCK_PARTITIONS; i++)
1416  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
1417 
1418  /* Get number of locks and allocate appropriately-sized arrays. */
1420  data->nelements = els;
1421  data->locktags = (PREDICATELOCKTARGETTAG *)
1422  palloc(sizeof(PREDICATELOCKTARGETTAG) * els);
1423  data->xacts = (SERIALIZABLEXACT *)
1424  palloc(sizeof(SERIALIZABLEXACT) * els);
1425 
1426 
1427  /* Scan through PredicateLockHash and copy contents */
1428  hash_seq_init(&seqstat, PredicateLockHash);
1429 
1430  el = 0;
1431 
1432  while ((predlock = (PREDICATELOCK *) hash_seq_search(&seqstat)))
1433  {
1434  data->locktags[el] = predlock->tag.myTarget->tag;
1435  data->xacts[el] = *predlock->tag.myXact;
1436  el++;
1437  }
1438 
1439  Assert(el == els);
1440 
1441  /* Release locks in reverse order */
1442  LWLockRelease(SerializableXactHashLock);
1443  for (i = NUM_PREDICATELOCK_PARTITIONS - 1; i >= 0; i--)
1445 
1446  return data;
1447 }
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1331
SERIALIZABLEXACT * xacts
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static HTAB * PredicateLockHash
Definition: predicate.c:390
PREDICATELOCKTARGETTAG * locktags
PREDICATELOCKTAG tag
PREDICATELOCKTARGETTAG tag
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
#define PredicateLockHashPartitionLockByIndex(i)
Definition: predicate.c:250
void * palloc(Size size)
Definition: mcxt.c:848
int i
SERIALIZABLEXACT * myXact
PREDICATELOCKTARGET * myTarget
#define NUM_PREDICATELOCK_PARTITIONS
Definition: lwlock.h:121
static Snapshot GetSafeSnapshot ( Snapshot  snapshot)
static

Definition at line 1514 of file predicate.c.

References Assert, DEBUG2, ereport, errcode(), errmsg(), SERIALIZABLEXACT::flags, GetSerializableTransactionSnapshotInt(), InvalidPid, InvalidSerializableXact, 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().

1515 {
1516  Snapshot snapshot;
1517 
1519 
1520  while (true)
1521  {
1522  /*
1523  * GetSerializableTransactionSnapshotInt is going to call
1524  * GetSnapshotData, so we need to provide it the static snapshot area
1525  * our caller passed to us. The pointer returned is actually the same
1526  * one passed to it, but we avoid assuming that here.
1527  */
1528  snapshot = GetSerializableTransactionSnapshotInt(origSnapshot,
1529  NULL, InvalidPid);
1530 
1532  return snapshot; /* no concurrent r/w xacts; it's safe */
1533 
1534  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1535 
1536  /*
1537  * Wait for concurrent transactions to finish. Stop early if one of
1538  * them marked us as conflicted.
1539  */
1543  {
1544  LWLockRelease(SerializableXactHashLock);
1546  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1547  }
1549 
1551  {
1552  LWLockRelease(SerializableXactHashLock);
1553  break; /* success */
1554  }
1555 
1556  LWLockRelease(SerializableXactHashLock);
1557 
1558  /* else, need to retry... */
1559  ereport(DEBUG2,
1560  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
1561  errmsg("deferrable snapshot was unsafe; trying a new one")));
1562  ReleasePredicateLocks(false);
1563  }
1564 
1565  /*
1566  * Now we have a safe snapshot, so we don't need to do any further checks.
1567  */
1569  ReleasePredicateLocks(false);
1570 
1571  return snapshot;
1572 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
bool XactDeferrable
Definition: xact.c:80
int errcode(int sqlerrcode)
Definition: elog.c:575
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static Snapshot GetSerializableTransactionSnapshotInt(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1707
SHM_QUEUE possibleUnsafeConflicts
#define InvalidSerializableXact
#define SXACT_FLAG_DEFERRABLE_WAITING
#define DEBUG2
Definition: elog.h:24
#define SxactIsROSafe(sxact)
Definition: predicate.c:280
#define ereport(elevel, rest)
Definition: elog.h:122
void ProcWaitForSignal(uint32 wait_event_info)
Definition: proc.c:1775
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
void ReleasePredicateLocks(bool isCommit)
Definition: predicate.c:3268
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define SxactIsROUnsafe(sxact)
Definition: predicate.c:281
#define InvalidPid
Definition: miscadmin.h:31
int GetSafeSnapshotBlockingPids ( int  blocked_pid,
int *  output,
int  output_size 
)

Definition at line 1584 of file predicate.c.

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

Referenced by pg_isolation_test_session_is_blocked(), and pg_safe_snapshot_blocking_pids().

1585 {
1586  int num_written = 0;
1587  SERIALIZABLEXACT *sxact;
1588 
1589  LWLockAcquire(SerializableXactHashLock, LW_SHARED);
1590 
1591  /* Find blocked_pid's SERIALIZABLEXACT by linear search. */
1592  for (sxact = FirstPredXact(); sxact != NULL; sxact = NextPredXact(sxact))
1593  {
1594  if (sxact->pid == blocked_pid)
1595  break;
1596  }
1597 
1598  /* Did we find it, and is it currently waiting in GetSafeSnapshot? */
1599  if (sxact != NULL && SxactIsDeferrableWaiting(sxact))
1600  {
1601  RWConflict possibleUnsafeConflict;
1602 
1603  /* Traverse the list of possible unsafe conflicts collecting PIDs. */
1604  possibleUnsafeConflict = (RWConflict)
1606  &sxact->possibleUnsafeConflicts,
1607  offsetof(RWConflictData, inLink));
1608 
1609  while (possibleUnsafeConflict != NULL && num_written < output_size)
1610  {
1611  output[num_written++] = possibleUnsafeConflict->sxactOut->pid;
1612  possibleUnsafeConflict = (RWConflict)
1614  &possibleUnsafeConflict->inLink,
1615  offsetof(RWConflictData, inLink));
1616  }
1617  }
1618 
1619  LWLockRelease(SerializableXactHashLock);
1620 
1621  return num_written;
1622 }
static void output(uint64 loop_count)
struct RWConflictData * RWConflict
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
SHM_QUEUE possibleUnsafeConflicts
static SERIALIZABLEXACT * NextPredXact(SERIALIZABLEXACT *sxact)
Definition: predicate.c:613
static SERIALIZABLEXACT * FirstPredXact(void)
Definition: predicate.c:598
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define SxactIsDeferrableWaiting(sxact)
Definition: predicate.c:279
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
#define offsetof(type, field)
Definition: c.h:549
SERIALIZABLEXACT * sxactOut
Snapshot GetSerializableTransactionSnapshot ( Snapshot  snapshot)

Definition at line 1636 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

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

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

1710 {
1711  PGPROC *proc;
1712  VirtualTransactionId vxid;
1713  SERIALIZABLEXACT *sxact,
1714  *othersxact;
1715  HASHCTL hash_ctl;
1716 
1717  /* We only do this for serializable transactions. Once. */
1719 
1721 
1722  /*
1723  * Since all parts of a serializable transaction must use the same
1724  * snapshot, it is too late to establish one after a parallel operation
1725  * has begun.
1726  */
1727  if (IsInParallelMode())
1728  elog(ERROR, "cannot establish serializable snapshot during a parallel operation");
1729 
1730  proc = MyProc;
1731  Assert(proc != NULL);
1732  GET_VXID_FROM_PGPROC(vxid, *proc);
1733 
1734  /*
1735  * First we get the sxact structure, which may involve looping and access
1736  * to the "finished" list to free a structure for use.
1737  *
1738  * We must hold SerializableXactHashLock when taking/checking the snapshot
1739  * to avoid race conditions, for much the same reasons that
1740  * GetSnapshotData takes the ProcArrayLock. Since we might have to
1741  * release SerializableXactHashLock to call SummarizeOldestCommittedSxact,
1742  * this means we have to create the sxact first, which is a bit annoying
1743  * (in particular, an elog(ERROR) in procarray.c would cause us to leak
1744  * the sxact). Consider refactoring to avoid this.
1745  */
1746 #ifdef TEST_OLDSERXID
1748 #endif
1749  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1750  do
1751  {
1752  sxact = CreatePredXact();
1753  /* If null, push out committed sxact to SLRU summary & retry. */
1754  if (!sxact)
1755  {
1756  LWLockRelease(SerializableXactHashLock);
1758  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
1759  }
1760  } while (!sxact);
1761 
1762  /* Get the snapshot, or check that it's safe to use */
1763  if (!sourcevxid)
1764  snapshot = GetSnapshotData(snapshot);
1765  else if (!ProcArrayInstallImportedXmin(snapshot->xmin, sourcevxid))
1766  {
1767  ReleasePredXact(sxact);
1768  LWLockRelease(SerializableXactHashLock);
1769  ereport(ERROR,
1770  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1771  errmsg("could not import the requested snapshot"),
1772  errdetail("The source process with PID %d is not running anymore.",
1773  sourcepid)));
1774  }
1775 
1776  /*
1777  * If there are no serializable transactions which are not read-only, we
1778  * can "opt out" of predicate locking and conflict checking for a
1779  * read-only transaction.
1780  *
1781  * The reason this is safe is that a read-only transaction can only become
1782  * part of a dangerous structure if it overlaps a writable transaction
1783  * which in turn overlaps a writable transaction which committed before
1784  * the read-only transaction started. A new writable transaction can
1785  * overlap this one, but it can't meet the other condition of overlapping
1786  * a transaction which committed before this one started.
1787  */
1789  {
1790  ReleasePredXact(sxact);
1791  LWLockRelease(SerializableXactHashLock);
1792  return snapshot;
1793  }
1794 
1795  /* Maintain serializable global xmin info. */
1797  {
1799  PredXact->SxactGlobalXmin = snapshot->xmin;
1801  OldSerXidSetActiveSerXmin(snapshot->xmin);
1802  }
1803  else if (TransactionIdEquals(snapshot->xmin, PredXact->SxactGlobalXmin))
1804  {
1807  }
1808  else
1809  {
1811  }
1812 
1813  /* Initialize the structure. */
1814  sxact->vxid = vxid;
1818  SHMQueueInit(&(sxact->outConflicts));
1819  SHMQueueInit(&(sxact->inConflicts));
1821  sxact->topXid = GetTopTransactionIdIfAny();
1823  sxact->xmin = snapshot->xmin;
1824  sxact->pid = MyProcPid;
1825  SHMQueueInit(&(sxact->predicateLocks));
1826  SHMQueueElemInit(&(sxact->finishedLink));
1827  sxact->flags = 0;
1828  if (XactReadOnly)
1829  {
1830  sxact->flags |= SXACT_FLAG_READ_ONLY;
1831 
1832  /*
1833  * Register all concurrent r/w transactions as possible conflicts; if
1834  * all of them commit without any outgoing conflicts to earlier
1835  * transactions then this snapshot can be deemed safe (and we can run
1836  * without tracking predicate locks).
1837  */
1838  for (othersxact = FirstPredXact();
1839  othersxact != NULL;
1840  othersxact = NextPredXact(othersxact))
1841  {
1842  if (!SxactIsCommitted(othersxact)
1843  && !SxactIsDoomed(othersxact)
1844  && !SxactIsReadOnly(othersxact))
1845  {
1846  SetPossibleUnsafeConflict(sxact, othersxact);
1847  }
1848  }
1849  }
1850  else
1851  {
1855  }
1856 
1857  MySerializableXact = sxact;
1858  MyXactDidWrite = false; /* haven't written anything yet */
1859 
1860  LWLockRelease(SerializableXactHashLock);
1861 
1862  /* Initialize the backend-local hash table of parent locks */
1863  Assert(LocalPredicateLockHash == NULL);
1864  MemSet(&hash_ctl, 0, sizeof(hash_ctl));
1865  hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
1866  hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
1867  LocalPredicateLockHash = hash_create("Local predicate lock",
1869  &hash_ctl,
1870  HASH_ELEM | HASH_BLOBS);
1871 
1872  return snapshot;
1873 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
TransactionId finishedBefore
int MyProcPid
Definition: globals.c:39
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
#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:376
TransactionId SxactGlobalXmin
Size entrysize
Definition: hsearch.h:73
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:846
bool RecoveryInProgress(void)
Definition: xlog.c:7962
int max_predicate_locks_per_xact
Definition: predicate.c:363
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
bool IsInParallelMode(void)
Definition: xact.c:914
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:583
int MaxBackends
Definition: globals.c:127
struct LOCALPREDICATELOCK LOCALPREDICATELOCK
VirtualTransactionId vxid
static SERIALIZABLEXACT * NextPredXact(SERIALIZABLEXACT *sxact)
Definition: predicate.c:613
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define InvalidTransactionId
Definition: transam.h:31
TransactionId xmin
Definition: snapshot.h:68
SerCommitSeqNo lastCommitBeforeSnapshot
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:405
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvalidSerCommitSeqNo
static SERIALIZABLEXACT * FirstPredXact(void)
Definition: predicate.c:598
SerCommitSeqNo commitSeqNo
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
union SERIALIZABLEXACT::@100 SeqNo
bool XactReadOnly
Definition: xact.c:77
#define Assert(condition)
Definition: c.h:664
static void OldSerXidSetActiveSerXmin(TransactionId xid)
Definition: predicate.c:992
struct PREDICATELOCKTARGETTAG PREDICATELOCKTARGETTAG
SerCommitSeqNo prepareSeqNo
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:1509
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
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:698
#define SXACT_FLAG_READ_ONLY
static void SummarizeOldestCommittedSxact(void)
Definition: predicate.c:1457
static bool MyXactDidWrite
Definition: predicate.c:414
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:1797
Definition: proc.h:95
static SERIALIZABLEXACT * CreatePredXact(void)
Definition: predicate.c:566
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
void InitPredicateLocks ( void  )

Definition at line 1108 of file predicate.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

2215 {
2216  switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag))
2217  {
2218  case PREDLOCKTAG_RELATION:
2223 
2224  case PREDLOCKTAG_PAGE:
2226 
2227  case PREDLOCKTAG_TUPLE:
2228 
2229  /*
2230  * not reachable: nothing is finer-granularity than a tuple, so we
2231  * should never try to promote to it.
2232  */
2233  Assert(false);
2234  return 0;
2235  }
2236 
2237  /* not reachable */
2238  Assert(false);
2239  return 0;
2240 }
int max_predicate_locks_per_xact
Definition: predicate.c:363
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define Assert(condition)
Definition: c.h:664
int max_predicate_locks_per_relation
Definition: predicate.c:364
int max_predicate_locks_per_page
Definition: predicate.c:365
static SERIALIZABLEXACT * NextPredXact ( SERIALIZABLEXACT sxact)
static

Definition at line 613 of file predicate.c.

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

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

614 {
615  PredXactListElement ptle;
616 
617  Assert(ShmemAddrIsValid(sxact));
618 
619  ptle = (PredXactListElement)
620  (((char *) sxact)
623  ptle = (PredXactListElement)
625  &ptle->link,
627  if (!ptle)
628  return NULL;
629 
630  return &ptle->sxact;
631 }
static PredXactList PredXact
Definition: predicate.c:376
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 Assert(condition)
Definition: c.h:664
struct PredXactListElementData * PredXactListElement
#define offsetof(type, field)
Definition: c.h:549
static void OldSerXidAdd ( TransactionId  xid,
SerCommitSeqNo  minConflictCommitSeqNo 
)
static

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

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

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

952 {
953  TransactionId headXid;
954  TransactionId tailXid;
956  int slotno;
957 
959 
960  LWLockAcquire(OldSerXidLock, LW_SHARED);
961  headXid = oldSerXidControl->headXid;
962  tailXid = oldSerXidControl->tailXid;
963  LWLockRelease(OldSerXidLock);
964 
965  if (!TransactionIdIsValid(headXid))
966  return 0;
967 
968  Assert(TransactionIdIsValid(tailXid));
969 
970  if (TransactionIdPrecedes(xid, tailXid)
971  || TransactionIdFollows(xid, headXid))
972  return 0;
973 
974  /*
975  * The following function must be called without holding OldSerXidLock,
976  * but will return with that lock held, which must then be released.
977  */
979  OldSerXidPage(xid), xid);
980  val = OldSerXidValue(slotno, xid);
981  LWLockRelease(OldSerXidLock);
982  return val;
983 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:391
#define OldSerXidPage(xid)
Definition: predicate.c:333
#define OldSerXidSlruCtl
Definition: predicate.c:314
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
TransactionId headXid
Definition: predicate.c:339
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:467
uint64 SerCommitSeqNo
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static OldSerXidControl oldSerXidControl
Definition: predicate.c:346
#define OldSerXidValue(slotno, xid)
Definition: predicate.c:329
#define TransactionIdIsValid(xid)
Definition: transam.h:41
long val
Definition: informix.c:689
TransactionId tailXid
Definition: predicate.c:340
static void OldSerXidInit ( void  )
static

Definition at line 800 of file predicate.c.

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

Referenced by InitPredicateLocks().

801 {
802  bool found;
803 
804  /*
805  * Set up SLRU management of the pg_serial data.
806  */
808  SimpleLruInit(OldSerXidSlruCtl, "oldserxid",
809  NUM_OLDSERXID_BUFFERS, 0, OldSerXidLock, "pg_serial",
811  /* Override default assumption that writes should be fsync'd */
812  OldSerXidSlruCtl->do_fsync = false;
813 
814  /*
815  * Create or attach to the OldSerXidControl structure.
816  */
818  ShmemInitStruct("OldSerXidControlData", sizeof(OldSerXidControlData), &found);
819 
820  Assert(found == IsUnderPostmaster);
821  if (!found)
822  {
823  /*
824  * Set control information to reflect empty SLRU.
825  */
830  }
831 }
struct OldSerXidControlData * OldSerXidControl
Definition: predicate.c:344
#define NUM_OLDSERXID_BUFFERS
Definition: predicate.h:31
#define OldSerXidSlruCtl
Definition: predicate.c:314
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
bool IsUnderPostmaster
Definition: globals.c:101
#define InvalidTransactionId
Definition: transam.h:31
TransactionId headXid
Definition: predicate.c:339
#define Assert(condition)
Definition: c.h:664
static bool OldSerXidPagePrecedesLogically(int p, int q)
Definition: predicate.c:777
static OldSerXidControl oldSerXidControl
Definition: predicate.c:346
TransactionId tailXid
Definition: predicate.c:340
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 777 of file predicate.c.

References Assert, and OLDSERXID_MAX_PAGE.

Referenced by OldSerXidAdd(), and OldSerXidInit().

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

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

993 {
994  LWLockAcquire(OldSerXidLock, LW_EXCLUSIVE);
995 
996  /*
997  * When no sxacts are active, nothing overlaps, set the xid values to
998  * invalid to show that there are no valid entries. Don't clear headPage,
999  * though. A new xmin might still land on that page, and we don't want to
1000  * repeatedly zero out the same page.
1001  */
1002  if (!TransactionIdIsValid(xid))
1003  {
1006  LWLockRelease(OldSerXidLock);
1007  return;
1008  }
1009 
1010  /*
1011  * When we're recovering prepared transactions, the global xmin might move
1012  * backwards depending on the order they're recovered. Normally that's not
1013  * OK, but during recovery no serializable transactions will commit, so
1014  * the SLRU is empty and we can get away with it.
1015  */
1016  if (RecoveryInProgress())
1017  {
1021  {
1022  oldSerXidControl->tailXid = xid;
1023  }
1024  LWLockRelease(OldSerXidLock);
1025  return;
1026  }
1027 
1030 
1031  oldSerXidControl->tailXid = xid;
1032 
1033  LWLockRelease(OldSerXidLock);
1034 }
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
bool RecoveryInProgress(void)
Definition: xlog.c:7962
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define InvalidTransactionId
Definition: transam.h:31
TransactionId headXid
Definition: predicate.c:339
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:664
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static OldSerXidControl oldSerXidControl
Definition: predicate.c:346
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId tailXid
Definition: predicate.c:340
static void OnConflict_CheckForSerializationFailure ( const SERIALIZABLEXACT reader,
SERIALIZABLEXACT writer 
)
static

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

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

Definition at line 1929 of file predicate.c.

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

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

Definition at line 4874 of file predicate.c.

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

Referenced by PrepareTransaction().

4875 {
4877  return;
4878 
4880 
4881  MySerializableXact->pid = 0;
4882 
4884  LocalPredicateLockHash = NULL;
4885 
4887  MyXactDidWrite = false;
4888 }
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:810
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
#define InvalidSerializableXact
#define Assert(condition)
Definition: c.h:664
static HTAB * LocalPredicateLockHash
Definition: predicate.c:406
static bool MyXactDidWrite
Definition: predicate.c:414
void PreCommit_CheckForSerializationFailure ( void  )

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

4713 {
4714  RWConflict nearConflict;
4715 
4717  return;
4718 
4720 
4721  LWLockAcquire(SerializableXactHashLock, LW_EXCLUSIVE);
4722 
4723  /* Check if someone else has already decided that we need to die */
4725  {
4726  LWLockRelease(SerializableXactHashLock);
4727  ereport(ERROR,
4728  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4729  errmsg("could not serialize access due to read/write dependencies among transactions"),
4730  errdetail_internal("Reason code: Canceled on identification as a pivot, during commit attempt."),
4731  errhint("The transaction might succeed if retried.")));
4732  }
4733 
4734  nearConflict = (RWConflict)
4737  offsetof(RWConflictData, inLink));
4738  while (nearConflict)
4739  {
4740  if (!SxactIsCommitted(nearConflict->sxactOut)
4741  && !SxactIsDoomed(nearConflict->sxactOut))
4742  {
4743  RWConflict farConflict;
4744 
4745  farConflict = (RWConflict)
4746  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4747  &nearConflict->sxactOut->inConflicts,
4748  offsetof(RWConflictData, inLink));
4749  while (farConflict)
4750  {
4751  if (farConflict->sxactOut == MySerializableXact
4752  || (!SxactIsCommitted(farConflict->sxactOut)
4753  && !SxactIsReadOnly(farConflict->sxactOut)
4754  && !SxactIsDoomed(farConflict->sxactOut)))
4755  {
4756  /*
4757  * Normally, we kill the pivot transaction to make sure we
4758  * make progress if the failing transaction is retried.
4759  * However, we can't kill it if it's already prepared, so
4760  * in that case we commit suicide instead.
4761  */
4762  if (SxactIsPrepared(nearConflict->sxactOut))
4763  {
4764  LWLockRelease(SerializableXactHashLock);
4765  ereport(ERROR,
4766  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
4767  errmsg("could not serialize access due to read/write dependencies among transactions"),
4768  errdetail_internal("Reason code: Canceled on commit attempt with conflict in from prepared pivot."),
4769  errhint("The transaction might succeed if retried.")));
4770  }
4771  nearConflict->sxactOut->flags |= SXACT_FLAG_DOOMED;
4772  break;
4773  }
4774  farConflict = (RWConflict)
4775  SHMQueueNext(&nearConflict->sxactOut->inConflicts,
4776  &farConflict->inLink,
4777  offsetof(RWConflictData, inLink));
4778  }
4779  }
4780 
4781  nearConflict = (RWConflict)
4783  &nearConflict->inLink,
4784  offsetof(RWConflictData, inLink));
4785  }
4786 
4789 
4790  LWLockRelease(SerializableXactHashLock);
4791 }
#define SxactIsReadOnly(sxact)
Definition: predicate.c:270
static SERIALIZABLEXACT * MySerializableXact
Definition: predicate.c:413
int errhint(const char *fmt,...)
Definition: elog.c:987
static PredXactList PredXact
Definition: predicate.c:376
struct RWConflictData * RWConflict
int errcode(int sqlerrcode)
Definition: elog.c:575
#define SxactIsPrepared(sxact)
Definition: predicate.c:267
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define SxactIsDoomed(sxact)
Definition: predicate.c:269
#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:664
SerCommitSeqNo prepareSeqNo
SerCommitSeqNo LastSxactCommitSeqNo
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define IsolationIsSerializable()
Definition: xact.h:44
#define SxactIsCommitted(sxact)
Definition: predicate.c:266
#define offsetof(type, field)
Definition: c.h:549
SERIALIZABLEXACT * sxactOut
static uint32 predicatelock_hash ( const void *  key,
Size  keysize 
)
static

Definition at line 1373 of file predicate.c.

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

Referenced by InitPredicateLocks().

1374 {
1375  const PREDICATELOCKTAG *predicatelocktag = (const PREDICATELOCKTAG *) key;
1376  uint32 targethash;
1377 
1378  Assert(keysize == sizeof(PREDICATELOCKTAG));
1379 
1380  /* Look into the associated target object, and compute its hash code */
1381  targethash = PredicateLockTargetTagHashCode(&predicatelocktag->myTarget->tag);
1382 
1383  return PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash);
1384 }
#define PredicateLockHashCodeFromTargetHashCode(predicatelocktag, targethash)
Definition: predicate.c:304
unsigned int uint32
Definition: c.h:258
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:291
PREDICATELOCKTARGETTAG tag
#define Assert(condition)
Definition: c.h:664
PREDICATELOCKTARGET * myTarget
void predicatelock_twophase_recover ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4923 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, 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.

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