📄 sinvaladt.c
字号:
/*------------------------------------------------------------------------- * * sinvaladt.c * POSTGRES shared cache invalidation segment definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.20 1999/05/28 17:03:28 tgl Exp $ * *------------------------------------------------------------------------- */#include <stdio.h>#include <signal.h>#include <unistd.h>#include "postgres.h"#include "storage/ipc.h"#include "storage/backendid.h"#include "storage/sinvaladt.h"#include "storage/lmgr.h"#include "utils/memutils.h"#include "utils/palloc.h"#include "utils/trace.h"/* ---------------- * global variable notes * * SharedInvalidationSemaphore * * shmInvalBuffer * the shared buffer segment, set by SISegmentAttach() * * MyBackendId * might be removed later, used only for * debugging in debug routines (end of file) * * SIDbId * identification of buffer (disappears) * * SIRelId \ * SIDummyOid \ identification of buffer * SIXidData / * SIXid / * * XXX This file really needs to be cleaned up. We switched to using * spinlocks to protect critical sections (as opposed to using fake * relations and going through the lock manager) and some of the old * cruft was 'ifdef'ed out, while other parts (now unused) are still * compiled into the system. -mer 5/24/92 * ---------------- */#ifdef HAS_TEST_AND_SETint SharedInvalidationLockId;#elseIpcSemaphoreId SharedInvalidationSemaphore;#endifSISeg *shmInvalBuffer;extern BackendId MyBackendId;static void CleanupInvalidationState(int status, SISeg *segInOutP);static BackendId SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag);static int SIGetNumEntries(SISeg *segP);/************************************************************************//* SISetActiveProcess(segP, backendId) set the backend status active *//* should be called only by the postmaster when creating a backend *//************************************************************************//* XXX I suspect that the segP parameter is extraneous. -hirohama */static voidSISetActiveProcess(SISeg *segInOutP, BackendId backendId){ /* mark all messages as read */ /* Assert(segP->procState[backendId - 1].tag == MyBackendTag); */ segInOutP->procState[backendId - 1].resetState = false; segInOutP->procState[backendId - 1].limit = SIGetNumEntries(segInOutP);}/****************************************************************************//* SIBackendInit() initializes a backend to operate on the buffer *//****************************************************************************/intSIBackendInit(SISeg *segInOutP){ LockRelId LtCreateRelId(); TransactionId LMITransactionIdCopy(); Assert(MyBackendTag > 0); MyBackendId = SIAssignBackendId(segInOutP, MyBackendTag); if (MyBackendId == InvalidBackendTag) return 0;#ifdef INVALIDDEBUG elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.", MyBackendTag, MyBackendId);#endif /* INVALIDDEBUG */ SISetActiveProcess(segInOutP, MyBackendId); on_shmem_exit(CleanupInvalidationState, (caddr_t) segInOutP); return 1;}/* ---------------- * SIAssignBackendId * ---------------- */static BackendIdSIAssignBackendId(SISeg *segInOutP, BackendTag backendTag){ Index index; ProcState *stateP = NULL; for (index = 0; index < segInOutP->maxBackends; index++) { if (segInOutP->procState[index].tag == InvalidBackendTag || segInOutP->procState[index].tag == backendTag) { stateP = &segInOutP->procState[index]; break; } if (!PointerIsValid(stateP) || (segInOutP->procState[index].resetState && (!stateP->resetState || stateP->tag < backendTag)) || (!stateP->resetState && (segInOutP->procState[index].limit < stateP->limit || stateP->tag < backendTag))) stateP = &segInOutP->procState[index]; } /* verify that all "procState" entries checked for matching tags */ for (index++; index < segInOutP->maxBackends; index++) { if (segInOutP->procState[index].tag == backendTag) elog(FATAL, "SIAssignBackendId: tag %d found twice", backendTag); } Assert(stateP); if (stateP->tag != InvalidBackendTag) { if (stateP->tag == backendTag) elog(NOTICE, "SIAssignBackendId: reusing tag %d", backendTag); else { elog(NOTICE, "SIAssignBackendId: discarding tag %d", stateP->tag); return InvalidBackendTag; } } stateP->tag = backendTag; return 1 + stateP - &segInOutP->procState[0];}/************************************************************************//* The following function should be called only by the postmaster !! *//************************************************************************//************************************************************************//* SISetDeadProcess(segP, backendId) set the backend status DEAD *//* should be called only by the postmaster when a backend died *//************************************************************************/static voidSISetDeadProcess(SISeg *segP, int backendId){ /* XXX call me.... */ segP->procState[backendId - 1].resetState = false; segP->procState[backendId - 1].limit = -1; segP->procState[backendId - 1].tag = InvalidBackendTag;}/* * CleanupInvalidationState * Note: * This is a temporary hack. ExitBackend should call this instead * of exit (via on_shmem_exit). */static voidCleanupInvalidationState(int status, /* XXX */ SISeg *segInOutP) /* XXX style */{ Assert(PointerIsValid(segInOutP)); SISetDeadProcess(segInOutP, MyBackendId);}/************************************************************************//* SIComputeSize() - compute size and offsets for SI segment *//************************************************************************/static voidSIComputeSize(SISegOffsets *oP, int maxBackends){ int A, B, a, b, totalSize; A = 0; /* sizeof(SISeg) includes the first ProcState entry */ a = sizeof(SISeg) + sizeof(ProcState) * (maxBackends - 1); a = MAXALIGN(a); /* offset to first data entry */ b = sizeof(SISegEntry) * MAXNUMMESSAGES; B = A + a + b; B = MAXALIGN(B); totalSize = B - A; oP->startSegment = A; oP->offsetToFirstEntry = a; /* relative to A */ oP->offsetToEndOfSegment = totalSize; /* relative to A */}/************************************************************************//* SISetStartEntrySection(segP, offset) - sets the offset *//************************************************************************/static voidSISetStartEntrySection(SISeg *segP, Offset offset){ segP->startEntrySection = offset;}/************************************************************************//* SIGetStartEntrySection(segP) - returnss the offset *//************************************************************************/static OffsetSIGetStartEntrySection(SISeg *segP){ return segP->startEntrySection;}/************************************************************************//* SISetEndEntrySection(segP, offset) - sets the offset *//************************************************************************/static voidSISetEndEntrySection(SISeg *segP, Offset offset){ segP->endEntrySection = offset;}/************************************************************************//* SISetEndEntryChain(segP, offset) - sets the offset *//************************************************************************/static voidSISetEndEntryChain(SISeg *segP, Offset offset){ segP->endEntryChain = offset;}/************************************************************************//* SIGetEndEntryChain(segP) - returnss the offset *//************************************************************************/static OffsetSIGetEndEntryChain(SISeg *segP){ return segP->endEntryChain;}/************************************************************************//* SISetStartEntryChain(segP, offset) - sets the offset *//************************************************************************/static voidSISetStartEntryChain(SISeg *segP, Offset offset){ segP->startEntryChain = offset;}/************************************************************************//* SIGetStartEntryChain(segP) - returns the offset *//************************************************************************/static OffsetSIGetStartEntryChain(SISeg *segP){ return segP->startEntryChain;}/************************************************************************//* SISetNumEntries(segP, num) sets the current nuber of entries *//************************************************************************/static boolSISetNumEntries(SISeg *segP, int num){ if (num <= MAXNUMMESSAGES) { segP->numEntries = num; return true; } else { return false; /* table full */ }}/************************************************************************//* SIGetNumEntries(segP) - returns the current nuber of entries *//************************************************************************/static intSIGetNumEntries(SISeg *segP){ return segP->numEntries;}/************************************************************************//* SISetMaxNumEntries(segP, num) sets the maximal number of entries *//************************************************************************/static boolSISetMaxNumEntries(SISeg *segP, int num){ if (num <= MAXNUMMESSAGES) { segP->maxNumEntries = num; return true; } else { return false; /* wrong number */ }}/************************************************************************//* SIGetProcStateLimit(segP, i) returns the limit of read messages *//************************************************************************/#define SIGetProcStateLimit(segP,i) \ ((segP)->procState[i].limit)/************************************************************************//* SIIncNumEntries(segP, num) increments the current nuber of entries *//************************************************************************/static boolSIIncNumEntries(SISeg *segP, int num){ /* * Try to prevent table overflow. When the table is 70% full send a * SIGUSR2 to the postmaster which will send it back to all the * backends. This will be handled by Async_NotifyHandler() with a * StartTransactionCommand() which will flush unread SI entries for * each backend. dz - 27 Jan 1998 */ if (segP->numEntries == (MAXNUMMESSAGES * 70 / 100)) { TPRINTF(TRACE_VERBOSE, "SIIncNumEntries: table is 70%% full, signaling postmaster"); kill(getppid(), SIGUSR2); } if ((segP->numEntries + num) <= MAXNUMMESSAGES) { segP->numEntries = segP->numEntries + num; return true; } else { return false; /* table full */ }}/************************************************************************//* SIDecNumEntries(segP, num) decrements the current nuber of entries *//************************************************************************/static boolSIDecNumEntries(SISeg *segP, int num){ if ((segP->numEntries - num) >= 0) { segP->numEntries = segP->numEntries - num; return true; } else { return false; /* not enough entries in table */ }}/************************************************************************//* SISetStartFreeSpace(segP, offset) - sets the offset *//************************************************************************/static voidSISetStartFreeSpace(SISeg *segP, Offset offset){ segP->startFreeSpace = offset;}/************************************************************************//* SIGetStartFreeSpace(segP) - returns the offset *//************************************************************************/static OffsetSIGetStartFreeSpace(SISeg *segP){ return segP->startFreeSpace;}/************************************************************************//* SIGetFirstDataEntry(segP) returns first data entry *//************************************************************************/static SISegEntry *SIGetFirstDataEntry(SISeg *segP){ SISegEntry *eP; Offset startChain; startChain = SIGetStartEntryChain(segP);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -