mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Keep track of the last active slot in the shared ProcState array, so
that search loops only have to scan that far and not through all maxBackends entries. This eliminates a performance penalty for setting maxBackends much higher than the average number of active backends. Also, eliminate no-longer-used 'backend tag' concept. Remove setting of environment variables at backend start (except for CYR_RECODE), since none of them are being examined by the backend any longer.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.22 2000/11/05 22:50:20 vadim Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.23 2000/11/12 20:51:51 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -185,6 +185,9 @@ void
|
||||
/*
|
||||
* DatabaseHasActiveBackends -- are there any backends running in the given DB
|
||||
*
|
||||
* If 'ignoreMyself' is TRUE, ignore this particular backend while checking
|
||||
* for backends in the target database.
|
||||
*
|
||||
* This function is used to interlock DROP DATABASE 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
|
||||
@@ -194,7 +197,7 @@ void
|
||||
*/
|
||||
|
||||
bool
|
||||
DatabaseHasActiveBackends(Oid databaseId)
|
||||
DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself)
|
||||
{
|
||||
bool result = false;
|
||||
SISeg *segP = shmInvalBuffer;
|
||||
@@ -203,7 +206,7 @@ DatabaseHasActiveBackends(Oid databaseId)
|
||||
|
||||
SpinAcquire(SInvalLock);
|
||||
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
for (index = 0; index < segP->lastBackend; index++)
|
||||
{
|
||||
SHMEM_OFFSET pOffset = stateP[index].procStruct;
|
||||
|
||||
@@ -213,6 +216,9 @@ DatabaseHasActiveBackends(Oid databaseId)
|
||||
|
||||
if (proc->databaseId == databaseId)
|
||||
{
|
||||
if (ignoreMyself && proc == MyProc)
|
||||
continue;
|
||||
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
@@ -237,7 +243,7 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||
|
||||
SpinAcquire(SInvalLock);
|
||||
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
for (index = 0; index < segP->lastBackend; index++)
|
||||
{
|
||||
SHMEM_OFFSET pOffset = stateP[index].procStruct;
|
||||
|
||||
@@ -275,7 +281,7 @@ GetXmaxRecent(TransactionId *XmaxRecent)
|
||||
|
||||
SpinAcquire(SInvalLock);
|
||||
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
for (index = 0; index < segP->lastBackend; index++)
|
||||
{
|
||||
SHMEM_OFFSET pOffset = stateP[index].procStruct;
|
||||
|
||||
@@ -309,11 +315,11 @@ GetSnapshotData(bool serializable)
|
||||
int count = 0;
|
||||
|
||||
/*
|
||||
* There can be no more than maxBackends active transactions, so this
|
||||
* There can be no more than lastBackend active transactions, so this
|
||||
* is enough space:
|
||||
*/
|
||||
snapshot->xip = (TransactionId *)
|
||||
malloc(segP->maxBackends * sizeof(TransactionId));
|
||||
malloc(segP->lastBackend * sizeof(TransactionId));
|
||||
snapshot->xmin = GetCurrentTransactionId();
|
||||
|
||||
SpinAcquire(SInvalLock);
|
||||
@@ -326,7 +332,7 @@ GetSnapshotData(bool serializable)
|
||||
*/
|
||||
ReadNewTransactionId(&(snapshot->xmax));
|
||||
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
for (index = 0; index < segP->lastBackend; index++)
|
||||
{
|
||||
SHMEM_OFFSET pOffset = stateP[index].procStruct;
|
||||
|
||||
@@ -386,7 +392,7 @@ GetUndoRecPtr(void)
|
||||
|
||||
SpinAcquire(SInvalLock);
|
||||
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
for (index = 0; index < segP->lastBackend; index++)
|
||||
{
|
||||
SHMEM_OFFSET pOffset = stateP[index].procStruct;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.34 2000/10/02 21:45:32 petere Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.35 2000/11/12 20:51:51 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -117,6 +117,7 @@ SISegInit(SISeg *segP, int maxBackends)
|
||||
/* Clear message counters, save size of procState array */
|
||||
segP->minMsgNum = 0;
|
||||
segP->maxMsgNum = 0;
|
||||
segP->lastBackend = 0;
|
||||
segP->maxBackends = maxBackends;
|
||||
|
||||
/* The buffer[] array is initially all unused, so we need not fill it */
|
||||
@@ -126,7 +127,6 @@ SISegInit(SISeg *segP, int maxBackends)
|
||||
{
|
||||
segP->procState[i].nextMsgNum = -1; /* inactive */
|
||||
segP->procState[i].resetState = false;
|
||||
segP->procState[i].tag = InvalidBackendTag;
|
||||
segP->procState[i].procStruct = INVALID_OFFSET;
|
||||
}
|
||||
}
|
||||
@@ -145,47 +145,45 @@ SIBackendInit(SISeg *segP)
|
||||
int index;
|
||||
ProcState *stateP = NULL;
|
||||
|
||||
Assert(MyBackendTag > 0);
|
||||
|
||||
/* Check for duplicate backend tags (should never happen) */
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
{
|
||||
if (segP->procState[index].tag == MyBackendTag)
|
||||
elog(FATAL, "SIBackendInit: tag %d already in use", MyBackendTag);
|
||||
}
|
||||
|
||||
/* Look for a free entry in the procState array */
|
||||
for (index = 0; index < segP->maxBackends; index++)
|
||||
for (index = 0; index < segP->lastBackend; index++)
|
||||
{
|
||||
if (segP->procState[index].tag == InvalidBackendTag)
|
||||
if (segP->procState[index].nextMsgNum < 0) /* inactive slot? */
|
||||
{
|
||||
stateP = &segP->procState[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* elog() with spinlock held is probably not too cool, but this
|
||||
* condition should never happen anyway.
|
||||
*/
|
||||
if (stateP == NULL)
|
||||
{
|
||||
elog(NOTICE, "SIBackendInit: no free procState slot available");
|
||||
MyBackendId = InvalidBackendTag;
|
||||
return 0;
|
||||
if (segP->lastBackend < segP->maxBackends)
|
||||
{
|
||||
stateP = &segP->procState[segP->lastBackend];
|
||||
Assert(stateP->nextMsgNum < 0);
|
||||
segP->lastBackend++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* elog() with spinlock held is probably not too cool, but this
|
||||
* condition should never happen anyway.
|
||||
*/
|
||||
elog(NOTICE, "SIBackendInit: no free procState slot available");
|
||||
MyBackendId = InvalidBackendId;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
MyBackendId = (stateP - &segP->procState[0]) + 1;
|
||||
|
||||
#ifdef INVALIDDEBUG
|
||||
elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.",
|
||||
MyBackendTag, MyBackendId);
|
||||
elog(DEBUG, "SIBackendInit: backend id %d", MyBackendId);
|
||||
#endif /* INVALIDDEBUG */
|
||||
|
||||
/* mark myself active, with all extant messages already read */
|
||||
stateP->nextMsgNum = segP->maxMsgNum;
|
||||
stateP->resetState = false;
|
||||
stateP->tag = MyBackendTag;
|
||||
stateP->procStruct = MAKE_OFFSET(MyProc);
|
||||
|
||||
/* register exit routine to mark my entry inactive at exit */
|
||||
@@ -206,17 +204,26 @@ SIBackendInit(SISeg *segP)
|
||||
static void
|
||||
CleanupInvalidationState(int status, Datum arg)
|
||||
{
|
||||
SISeg *segP = (void*) DatumGetPointer(arg);
|
||||
SISeg *segP = (SISeg *) DatumGetPointer(arg);
|
||||
int i;
|
||||
|
||||
Assert(PointerIsValid(segP));
|
||||
|
||||
SpinAcquire(SInvalLock);
|
||||
|
||||
/* Mark myself inactive */
|
||||
segP->procState[MyBackendId - 1].nextMsgNum = -1;
|
||||
segP->procState[MyBackendId - 1].resetState = false;
|
||||
segP->procState[MyBackendId - 1].tag = InvalidBackendTag;
|
||||
segP->procState[MyBackendId - 1].procStruct = INVALID_OFFSET;
|
||||
|
||||
/* Recompute index of last active backend */
|
||||
for (i = segP->lastBackend; i > 0; i--)
|
||||
{
|
||||
if (segP->procState[i - 1].nextMsgNum >= 0)
|
||||
break;
|
||||
}
|
||||
segP->lastBackend = i;
|
||||
|
||||
SpinRelease(SInvalLock);
|
||||
}
|
||||
|
||||
@@ -299,7 +306,7 @@ SISetProcStateInvalid(SISeg *segP)
|
||||
segP->minMsgNum = 0;
|
||||
segP->maxMsgNum = 0;
|
||||
|
||||
for (i = 0; i < segP->maxBackends; i++)
|
||||
for (i = 0; i < segP->lastBackend; i++)
|
||||
{
|
||||
if (segP->procState[i].nextMsgNum >= 0) /* active backend? */
|
||||
{
|
||||
@@ -325,8 +332,6 @@ SIGetDataEntry(SISeg *segP, int backendId,
|
||||
{
|
||||
ProcState *stateP = &segP->procState[backendId - 1];
|
||||
|
||||
Assert(stateP->tag == MyBackendTag);
|
||||
|
||||
if (stateP->resetState)
|
||||
{
|
||||
|
||||
@@ -373,7 +378,7 @@ SIDelExpiredDataEntries(SISeg *segP)
|
||||
|
||||
/* Recompute minMsgNum = minimum of all backends' nextMsgNum */
|
||||
|
||||
for (i = 0; i < segP->maxBackends; i++)
|
||||
for (i = 0; i < segP->lastBackend; i++)
|
||||
{
|
||||
h = segP->procState[i].nextMsgNum;
|
||||
if (h >= 0)
|
||||
@@ -392,7 +397,7 @@ SIDelExpiredDataEntries(SISeg *segP)
|
||||
{
|
||||
segP->minMsgNum -= MSGNUMWRAPAROUND;
|
||||
segP->maxMsgNum -= MSGNUMWRAPAROUND;
|
||||
for (i = 0; i < segP->maxBackends; i++)
|
||||
for (i = 0; i < segP->lastBackend; i++)
|
||||
{
|
||||
if (segP->procState[i].nextMsgNum >= 0)
|
||||
segP->procState[i].nextMsgNum -= MSGNUMWRAPAROUND;
|
||||
|
||||
Reference in New Issue
Block a user