| /*------------------------------------------------------------------------- |
| * |
| * lock.h |
| * POSTGRES low-level lock mechanism |
| * |
| * |
| * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| * |
| * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.102 2006/11/23 05:14:04 momjian Exp $ |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #ifndef LOCK_H_ |
| #define LOCK_H_ |
| |
| #include "nodes/pg_list.h" |
| #include "storage/itemptr.h" |
| #include "storage/lwlock.h" |
| #include "storage/shmem.h" |
| #include "utils/resowner.h" |
| |
| |
| /* struct PGPROC is declared in proc.h, but must forward-reference it */ |
| typedef struct PGPROC PGPROC; |
| |
| typedef struct PROC_QUEUE |
| { |
| SHM_QUEUE links; /* head of list of PGPROC objects */ |
| int size; /* number of entries in list */ |
| } PROC_QUEUE; |
| |
| /* GUC variables */ |
| extern int max_locks_per_xact; |
| |
| #ifdef LOCK_DEBUG |
| extern int Trace_lock_oidmin; |
| extern bool Trace_locks; |
| extern bool Trace_userlocks; |
| extern int Trace_lock_table; |
| extern bool Debug_deadlocks; |
| #endif /* LOCK_DEBUG */ |
| |
| |
| /* |
| * LOCKMODE is an integer (1..N) indicating a lock type. LOCKMASK is a bit |
| * mask indicating a set of held or requested lock types (the bit 1<<mode |
| * corresponds to a particular lock mode). |
| */ |
| typedef int LOCKMASK; |
| typedef int LOCKMODE; |
| |
| /* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */ |
| #define MAX_LOCKMODES 10 |
| |
| #define LOCKBIT_ON(lockmode) (1 << (lockmode)) |
| #define LOCKBIT_OFF(lockmode) (~(1 << (lockmode))) |
| |
| |
| /* |
| * This data structure defines the locking semantics associated with a |
| * "lock method". The semantics specify the meaning of each lock mode |
| * (by defining which lock modes it conflicts with), and also whether locks |
| * of this method are transactional (ie, are released at transaction end). |
| * All of this data is constant and is kept in const tables. |
| * |
| * numLockModes -- number of lock modes (READ,WRITE,etc) that |
| * are defined in this lock method. Must be less than MAX_LOCKMODES. |
| * |
| * transactional -- TRUE if locks are released automatically at xact end. |
| * |
| * conflictTab -- this is an array of bitmasks showing lock |
| * mode conflicts. conflictTab[i] is a mask with the j-th bit |
| * turned on if lock modes i and j conflict. Lock modes are |
| * numbered 1..numLockModes; conflictTab[0] is unused. |
| * |
| * lockModeNames -- ID strings for debug printouts. |
| * |
| * trace_flag -- pointer to GUC trace flag for this lock method. |
| */ |
| typedef struct LockMethodData |
| { |
| int numLockModes; |
| bool transactional; |
| const LOCKMASK *conflictTab; |
| const char *const * lockModeNames; |
| const bool *trace_flag; |
| } LockMethodData; |
| |
| typedef const LockMethodData *LockMethod; |
| |
| /* |
| * Lock methods are identified by LOCKMETHODID. (Despite the declaration as |
| * uint16, we are constrained to 256 lockmethods by the layout of LOCKTAG.) |
| */ |
| typedef uint16 LOCKMETHODID; |
| |
| /* These identify the known lock methods */ |
| #define DEFAULT_LOCKMETHOD 1 |
| #define USER_LOCKMETHOD 2 |
| |
| /* |
| * These are the valid values of type LOCKMODE for all the standard lock |
| * methods (both DEFAULT and USER). |
| */ |
| |
| /* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */ |
| #define NoLock 0 |
| |
| #define AccessShareLock 1 /* SELECT */ |
| #define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */ |
| #define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */ |
| #define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL),ANALYZE, CREATE |
| * INDEX CONCURRENTLY */ |
| #define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */ |
| #define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW |
| * SHARE */ |
| #define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR |
| * UPDATE */ |
| #define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM |
| * FULL, and unqualified LOCK TABLE */ |
| |
| /* |
| * Map from lock methods to lock table data structures. |
| */ |
| extern const LockMethod LockMethods[]; |
| |
| |
| /* |
| * The lock hash tables. (needed by resource queuing). |
| */ |
| extern HTAB *LockMethodLockHash; |
| extern HTAB *LockMethodProcLockHash; |
| extern HTAB *LockMethodLocalHash; |
| |
| |
| /* |
| * LOCKTAG is the key information needed to look up a LOCK item in the |
| * lock hashtable. A LOCKTAG value uniquely identifies a lockable object. |
| * |
| * The LockTagType enum defines the different kinds of objects we can lock. |
| * We can handle up to 256 different LockTagTypes. |
| */ |
| typedef enum LockTagType |
| { |
| LOCKTAG_RELATION, /* whole relation */ |
| /* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */ |
| LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */ |
| /* same ID info as RELATION */ |
| LOCKTAG_PAGE, /* one page of a relation */ |
| /* ID info for a page is RELATION info + BlockNumber */ |
| LOCKTAG_TUPLE, /* one physical tuple */ |
| /* ID info for a tuple is PAGE info + OffsetNumber */ |
| LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */ |
| /* ID info for a transaction is its TransactionId */ |
| LOCKTAG_RELATION_RESYNCHRONIZE, /* whole relation for resynchronize */ |
| /* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */ |
| LOCKTAG_RELATION_APPENDONLY_SEGMENT_FILE, /* Segment file within an Append-Only relation */ |
| /* ID info for a relation is DB OID + REL OID + (LOGICAL) SEGMENT FILE # */ |
| LOCKTAG_OBJECT, /* non-relation database object */ |
| /* ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID */ |
| |
| /* |
| * Note: object ID has same representation as in pg_depend and |
| * pg_description, but notice that we are constraining SUBID to 16 bits. |
| * Also, we use DB OID = 0 for shared objects such as tablespaces. |
| */ |
| LOCKTAG_RESOURCE_QUEUE, /* ID info for resource queue is QUEUE ID */ |
| LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */ |
| LOCKTAG_ADVISORY /* advisory user locks */ |
| } LockTagType; |
| |
| /* |
| * The LOCKTAG struct is defined with malice aforethought to fit into 16 |
| * bytes with no padding. Note that this would need adjustment if we were |
| * to widen Oid, BlockNumber, or TransactionId to more than 32 bits. |
| * |
| * We include lockmethodid in the locktag so that a single hash table in |
| * shared memory can store locks of different lockmethods. |
| */ |
| typedef struct LOCKTAG |
| { |
| uint32 segindex; /* backend contentid */ |
| uint32 locktag_field1; /* a 32-bit ID field */ |
| uint32 locktag_field2; /* a 32-bit ID field */ |
| uint32 locktag_field3; /* a 32-bit ID field */ |
| uint16 locktag_field4; /* a 16-bit ID field */ |
| uint8 locktag_type; /* see enum LockTagType */ |
| uint8 locktag_lockmethodid; /* lockmethod indicator */ |
| } LOCKTAG; |
| |
| /* |
| * These macros define how we map logical IDs of lockable objects into |
| * the physical fields of LOCKTAG. Use these to set up LOCKTAG values, |
| * rather than accessing the fields directly. Note multiple eval of target! |
| */ |
| #define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (reloid), \ |
| (locktag).locktag_field3 = 0, \ |
| (locktag).locktag_field4 = 0, \ |
| (locktag).locktag_type = LOCKTAG_RELATION, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_RELATION_EXTEND(locktag,dboid,reloid) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (reloid), \ |
| (locktag).locktag_field3 = 0, \ |
| (locktag).locktag_field4 = 0, \ |
| (locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_PAGE(locktag,dboid,reloid,blocknum) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (reloid), \ |
| (locktag).locktag_field3 = (blocknum), \ |
| (locktag).locktag_field4 = 0, \ |
| (locktag).locktag_type = LOCKTAG_PAGE, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (reloid), \ |
| (locktag).locktag_field3 = (blocknum), \ |
| (locktag).locktag_field4 = (offnum), \ |
| (locktag).locktag_type = LOCKTAG_TUPLE, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_TRANSACTION(locktag,xid) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (xid), \ |
| (locktag).locktag_field2 = 0, \ |
| (locktag).locktag_field3 = 0, \ |
| (locktag).locktag_field4 = 0, \ |
| (locktag).locktag_type = LOCKTAG_TRANSACTION, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_RELATION_RESYNCHRONIZE(locktag,dboid,reloid) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (reloid), \ |
| (locktag).locktag_field3 = 0, \ |
| (locktag).locktag_field4 = 0, \ |
| (locktag).locktag_type = LOCKTAG_RELATION_RESYNCHRONIZE, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_RELATION_APPENDONLY_SEGMENT_FILE(locktag,dboid,reloid,segno) \ |
| ((locktag).segindex = (-1), \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (reloid), \ |
| (locktag).locktag_field3 = (segno), \ |
| (locktag).locktag_field4 = 0, \ |
| (locktag).locktag_type = LOCKTAG_RELATION_APPENDONLY_SEGMENT_FILE, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_OBJECT(locktag,dboid,classoid,objoid,objsubid) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (dboid), \ |
| (locktag).locktag_field2 = (classoid), \ |
| (locktag).locktag_field3 = (objoid), \ |
| (locktag).locktag_field4 = (objsubid), \ |
| (locktag).locktag_type = LOCKTAG_OBJECT, \ |
| (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
| |
| #define SET_LOCKTAG_ADVISORY(locktag,id1,id2,id3,id4) \ |
| ((locktag).segindex = MASTER_CONTENT_ID, \ |
| (locktag).locktag_field1 = (id1), \ |
| (locktag).locktag_field2 = (id2), \ |
| (locktag).locktag_field3 = (id3), \ |
| (locktag).locktag_field4 = (id4), \ |
| (locktag).locktag_type = LOCKTAG_ADVISORY, \ |
| (locktag).locktag_lockmethodid = USER_LOCKMETHOD) |
| |
| |
| /* |
| * Per-locked-object lock information: |
| * |
| * tag -- uniquely identifies the object being locked |
| * grantMask -- bitmask for all lock types currently granted on this object. |
| * waitMask -- bitmask for all lock types currently awaited on this object. |
| * procLocks -- list of PROCLOCK objects for this lock. |
| * waitProcs -- queue of processes waiting for this lock. |
| * requested -- count of each lock type currently requested on the lock |
| * (includes requests already granted!!). |
| * nRequested -- total requested locks of all types. |
| * granted -- count of each lock type currently granted on the lock. |
| * nGranted -- total granted locks of all types. |
| * |
| * Note: these counts count 1 for each backend. Internally to a backend, |
| * there may be multiple grabs on a particular lock, but this is not reflected |
| * into shared memory. |
| */ |
| typedef struct LOCK |
| { |
| /* hash key */ |
| LOCKTAG tag; /* unique identifier of lockable object */ |
| |
| /* data */ |
| LOCKMASK grantMask; /* bitmask for lock types already granted */ |
| LOCKMASK waitMask; /* bitmask for lock types awaited */ |
| SHM_QUEUE procLocks; /* list of PROCLOCK objects assoc. with lock */ |
| PROC_QUEUE waitProcs; /* list of PGPROC objects waiting on lock */ |
| int requested[MAX_LOCKMODES]; /* counts of requested locks */ |
| int nRequested; /* total of requested[] array */ |
| int granted[MAX_LOCKMODES]; /* counts of granted locks */ |
| int nGranted; /* total of granted[] array */ |
| } LOCK; |
| |
| #define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid) |
| |
| |
| /* |
| * We may have several different backends holding or awaiting locks |
| * on the same lockable object. We need to store some per-holder/waiter |
| * information for each such holder (or would-be holder). This is kept in |
| * a PROCLOCK struct. |
| * |
| * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the |
| * proclock hashtable. A PROCLOCKTAG value uniquely identifies the combination |
| * of a lockable object and a holder/waiter for that object. (We can use |
| * pointers here because the PROCLOCKTAG need only be unique for the lifespan |
| * of the PROCLOCK, and it will never outlive the lock or the proc.) |
| * |
| * Internally to a backend, it is possible for the same lock to be held |
| * for different purposes: the backend tracks transaction locks separately |
| * from session locks. However, this is not reflected in the shared-memory |
| * state: we only track which backend(s) hold the lock. This is OK since a |
| * backend can never block itself. |
| * |
| * The holdMask field shows the already-granted locks represented by this |
| * proclock. Note that there will be a proclock object, possibly with |
| * zero holdMask, for any lock that the process is currently waiting on. |
| * Otherwise, proclock objects whose holdMasks are zero are recycled |
| * as soon as convenient. |
| * |
| * releaseMask is workspace for LockReleaseAll(): it shows the locks due |
| * to be released during the current call. This must only be examined or |
| * set by the backend owning the PROCLOCK. |
| * |
| * Each PROCLOCK object is linked into lists for both the associated LOCK |
| * object and the owning PGPROC object. Note that the PROCLOCK is entered |
| * into these lists as soon as it is created, even if no lock has yet been |
| * granted. A PGPROC that is waiting for a lock to be granted will also be |
| * linked into the lock's waitProcs queue. |
| */ |
| typedef struct PROCLOCKTAG |
| { |
| /* NB: we assume this struct contains no padding! */ |
| LOCK *myLock; /* link to per-lockable-object information */ |
| PGPROC *myProc; /* link to PGPROC of owning backend */ |
| } PROCLOCKTAG; |
| |
| typedef struct PROCLOCK |
| { |
| /* tag */ |
| PROCLOCKTAG tag; /* unique identifier of proclock object */ |
| |
| /* data */ |
| LOCKMASK holdMask; /* bitmask for lock types currently held */ |
| LOCKMASK releaseMask; /* bitmask for lock types to be released */ |
| SHM_QUEUE lockLink; /* list link in LOCK's list of proclocks */ |
| SHM_QUEUE procLink; /* list link in PGPROC's list of proclocks */ |
| int nLocks; /* total number of times lock is held by |
| this process, used by resource scheduler */ |
| SHM_QUEUE portalLinks; /* list of ResPortalIncrements for this |
| proclock, used by resource scheduler */ |
| } PROCLOCK; |
| |
| #define PROCLOCK_LOCKMETHOD(proclock) \ |
| LOCK_LOCKMETHOD(*((proclock).tag.myLock)) |
| |
| /* |
| * Each backend also maintains a local hash table with information about each |
| * lock it is currently interested in. In particular the local table counts |
| * the number of times that lock has been acquired. This allows multiple |
| * requests for the same lock to be executed without additional accesses to |
| * shared memory. We also track the number of lock acquisitions per |
| * ResourceOwner, so that we can release just those locks belonging to a |
| * particular ResourceOwner. |
| */ |
| typedef struct LOCALLOCKTAG |
| { |
| LOCKTAG lock; /* identifies the lockable object */ |
| LOCKMODE mode; /* lock mode for this table entry */ |
| } LOCALLOCKTAG; |
| |
| typedef struct LOCALLOCKOWNER |
| { |
| /* |
| * Note: if owner is NULL then the lock is held on behalf of the session; |
| * otherwise it is held on behalf of my current transaction. |
| * |
| * Must use a forward struct reference to avoid circularity. |
| */ |
| struct ResourceOwnerData *owner; |
| int64 nLocks; /* # of times held by this owner */ |
| } LOCALLOCKOWNER; |
| |
| typedef struct LOCALLOCK |
| { |
| /* tag */ |
| LOCALLOCKTAG tag; /* unique identifier of locallock entry */ |
| |
| /* data */ |
| LOCK *lock; /* associated LOCK object in shared mem */ |
| PROCLOCK *proclock; /* associated PROCLOCK object in shmem */ |
| uint32 hashcode; /* copy of LOCKTAG's hash value */ |
| bool preparable; /* MPP: During prepare we populate this to avoid MPP-1094 */ |
| bool isFake; /* For MPP */ |
| int64 nLocks; /* total number of times lock is held */ |
| int numLockOwners; /* # of relevant ResourceOwners */ |
| int maxLockOwners; /* allocated size of array */ |
| LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */ |
| } LOCALLOCK; |
| |
| #define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid) |
| |
| /* Waiter global locallock. (needed by resource queuing). */ |
| extern LOCALLOCK *awaitedLock; |
| extern ResourceOwner awaitedOwner; |
| |
| /* |
| * This struct holds information passed from lmgr internals to the lock |
| * listing user-level functions (in lockfuncs.c). For each PROCLOCK in |
| * the system, copies of the PROCLOCK object and associated PGPROC and |
| * LOCK objects are stored. Note there will often be multiple copies |
| * of the same PGPROC or LOCK --- to detect whether two are the same, |
| * compare the PROCLOCK tag fields. |
| */ |
| typedef struct LockData |
| { |
| int nelements; /* The length of each of the arrays */ |
| PROCLOCK *proclocks; |
| PGPROC *procs; |
| LOCK *locks; |
| } LockData; |
| |
| |
| /* Result codes for LockAcquire() */ |
| typedef enum |
| { |
| LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */ |
| LOCKACQUIRE_OK, /* lock successfully acquired */ |
| LOCKACQUIRE_ALREADY_HELD /* incremented count for lock already held */ |
| } LockAcquireResult; |
| |
| |
| /* |
| * The lockmgr's shared hash tables are partitioned to reduce contention. |
| * To determine which partition a given locktag belongs to, compute the tag's |
| * hash code with LockTagHashCode(), then apply one of these macros. |
| * NB: NUM_LOCK_PARTITIONS must be a power of 2! |
| */ |
| #define LockHashPartition(hashcode) \ |
| ((hashcode) % NUM_LOCK_PARTITIONS) |
| #define LockHashPartitionLock(hashcode) \ |
| ((LWLockId) (FirstLockMgrLock + LockHashPartition(hashcode))) |
| |
| |
| /* |
| * function prototypes |
| */ |
| extern void InitLocks(void); |
| extern LockMethod GetLocksMethodTable(const LOCK *lock); |
| extern uint32 LockTagHashCode(const LOCKTAG *locktag); |
| /* |
| * Compute the hash code associated with a PROCLOCKTAG, given the hashcode |
| * for its underlying LOCK. |
| * |
| * We use this just to avoid redundant calls of LockTagHashCode(). |
| */ |
| static inline uint32 |
| ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode) |
| { |
| uint32 lockhash = hashcode; |
| Datum procptr; |
| |
| /* |
| * This must match proclock_hash()! |
| */ |
| procptr = PointerGetDatum(proclocktag->myProc); |
| lockhash ^= ((uint32) procptr) << LOG2_NUM_LOCK_PARTITIONS; |
| |
| return lockhash; |
| } |
| extern LockAcquireResult LockAcquire(const LOCKTAG *locktag, |
| LOCKMODE lockmode, |
| bool sessionLock, |
| bool dontWait); |
| extern bool LockRelease(const LOCKTAG *locktag, |
| LOCKMODE lockmode, bool sessionLock); |
| extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks); |
| extern void LockReleaseCurrentOwner(void); |
| extern void LockReassignCurrentOwner(void); |
| extern List *GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode); |
| extern void AtPrepare_Locks(void); |
| extern void PostPrepare_Locks(TransactionId xid); |
| extern int LockCheckConflicts(LockMethod lockMethodTable, |
| LOCKMODE lockmode, |
| LOCK *lock, PROCLOCK *proclock, PGPROC *proc); |
| extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode); |
| extern void GrantAwaitedLock(void); |
| extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode); |
| extern void RemoveLocalLock(LOCALLOCK *locallock); |
| extern Size LockShmemSize(void); |
| extern LockData *GetLockStatusData(void); |
| extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode); |
| |
| extern void lock_twophase_recover(TransactionId xid, uint16 info, |
| void *recdata, uint32 len); |
| extern void lock_twophase_postcommit(TransactionId xid, uint16 info, |
| void *recdata, uint32 len); |
| extern void lock_twophase_postabort(TransactionId xid, uint16 info, |
| void *recdata, uint32 len); |
| |
| extern bool DeadLockCheck(PGPROC *proc); |
| extern void DeadLockReport(void); |
| extern void RememberSimpleDeadLock(PGPROC *proc1, |
| LOCKMODE lockmode, |
| LOCK *lock, |
| PGPROC *proc2); |
| extern void InitDeadLockChecking(void); |
| |
| |
| |
| typedef struct LockStatStd { |
| char lf_locktype[100]; /* 1 */ |
| Oid lf_database; /* 2 */ |
| Oid lf_relation; /* 3 */ |
| uint32 lf_page; /* 4 */ |
| uint16 lf_tuple; /* 5 */ |
| TransactionId lf_transactionid; /* 6 */ |
| Oid lf_classid; /* 7 */ |
| Oid lf_objid; /* 8 */ |
| uint16 lf_objsubid; /* 9 */ |
| TransactionId lf_transaction; /* 10 */ |
| uint32 lf_pid; /* 11 */ |
| char lf_mode[100]; /* 12 */ |
| bool lf_granted; /* 13 */ |
| uint32 lf_mppSessionId; /* 14 */ |
| bool lf_mppIsWriter; /* 15 */ |
| |
| } LockStatStd; |
| |
| extern int LockStatStuff(LockStatStd *lf, int ii, LockData *lockData); |
| |
| |
| #ifdef LOCK_DEBUG |
| extern void DumpLocks(PGPROC *proc); |
| extern void DumpAllLocks(void); |
| #endif |
| |
| #endif /* LOCK_H */ |