postgres/src/include/storage/sinvaladt.h
Tom Lane bbbc00af88 Clean up some longstanding problems in shared-cache invalidation.
SI messages now include the relevant database OID, so that operations
in one database do not cause useless cache flushes in backends attached
to other databases.  Declare SI messages properly using a union, to
eliminate the former assumption that Oid is the same size as int or Index.
Rewrite the nearly-unreadable code in inval.c, and document it better.
Arrange for catcache flushes at end of command/transaction to happen before
relcache flushes do --- this avoids loading a new tuple into the catcache
while setting up new relcache entry, only to have it be flushed again
immediately.
2001-06-19 19:42:16 +00:00

119 lines
4.1 KiB
C

/*-------------------------------------------------------------------------
*
* sinvaladt.h
* POSTGRES shared cache invalidation segment definitions.
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: sinvaladt.h,v 1.27 2001/06/19 19:42:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef SINVALADT_H
#define SINVALADT_H
#include "storage/shmem.h"
#include "storage/sinval.h"
/*
* The shared cache invalidation manager is responsible for transmitting
* invalidation messages between backends. Any message sent by any backend
* must be delivered to all already-running backends before it can be
* forgotten.
*
* Conceptually, the messages are stored in an infinite array, where
* maxMsgNum is the next array subscript to store a submitted message in,
* minMsgNum is the smallest array subscript containing a message not yet
* read by all backends, and we always have maxMsgNum >= minMsgNum. (They
* are equal when there are no messages pending.) For each active backend,
* there is a nextMsgNum pointer indicating the next message it needs to read;
* we have maxMsgNum >= nextMsgNum >= minMsgNum for every backend.
*
* In reality, the messages are stored in a circular buffer of MAXNUMMESSAGES
* entries. We translate MsgNum values into circular-buffer indexes by
* computing MsgNum % MAXNUMMESSAGES (this should be fast as long as
* MAXNUMMESSAGES is a constant and a power of 2). As long as maxMsgNum
* doesn't exceed minMsgNum by more than MAXNUMMESSAGES, we have enough space
* in the buffer. If the buffer does overflow, we reset it to empty and
* force each backend to "reset", ie, discard all its invalidatable state.
*
* We would have problems if the MsgNum values overflow an integer, so
* whenever minMsgNum exceeds MSGNUMWRAPAROUND, we subtract MSGNUMWRAPAROUND
* from all the MsgNum variables simultaneously. MSGNUMWRAPAROUND can be
* large so that we don't need to do this often. It must be a multiple of
* MAXNUMMESSAGES so that the existing circular-buffer entries don't need
* to be moved when we do it.
*
* The struct type SharedInvalidationMessage, defining the contents of
* a single message, is defined in sinval.h.
*/
/*
* Configurable parameters.
*
* MAXNUMMESSAGES: max number of shared-inval messages we can buffer.
* Must be a power of 2 for speed.
*
* MSGNUMWRAPAROUND: how often to reduce MsgNum variables to avoid overflow.
* Must be a multiple of MAXNUMMESSAGES. Should be large.
*/
#define MAXNUMMESSAGES 4096
#define MSGNUMWRAPAROUND (MAXNUMMESSAGES * 4096)
/* Per-backend state in shared invalidation structure */
typedef struct ProcState
{
/* nextMsgNum is -1 in an inactive ProcState array entry. */
int nextMsgNum; /* next message number to read, or -1 */
bool resetState; /* true, if backend has to reset its state */
SHMEM_OFFSET procStruct; /* location of backend's PROC struct */
} ProcState;
/* Shared cache invalidation memory segment */
typedef struct SISeg
{
/*
* General state information
*/
int minMsgNum; /* oldest message still needed */
int maxMsgNum; /* next message number to be assigned */
int lastBackend; /* index of last active procState entry,
* +1 */
int maxBackends; /* size of procState array */
/*
* Circular buffer holding shared-inval messages
*/
SharedInvalidationMessage buffer[MAXNUMMESSAGES];
/*
* Per-backend state info.
*
* We declare procState as 1 entry because C wants a fixed-size array,
* but actually it is maxBackends entries long.
*/
ProcState procState[1]; /* reflects the invalidation state */
} SISeg;
extern SISeg *shmInvalBuffer; /* pointer to the shared inval buffer */
/*
* prototypes for functions in sinvaladt.c
*/
extern void SIBufferInit(int maxBackends);
extern int SIBackendInit(SISeg *segP);
extern bool SIInsertDataEntry(SISeg *segP, SharedInvalidationMessage *data);
extern int SIGetDataEntry(SISeg *segP, int backendId,
SharedInvalidationMessage *data);
extern void SIDelExpiredDataEntries(SISeg *segP);
#endif /* SINVALADT_H */