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

📄 procarray.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 3 页
字号:
				{					result = true;					break;				}			}			if (result)				break;		}	}	LWLockRelease(ProcArrayLock);	return result;}/* * BackendPidGetProc -- get a backend's PGPROC given its PID * * Returns NULL if not found.  Note that it is up to the caller to be * sure that the question remains meaningful for long enough for the * answer to be used ... */PGPROC *BackendPidGetProc(int pid){	PGPROC	   *result = NULL;	ProcArrayStruct *arrayP = procArray;	int			index;	if (pid == 0)				/* never match dummy PGPROCs */		return NULL;	LWLockAcquire(ProcArrayLock, LW_SHARED);	for (index = 0; index < arrayP->numProcs; index++)	{		PGPROC	   *proc = arrayP->procs[index];		if (proc->pid == pid)		{			result = proc;			break;		}	}	LWLockRelease(ProcArrayLock);	return result;}/* * BackendXidGetPid -- get a backend's pid given its XID * * Returns 0 if not found or it's a prepared transaction.  Note that * it is up to the caller to be sure that the question remains * meaningful for long enough for the answer to be used ... * * Only main transaction Ids are considered.  This function is mainly * useful for determining what backend owns a lock. * * Beware that not every xact has an XID assigned.	However, as long as you * only call this using an XID found on disk, you're safe. */intBackendXidGetPid(TransactionId xid){	int			result = 0;	ProcArrayStruct *arrayP = procArray;	int			index;	if (xid == InvalidTransactionId)	/* never match invalid xid */		return 0;	LWLockAcquire(ProcArrayLock, LW_SHARED);	for (index = 0; index < arrayP->numProcs; index++)	{		volatile PGPROC *proc = arrayP->procs[index];		if (proc->xid == xid)		{			result = proc->pid;			break;		}	}	LWLockRelease(ProcArrayLock);	return result;}/* * IsBackendPid -- is a given pid a running backend */boolIsBackendPid(int pid){	return (BackendPidGetProc(pid) != NULL);}/* * GetCurrentVirtualXIDs -- returns an array of currently active VXIDs. * * The array is palloc'd and is terminated with an invalid VXID. * * If limitXmin is not InvalidTransactionId, we skip any backends * with xmin >= limitXmin.	If allDbs is false, we skip backends attached * to other databases.  If excludeVacuum isn't zero, we skip processes for * which (excludeVacuum & vacuumFlags) is not zero.  Also, our own process * is always skipped. */VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin, bool allDbs, int excludeVacuum){	VirtualTransactionId *vxids;	ProcArrayStruct *arrayP = procArray;	int			count = 0;	int			index;	/* allocate result space with room for a terminator */	vxids = (VirtualTransactionId *)		palloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));	LWLockAcquire(ProcArrayLock, LW_SHARED);	for (index = 0; index < arrayP->numProcs; index++)	{		volatile PGPROC *proc = arrayP->procs[index];		if (proc == MyProc)			continue;		if (excludeVacuum & proc->vacuumFlags)			continue;		if (allDbs || proc->databaseId == MyDatabaseId)		{			/* Fetch xmin just once - might change on us? */			TransactionId pxmin = proc->xmin;			/*			 * Note that InvalidTransactionId precedes all other XIDs, so a			 * proc that hasn't set xmin yet will always be included.			 */			if (!TransactionIdIsValid(limitXmin) ||				TransactionIdPrecedes(pxmin, limitXmin))			{				VirtualTransactionId vxid;				GET_VXID_FROM_PGPROC(vxid, *proc);				if (VirtualTransactionIdIsValid(vxid))					vxids[count++] = vxid;			}		}	}	LWLockRelease(ProcArrayLock);	/* add the terminator */	vxids[count].backendId = InvalidBackendId;	vxids[count].localTransactionId = InvalidLocalTransactionId;	return vxids;}/* * CountActiveBackends --- count backends (other than myself) that are in *		active transactions.  This is used as a heuristic to decide if *		a pre-XLOG-flush delay is worthwhile during commit. * * Do not count backends that are blocked waiting for locks, since they are * not going to get to run until someone else commits. */intCountActiveBackends(void){	ProcArrayStruct *arrayP = procArray;	int			count = 0;	int			index;	/*	 * Note: for speed, we don't acquire ProcArrayLock.  This is a little bit	 * bogus, but since we are only testing fields for zero or nonzero, it	 * should be OK.  The result is only used for heuristic purposes anyway...	 */	for (index = 0; index < arrayP->numProcs; index++)	{		volatile PGPROC *proc = arrayP->procs[index];		if (proc == MyProc)			continue;			/* do not count myself */		if (proc->pid == 0)			continue;			/* do not count prepared xacts */		if (proc->xid == InvalidTransactionId)			continue;			/* do not count if no XID assigned */		if (proc->waitLock != NULL)			continue;			/* do not count if blocked on a lock */		count++;	}	return count;}/* * CountDBBackends --- count backends that are using specified database */intCountDBBackends(Oid databaseid){	ProcArrayStruct *arrayP = procArray;	int			count = 0;	int			index;	LWLockAcquire(ProcArrayLock, LW_SHARED);	for (index = 0; index < arrayP->numProcs; index++)	{		volatile PGPROC *proc = arrayP->procs[index];		if (proc->pid == 0)			continue;			/* do not count prepared xacts */		if (proc->databaseId == databaseid)			count++;	}	LWLockRelease(ProcArrayLock);	return count;}/* * CountUserBackends --- count backends that are used by specified user */intCountUserBackends(Oid roleid){	ProcArrayStruct *arrayP = procArray;	int			count = 0;	int			index;	LWLockAcquire(ProcArrayLock, LW_SHARED);	for (index = 0; index < arrayP->numProcs; index++)	{		volatile PGPROC *proc = arrayP->procs[index];		if (proc->pid == 0)			continue;			/* do not count prepared xacts */		if (proc->roleId == roleid)			count++;	}	LWLockRelease(ProcArrayLock);	return count;}/* * CheckOtherDBBackends -- check for other backends running in the given DB * * If there are other backends in the DB, we will wait a maximum of 5 seconds * for them to exit.  Autovacuum backends are encouraged to exit early by * sending them SIGTERM, but normal user backends are just waited for. * * The current backend is always ignored; it is caller's responsibility to * check whether the current backend uses the given DB, if it's important. * * Returns TRUE if there are (still) other backends in the DB, FALSE if not. * * This function is used to interlock DROP DATABASE and related commands * against there being any active backends in the target DB --- dropping the * DB while active backends remain would be a Bad Thing.  Note that we cannot * detect here the possibility of a newly-started backend that is trying to * connect to the doomed database, so additional interlocking is needed during * backend startup.  The caller should normally hold an exclusive lock on the * target DB before calling this, which is one reason we mustn't wait * indefinitely. */boolCheckOtherDBBackends(Oid databaseId){	ProcArrayStruct *arrayP = procArray;	int			tries;	/* 50 tries with 100ms sleep between tries makes 5 sec total wait */	for (tries = 0; tries < 50; tries++)	{		bool		found = false;		int			index;		CHECK_FOR_INTERRUPTS();		LWLockAcquire(ProcArrayLock, LW_SHARED);		for (index = 0; index < arrayP->numProcs; index++)		{			volatile PGPROC *proc = arrayP->procs[index];			if (proc->databaseId != databaseId)				continue;			if (proc == MyProc)				continue;			found = true;			if (proc->vacuumFlags & PROC_IS_AUTOVACUUM)			{				/* an autovacuum --- send it SIGTERM before sleeping */				int			autopid = proc->pid;				/*				 * It's a bit awkward to release ProcArrayLock within the				 * loop, but we'd probably better do so before issuing kill().				 * We have no idea what might block kill() inside the				 * kernel...				 */				LWLockRelease(ProcArrayLock);				(void) kill(autopid, SIGTERM);	/* ignore any error */				break;			}			else			{				LWLockRelease(ProcArrayLock);				break;			}		}		/* if found is set, we released the lock within the loop body */		if (!found)		{			LWLockRelease(ProcArrayLock);			return false;		/* no conflicting backends, so done */		}		/* else sleep and try again */		pg_usleep(100 * 1000L); /* 100ms */	}	return true;				/* timed out, still conflicts */}#define XidCacheRemove(i) \	do { \		MyProc->subxids.xids[i] = MyProc->subxids.xids[MyProc->subxids.nxids - 1]; \		MyProc->subxids.nxids--; \	} while (0)/* * XidCacheRemoveRunningXids * * Remove a bunch of TransactionIds from the list of known-running * subtransactions for my backend.	Both the specified xid and those in * the xids[] array (of length nxids) are removed from the subxids cache. * latestXid must be the latest XID among the group. */voidXidCacheRemoveRunningXids(TransactionId xid,						  int nxids, const TransactionId *xids,						  TransactionId latestXid){	int			i,				j;	Assert(TransactionIdIsValid(xid));	/*	 * We must hold ProcArrayLock exclusively in order to remove transactions	 * from the PGPROC array.  (See src/backend/access/transam/README.)  It's	 * possible this could be relaxed since we know this routine is only used	 * to abort subtransactions, but pending closer analysis we'd best be	 * conservative.	 */	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);	/*	 * Under normal circumstances xid and xids[] will be in increasing order,	 * as will be the entries in subxids.  Scan backwards to avoid O(N^2)	 * behavior when removing a lot of xids.	 */	for (i = nxids - 1; i >= 0; i--)	{		TransactionId anxid = xids[i];		for (j = MyProc->subxids.nxids - 1; j >= 0; j--)		{			if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))			{				XidCacheRemove(j);				break;			}		}		/*		 * Ordinarily we should have found it, unless the cache has		 * overflowed. However it's also possible for this routine to be		 * invoked multiple times for the same subtransaction, in case of an		 * error during AbortSubTransaction.  So instead of Assert, emit a		 * debug warning.		 */		if (j < 0 && !MyProc->subxids.overflowed)			elog(WARNING, "did not find subXID %u in MyProc", anxid);	}	for (j = MyProc->subxids.nxids - 1; j >= 0; j--)	{		if (TransactionIdEquals(MyProc->subxids.xids[j], xid))		{			XidCacheRemove(j);			break;		}	}	/* Ordinarily we should have found it, unless the cache has overflowed */	if (j < 0 && !MyProc->subxids.overflowed)		elog(WARNING, "did not find subXID %u in MyProc", xid);	/* Also advance global latestCompletedXid while holding the lock */	if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid,							  latestXid))		ShmemVariableCache->latestCompletedXid = latestXid;	LWLockRelease(ProcArrayLock);}#ifdef XIDCACHE_DEBUG/* * Print stats about effectiveness of XID cache */static voidDisplayXidCache(void){	fprintf(stderr,			"XidCache: xmin: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",			xc_by_recent_xmin,			xc_by_my_xact,			xc_by_latest_xid,			xc_by_main_xid,			xc_by_child_xid,			xc_no_overflow,			xc_slow_answer);}#endif   /* XIDCACHE_DEBUG */

⌨️ 快捷键说明

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