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 251 of file predicate.c.

Referenced by InitPredicateLocks(), and PredicateLockShmemSize().

#define OLDSERXID_ENTRIESPERPAGE   (OLDSERXID_PAGESIZE / OLDSERXID_ENTRYSIZE)

Definition at line 316 of file predicate.c.

#define OLDSERXID_ENTRYSIZE   sizeof(SerCommitSeqNo)

Definition at line 315 of file predicate.c.

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

Definition at line 322 of file predicate.c.

Referenced by OldSerXidPagePrecedesLogically().

#define OLDSERXID_PAGESIZE   BLCKSZ

Definition at line 314 of file predicate.c.

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

Definition at line 325 of file predicate.c.

Referenced by OldSerXidAdd().

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

Definition at line 332 of file predicate.c.

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

Definition at line 327 of file predicate.c.

Referenced by OldSerXidAdd(), and OldSerXidGetMinConflictCommitSeqNo().

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

Definition at line 243 of file predicate.c.

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

Definition at line 277 of file predicate.c.

Referenced by GetSafeSnapshotBlockingPids(), and ReleasePredicateLocks().

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

Definition at line 254 of file predicate.c.

Referenced by ReleaseOneSerializableXact(), and ReleasePredicateLocks().

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

Definition at line 279 of file predicate.c.

Referenced by GetSafeSnapshot(), and ReleasePredicateLocks().

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

Definition at line 220 of file predicate.c.

Referenced by DeleteChildTargetLocks().

Typedef Documentation

Definition at line 342 of file predicate.c.

Function Documentation

void AtPrepare_PredicateLocks ( void  )

Definition at line 4790 of file predicate.c.

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

Referenced by PrepareTransaction().

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

Definition at line 2236 of file predicate.c.

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

Referenced by PredicateLockAcquire().

2237 {
2238  PREDICATELOCKTARGETTAG targettag,
2239  nexttag,
2240  promotiontag;
2241  LOCALPREDICATELOCK *parentlock;
2242  bool found,
2243  promote;
2244 
2245  promote = false;
2246 
2247  targettag = *reqtag;
2248 
2249  /* check parents iteratively */
2250  while (GetParentPredicateLockTag(&targettag, &nexttag))
2251  {
2252  targettag = nexttag;
2254  &targettag,
2255  HASH_ENTER,
2256  &found);
2257  if (!found)
2258  {
2259  parentlock->held = false;
2260  parentlock->childLocks = 1;
2261  }
2262  else
2263  parentlock->childLocks++;
2264 
2265  if (parentlock->childLocks >
2266  MaxPredicateChildLocks(&targettag))
2267  {
2268  /*
2269  * We should promote to this parent lock. Continue to check its
2270  * ancestors, however, both to get their child counts right and to
2271  * check whether we should just go ahead and promote to one of
2272  * them.
2273  */
2274  promotiontag = targettag;
2275  promote = true;
2276  }
2277  }
2278 
2279  if (promote)
2280  {
2281  /* acquire coarsest ancestor eligible for promotion */
2282  PredicateLockAcquire(&promotiontag);
2283  return true;
2284  }
2285  else
2286  return false;
2287 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:903
static void PredicateLockAcquire(const PREDICATELOCKTARGETTAG *targettag)
Definition: predicate.c:2424
static int MaxPredicateChildLocks(const PREDICATELOCKTARGETTAG *tag)
Definition: predicate.c:2199
static bool GetParentPredicateLockTag(const PREDICATELOCKTARGETTAG *tag, PREDICATELOCKTARGETTAG *parent)
Definition: predicate.c:1978
static HTAB * LocalPredicateLockHash
Definition: predicate.c:404
void CheckForSerializableConflictIn ( Relation  relation,
HeapTuple  tuple,
Buffer  buffer 
)

Definition at line 4311 of file predicate.c.

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

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

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

Definition at line 3930 of file predicate.c.

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

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

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

Definition at line 1040 of file predicate.c.

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

Referenced by CheckPointGuts().

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

Definition at line 4395 of file predicate.c.

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

Referenced by ExecuteTruncate(), and heap_drop_with_catalog().

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

Definition at line 4133 of file predicate.c.

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

Referenced by CheckForSerializableConflictIn().

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

Definition at line 3571 of file predicate.c.

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

Referenced by ReleasePredicateLocks().

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

Definition at line 2017 of file predicate.c.

References GetParentPredicateLockTag(), and PredicateLockExists().

Referenced by PredicateLockAcquire().

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

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

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

Definition at line 564 of file predicate.c.

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

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

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

Definition at line 2301 of file predicate.c.

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

Referenced by CheckTargetForConflictsIn(), and DeleteChildTargetLocks().

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

Definition at line 2118 of file predicate.c.

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

Referenced by PredicateLockAcquire().

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

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

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

Definition at line 2879 of file predicate.c.

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

Referenced by TransferPredicateLocksToHeapRelation().

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

Definition at line 596 of file predicate.c.

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

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

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

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

4488 {
4489  Assert(reader != writer);
4490 
4491  /* First, see if this conflict causes failure. */
4493 
4494  /* Actually do the conflict flagging. */
4495  if (reader == OldCommittedSxact)
4497  else if (writer == OldCommittedSxact)
4499  else
4500  SetRWConflict(reader, writer);
4501 }
#define SXACT_FLAG_SUMMARY_CONFLICT_OUT
static void SetRWConflict(SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:670
static void OnConflict_CheckForSerializationFailure(const SERIALIZABLEXACT *reader, SERIALIZABLEXACT *writer)
Definition: predicate.c:4522
#define Assert(condition)
Definition: c.h:675
static SERIALIZABLEXACT * OldCommittedSxact
Definition: predicate.c:352
#define SXACT_FLAG_SUMMARY_CONFLICT_IN
static void FlagSxactUnsafe ( SERIALIZABLEXACT sxact)
static

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

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

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

1980 {
1981  switch (GET_PREDICATELOCKTARGETTAG_TYPE(*tag))
1982  {
1983  case PREDLOCKTAG_RELATION:
1984  /* relation locks have no parent lock */
1985  return false;
1986 
1987  case PREDLOCKTAG_PAGE:
1988  /* parent lock is relation lock */
1992 
1993  return true;
1994 
1995  case PREDLOCKTAG_TUPLE:
1996  /* parent lock is page lock */
2001  return true;
2002  }
2003 
2004  /* not reachable */
2005  Assert(false);
2006  return false;
2007 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag)
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag, dboid, reloid)
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define Assert(condition)
Definition: c.h:675
PredicateLockData* GetPredicateLockStatusData ( void  )

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

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

Definition at line 1499 of file predicate.c.

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

Referenced by GetSerializableTransactionSnapshot().

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

Definition at line 1569 of file predicate.c.

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

Referenced by pg_isolation_test_session_is_blocked(), and pg_safe_snapshot_blocking_pids().

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

Definition at line 1621 of file predicate.c.

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

Referenced by GetTransactionSnapshot().

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

Definition at line 1692 of file predicate.c.

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

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

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

Definition at line 1105 of file predicate.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

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

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

Definition at line 611 of file predicate.c.

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

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

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

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

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

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

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

Definition at line 798 of file predicate.c.

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

Referenced by InitPredicateLocks().

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

Definition at line 775 of file predicate.c.

References Assert, and OLDSERXID_MAX_PAGE.

Referenced by OldSerXidAdd(), and OldSerXidInit().

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

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

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

Definition at line 4522 of file predicate.c.

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

Referenced by FlagRWConflict().

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

Definition at line 1914 of file predicate.c.

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

1915 {
1916  PREDICATELOCKTARGETTAG targettag;
1917  uint32 targettaghash;
1918  LWLock *partitionLock;
1919  PREDICATELOCKTARGET *target;
1920 
1922  relation->rd_node.dbNode,
1923  relation->rd_id,
1924  blkno);
1925 
1926  targettaghash = PredicateLockTargetTagHashCode(&targettag);
1927  partitionLock = PredicateLockHashPartitionLock(targettaghash);
1928  LWLockAcquire(partitionLock, LW_SHARED);
1929  target = (PREDICATELOCKTARGET *)
1931  &targettag, targettaghash,
1932  HASH_FIND, NULL);
1933  LWLockRelease(partitionLock);
1934 
1935  return (target != NULL);
1936 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:916
Definition: lwlock.h:32
static HTAB * PredicateLockTargetHash
Definition: predicate.c:387
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag, dboid, reloid, blocknum)
#define PredicateLockHashPartitionLock(hashcode)
Definition: predicate.c:245
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
unsigned int uint32
Definition: c.h:268
Oid rd_id
Definition: rel.h:116
#define PredicateLockTargetTagHashCode(predicatelocktargettag)
Definition: predicate.c:289
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:229
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
void PostPrepare_PredicateLocks ( TransactionId  xid)

Definition at line 4859 of file predicate.c.

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

Referenced by PrepareTransaction().

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

Definition at line 4697 of file predicate.c.

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

Referenced by CommitTransaction(), and PrepareTransaction().

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

Definition at line 1358 of file predicate.c.

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

Referenced by InitPredicateLocks().

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

Definition at line 4908 of file predicate.c.

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

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