/* * ReceiveSharedInvalidMessages * Process shared-cache-invalidation messages waiting for this backend * * NOTE: it is entirely possible for this routine to be invoked recursively * as a consequence of processing inside the invalFunction or resetFunction. * Hence, we must be holding no SI resources when we call them. The only * bad side-effect is that SIDelExpiredDataEntries might be called extra * times on the way out of a nested call. */ void ReceiveSharedInvalidMessages( void (*invalFunction) (SharedInvalidationMessage *msg), void (*resetFunction) (void)) { SharedInvalidationMessage data; int getResult; bool gotMessage = false; for (;;) { /* * We can run SIGetDataEntry in parallel with other backends * running SIGetDataEntry for themselves, since each instance will * modify only fields of its own backend's ProcState, and no * instance will look at fields of other backends' ProcStates. We * express this by grabbing SInvalLock in shared mode. Note that * this is not exactly the normal (read-only) interpretation of a * shared lock! Look closely at the interactions before allowing * SInvalLock to be grabbed in shared mode for any other reason! * * The routines later in this file that use shared mode are okay with * this, because they aren't looking at the ProcState fields * associated with SI message transfer; they only use the * ProcState array as an easy way to find all the PGPROC * structures. */ LWLockAcquire(SInvalLock, LW_SHARED); getResult = SIGetDataEntry(shmInvalBuffer, MyBackendId, &data); LWLockRelease(SInvalLock); if (getResult == 0) break; /* nothing more to do */ if (getResult < 0) { /* got a reset message */ elog(DEBUG4, "cache state reset"); resetFunction(); } else { /* got a normal data message */ invalFunction(&data); } gotMessage = true; } /* If we got any messages, try to release dead messages */ if (gotMessage) { LWLockAcquire(SInvalLock, LW_EXCLUSIVE); SIDelExpiredDataEntries(shmInvalBuffer); LWLockRelease(SInvalLock); } }
/* * ReceiveSharedInvalidMessages * Process shared-cache-invalidation messages waiting for this backend * * NOTE: it is entirely possible for this routine to be invoked recursively * as a consequence of processing inside the invalFunction or resetFunction. * Hence, we must be holding no SI resources when we call them. The only * bad side-effect is that SIDelExpiredDataEntries might be called extra * times on the way out of a nested call. */ void ReceiveSharedInvalidMessages( void (*invalFunction) (SharedInvalidationMessage *msg), void (*resetFunction) (void)) { SharedInvalidationMessage data; int getResult; bool gotMessage = false; for (;;) { /* * We can discard any pending catchup event, since we will not exit * this loop until we're fully caught up. */ catchupInterruptOccurred = 0; /* * We can run SIGetDataEntry in parallel with other backends running * SIGetDataEntry for themselves, since each instance will modify only * fields of its own backend's ProcState, and no instance will look at * fields of other backends' ProcStates. We express this by grabbing * SInvalLock in shared mode. Note that this is not exactly the * normal (read-only) interpretation of a shared lock! Look closely at * the interactions before allowing SInvalLock to be grabbed in shared * mode for any other reason! */ LWLockAcquire(SInvalLock, LW_SHARED); getResult = SIGetDataEntry(shmInvalBuffer, MyBackendId, &data); LWLockRelease(SInvalLock); if (getResult == 0) break; /* nothing more to do */ if (getResult < 0) { /* got a reset message */ elog(DEBUG4, "cache state reset"); resetFunction(); } else { /* got a normal data message */ invalFunction(&data); } gotMessage = true; } /* If we got any messages, try to release dead messages */ if (gotMessage) { LWLockAcquire(SInvalLock, LW_EXCLUSIVE); SIDelExpiredDataEntries(shmInvalBuffer); LWLockRelease(SInvalLock); } }