diff options
Diffstat (limited to 'src/backend/storage')
-rw-r--r-- | src/backend/storage/ipc/sinval.c | 24 | ||||
-rw-r--r-- | src/backend/storage/ipc/sinvaladt.c | 65 |
2 files changed, 50 insertions, 39 deletions
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index c610147fc5f..fb2e4804dd3 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -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; diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index fcea99dd043..f4b29983433 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -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; |