cks of all types.
* granted -- countof each lock type currently granted on the lock.
* nGranted --total granted locks of all types.
*
* Note: thesecounts count 1 for each backend. Internally to a backend,
* there may bemultiple grabs on a particular lock, but this is not reflected
* into sharedmemory.
*/
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 ofrequested locks */
int nRequested; /* total ofrequested[] array */
int granted[MAX_LOCKMODES];/* counts of granted locks */
int nGranted; /* total ofgranted[] array */
} LOCK;
pg可以有多个不同的backend进程在同一个开锁对象上持有或等待锁。pg需要为每个持有者/等待着存储一些信息。这些保存在结构PROCLOCK里。
PROCLOCKTAG是在proclock哈希表里查找一个PROCLOCK项的关键信息。一个PROCLOCKTAG值唯一的标识一个可锁对象和一个持有者/等待着的组合。(这儿pg能使用指针,因为PROCLOCKTAG仅需要在PROCLOCK的生命周期里唯一,且不会在lock和proc生存期以为)
为了不同的目的,backend进程可以持有同一个锁:独立于会话锁,backend进程跟踪事务锁。但是,这个在共享内存状态中没有反映出来:pg仅跟踪持有锁的backend进程。这是可以的,因为backend进程不能阻塞自己。
holdMask字段显示已经授予的由proclock代表的锁。注意,可能有一个具有0 holdMask的proclock对象,对于任何锁,进程当前正在等待它。负责,holdMask是0的proclock对象在方便的时候被尽快回收。
* releaseMask is workspace for LockReleaseAll(): it showsthe locks due
* to be releasedduring the current call. This must onlybe examined or
* set by thebackend owning the PROCLOCK.
每一个PROCLOCK对象被链接到链表,为了相关LOCK对象和所属PGPROC对象。注意,PROCLOCK对象一被创建就就加入到这些链表,甚至还没有锁lock被授予的时候。等待lock锁被授予的PGPROC进程也会被链接到锁的等待进程(waitProcs)队列。
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; /* uniqueidentifier 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 */
} PROCLOCK;
每一个backend进程还维持一个本地哈希表,其记录着目前感兴趣的每一个锁lock的信息。特别的,本地表记录着获得的这些锁的时间。这允许不额外访问共享内存的情况下对同一个锁多请求被执行。为了pg能释放属于某个特别资源属主(ResourceOwner)的锁。pg还跟踪每个资源属主(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 heldon behalf of the session;
* otherwise it is held on behalf of my currenttransaction.
*
* Must use a forward struct reference to avoidcircularity.
*/
struct ResourceOwnerData *owner;
int64 nLocks; /* # of times held by this owner */
} LOCALLOCKOWNER;
typedef struct LOCALLOCK
{
/* tag */
LOCALLOCKTAG tag