⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lock.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
		MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG));		proclocktag.lock = MAKE_OFFSET(lock);		proclocktag.proc = MAKE_OFFSET(newproc);		newproclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid],											   (void *) &proclocktag,											   HASH_ENTER_NULL, &found);		if (!newproclock)			ereport(PANIC,		/* should not happen */					(errcode(ERRCODE_OUT_OF_MEMORY),					 errmsg("out of shared memory"),					 errdetail("Not enough memory for reassigning the prepared transaction's locks.")));		/*		 * If new, initialize the new entry		 */		if (!found)		{			newproclock->holdMask = 0;			newproclock->releaseMask = 0;			/* Add new proclock to appropriate lists */			SHMQueueInsertBefore(&lock->procLocks, &newproclock->lockLink);			SHMQueueInsertBefore(&newproc->procLocks, &newproclock->procLink);			PROCLOCK_PRINT("PostPrepare_Locks: new", newproclock);		}		else		{			PROCLOCK_PRINT("PostPrepare_Locks: found", newproclock);			Assert((newproclock->holdMask & ~lock->grantMask) == 0);		}		/*		 * Pass over the identified lock ownership.		 */		Assert((newproclock->holdMask & holdMask) == 0);		newproclock->holdMask |= holdMask;next_item:		proclock = nextplock;	}	LWLockRelease(masterLock);	END_CRIT_SECTION();}/* * Estimate shared-memory space used for lock tables */SizeLockShmemSize(void){	Size		size;	long		max_table_size = NLOCKENTS();	/* lock method headers */	size = MAX_LOCK_METHODS * MAXALIGN(sizeof(LockMethodData));	/* lockHash table */	size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));	/* proclockHash table */	size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));	/*	 * Note we count only one pair of hash tables, since the userlocks table	 * actually overlays the main one.	 *	 * Since the lockHash entry count above is only an estimate, add 10%	 * safety margin.	 */	size = add_size(size, size / 10);	return size;}/* * GetLockStatusData - Return a summary of the lock manager's internal * status, for use in a user-level reporting function. * * The return data consists of an array of PROCLOCK objects, with the * associated PGPROC and LOCK objects for each.  Note that multiple * copies of the same PGPROC and/or LOCK objects are likely to appear. * It is the caller's responsibility to match up duplicates if wanted. * * The design goal is to hold the LockMgrLock for as short a time as possible; * thus, this function simply makes a copy of the necessary data and releases * the lock, allowing the caller to contemplate and format the data for as * long as it pleases. */LockData *GetLockStatusData(void){	LockData   *data;	HTAB	   *proclockTable;	PROCLOCK   *proclock;	HASH_SEQ_STATUS seqstat;	int			i;	data = (LockData *) palloc(sizeof(LockData));	LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);	proclockTable = LockMethodProcLockHash[DEFAULT_LOCKMETHOD];	data->nelements = i = proclockTable->hctl->nentries;	data->proclockaddrs = (SHMEM_OFFSET *) palloc(sizeof(SHMEM_OFFSET) * i);	data->proclocks = (PROCLOCK *) palloc(sizeof(PROCLOCK) * i);	data->procs = (PGPROC *) palloc(sizeof(PGPROC) * i);	data->locks = (LOCK *) palloc(sizeof(LOCK) * i);	hash_seq_init(&seqstat, proclockTable);	i = 0;	while ((proclock = hash_seq_search(&seqstat)))	{		PGPROC	   *proc = (PGPROC *) MAKE_PTR(proclock->tag.proc);		LOCK	   *lock = (LOCK *) MAKE_PTR(proclock->tag.lock);		data->proclockaddrs[i] = MAKE_OFFSET(proclock);		memcpy(&(data->proclocks[i]), proclock, sizeof(PROCLOCK));		memcpy(&(data->procs[i]), proc, sizeof(PGPROC));		memcpy(&(data->locks[i]), lock, sizeof(LOCK));		i++;	}	LWLockRelease(LockMgrLock);	Assert(i == data->nelements);	return data;}/* Provide the textual name of any lock mode */const char *GetLockmodeName(LOCKMODE mode){	Assert(mode <= MAX_LOCKMODES);	return lock_mode_names[mode];}#ifdef LOCK_DEBUG/* * Dump all locks in the given proc's procLocks list. * * Must have already acquired the masterLock. */voidDumpLocks(PGPROC *proc){	SHM_QUEUE  *procLocks;	PROCLOCK   *proclock;	LOCK	   *lock;	int			lockmethodid = DEFAULT_LOCKMETHOD;	LockMethod	lockMethodTable;	if (proc == NULL)		return;	procLocks = &proc->procLocks;	Assert(lockmethodid < NumLockMethods);	lockMethodTable = LockMethods[lockmethodid];	if (!lockMethodTable)		return;	if (proc->waitLock)		LOCK_PRINT("DumpLocks: waiting on", proc->waitLock, 0);	proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,										 offsetof(PROCLOCK, procLink));	while (proclock)	{		Assert(proclock->tag.proc == MAKE_OFFSET(proc));		lock = (LOCK *) MAKE_PTR(proclock->tag.lock);		PROCLOCK_PRINT("DumpLocks", proclock);		LOCK_PRINT("DumpLocks", lock, 0);		proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->procLink,											 offsetof(PROCLOCK, procLink));	}}/* * Dump all postgres locks. Must have already acquired the masterLock. */voidDumpAllLocks(void){	PGPROC	   *proc;	PROCLOCK   *proclock;	LOCK	   *lock;	int			lockmethodid = DEFAULT_LOCKMETHOD;	LockMethod	lockMethodTable;	HTAB	   *proclockTable;	HASH_SEQ_STATUS status;	proc = MyProc;	if (proc == NULL)		return;	Assert(lockmethodid < NumLockMethods);	lockMethodTable = LockMethods[lockmethodid];	if (!lockMethodTable)		return;	proclockTable = LockMethodProcLockHash[lockmethodid];	if (proc->waitLock)		LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0);	hash_seq_init(&status, proclockTable);	while ((proclock = (PROCLOCK *) hash_seq_search(&status)) != NULL)	{		PROCLOCK_PRINT("DumpAllLocks", proclock);		if (proclock->tag.lock)		{			lock = (LOCK *) MAKE_PTR(proclock->tag.lock);			LOCK_PRINT("DumpAllLocks", lock, 0);		}		else			elog(LOG, "DumpAllLocks: proclock->tag.lock = NULL");	}}#endif   /* LOCK_DEBUG *//* * LOCK 2PC resource manager's routines *//* * Re-acquire a lock belonging to a transaction that was prepared. * * Because this function is run at db startup, re-acquiring the locks should * never conflict with running transactions because there are none.  We * assume that the lock state represented by the stored 2PC files is legal. */voidlock_twophase_recover(TransactionId xid, uint16 info,					  void *recdata, uint32 len){	TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;	PGPROC	   *proc = TwoPhaseGetDummyProc(xid);	LOCKTAG    *locktag;	LOCKMODE	lockmode;	LOCKMETHODID lockmethodid;	LOCK	   *lock;	PROCLOCK   *proclock;	PROCLOCKTAG proclocktag;	bool		found;	LWLockId	masterLock;	LockMethod	lockMethodTable;	Assert(len == sizeof(TwoPhaseLockRecord));	locktag = &rec->locktag;	lockmode = rec->lockmode;	lockmethodid = locktag->locktag_lockmethodid;	Assert(lockmethodid < NumLockMethods);	lockMethodTable = LockMethods[lockmethodid];	if (!lockMethodTable)		elog(ERROR, "unrecognized lock method: %d", lockmethodid);	masterLock = lockMethodTable->masterLock;	LWLockAcquire(masterLock, LW_EXCLUSIVE);	/*	 * Find or create a lock with this tag.	 */	lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],								(void *) locktag,								HASH_ENTER_NULL, &found);	if (!lock)	{		LWLockRelease(masterLock);		ereport(ERROR,				(errcode(ERRCODE_OUT_OF_MEMORY),				 errmsg("out of shared memory"),			errhint("You may need to increase max_locks_per_transaction.")));	}	/*	 * if it's a new lock object, initialize it	 */	if (!found)	{		lock->grantMask = 0;		lock->waitMask = 0;		SHMQueueInit(&(lock->procLocks));		ProcQueueInit(&(lock->waitProcs));		lock->nRequested = 0;		lock->nGranted = 0;		MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);		MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);		LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);	}	else	{		LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);		Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));		Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));		Assert(lock->nGranted <= lock->nRequested);	}	/*	 * Create the hash key for the proclock table.	 */	MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG));		/* must clear padding */	proclocktag.lock = MAKE_OFFSET(lock);	proclocktag.proc = MAKE_OFFSET(proc);	/*	 * Find or create a proclock entry with this tag	 */	proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid],										(void *) &proclocktag,										HASH_ENTER_NULL, &found);	if (!proclock)	{		/* Ooops, not enough shmem for the proclock */		if (lock->nRequested == 0)		{			/*			 * There are no other requestors of this lock, so garbage-collect			 * the lock object.  We *must* do this to avoid a permanent leak			 * of shared memory, because there won't be anything to cause			 * anyone to release the lock object later.			 */			Assert(SHMQueueEmpty(&(lock->procLocks)));			if (!hash_search(LockMethodLockHash[lockmethodid],							 (void *) &(lock->tag),							 HASH_REMOVE, NULL))				elog(PANIC, "lock table corrupted");		}		LWLockRelease(masterLock);		ereport(ERROR,				(errcode(ERRCODE_OUT_OF_MEMORY),				 errmsg("out of shared memory"),			errhint("You may need to increase max_locks_per_transaction.")));	}	/*	 * If new, initialize the new entry	 */	if (!found)	{		proclock->holdMask = 0;		proclock->releaseMask = 0;		/* Add proclock to appropriate lists */		SHMQueueInsertBefore(&lock->procLocks, &proclock->lockLink);		SHMQueueInsertBefore(&proc->procLocks, &proclock->procLink);		PROCLOCK_PRINT("lock_twophase_recover: new", proclock);	}	else	{		PROCLOCK_PRINT("lock_twophase_recover: found", proclock);		Assert((proclock->holdMask & ~lock->grantMask) == 0);	}	/*	 * lock->nRequested and lock->requested[] count the total number of	 * requests, whether granted or waiting, so increment those immediately.	 */	lock->nRequested++;	lock->requested[lockmode]++;	Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));	/*	 * We shouldn't already hold the desired lock.	 */	if (proclock->holdMask & LOCKBIT_ON(lockmode))		elog(ERROR, "lock %s on object %u/%u/%u is already held",			 lock_mode_names[lockmode],			 lock->tag.locktag_field1, lock->tag.locktag_field2,			 lock->tag.locktag_field3);	/*	 * We ignore any possible conflicts and just grant ourselves the lock.	 */	GrantLock(lock, proclock, lockmode);	LWLockRelease(masterLock);}/* * 2PC processing routine for COMMIT PREPARED case. * * Find and release the lock indicated by the 2PC record. */voidlock_twophase_postcommit(TransactionId xid, uint16 info,						 void *recdata, uint32 len){	TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;	PGPROC	   *proc = TwoPhaseGetDummyProc(xid);	LOCKTAG    *locktag;	LOCKMODE	lockmode;	LOCKMETHODID lockmethodid;	PROCLOCKTAG proclocktag;	LOCK	   *lock;	PROCLOCK   *proclock;	LWLockId	masterLock;	LockMethod	lockMethodTable;	bool		wakeupNeeded;	Assert(len == sizeof(TwoPhaseLockRecord));	locktag = &rec->locktag;	lockmode = rec->lockmode;	lockmethodid = locktag->locktag_lockmethodid;	Assert(lockmethodid < NumLockMethods);	lockMethodTable = LockMethods[lockmethodid];	if (!lockMethodTable)		elog(ERROR, "unrecognized lock method: %d", lockmethodid);	masterLock = lockMethodTable->masterLock;	LWLockAcquire(masterLock, LW_EXCLUSIVE);	/*	 * Re-find the lock object (it had better be there).	 */	lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],								(void *) locktag,								HASH_FIND, NULL);	if (!lock)		elog(PANIC, "failed to re-find shared lock object");	/*	 * Re-find the proclock object (ditto).	 */	MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG));		/* must clear padding */	proclocktag.lock = MAKE_OFFSET(lock);	proclocktag.proc = MAKE_OFFSET(proc);	proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid],										(void *) &proclocktag,										HASH_FIND, NULL);	if (!proclock)		elog(PANIC, "failed to re-find shared proclock object");	/*	 * Double-check that we are actually holdin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -