mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
Allow maximum number of backends to be set at configure time
(--with-maxbackends). Add a postmaster switch (-N backends) that allows the limit to be reduced at postmaster start time. (You can't increase it, sorry to say, because there are still some fixed-size arrays.) Grab the number of semaphores indicated by min(MAXBACKENDS, -N) at postmaster startup, so that this particular form of bogus configuration is exposed immediately rather than under heavy load.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.18 1999/02/13 23:18:11 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.19 1999/02/19 06:06:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -44,17 +44,19 @@ SystemPortAddressCreateIPCKey(SystemPortAddress address)
|
||||
|
||||
CreateSharedMemoryAndSemaphores
|
||||
is called exactly *ONCE* by the postmaster.
|
||||
It is *NEVER* called by the postgres backend
|
||||
It is *NEVER* called by the postgres backend,
|
||||
except in the case of a standalone backend.
|
||||
|
||||
0) destroy any existing semaphores for both buffer
|
||||
and lock managers.
|
||||
1) create the appropriate *SHARED* memory segments
|
||||
for the two resource managers.
|
||||
2) create shared semaphores as needed.
|
||||
|
||||
**************************************************/
|
||||
|
||||
void
|
||||
CreateSharedMemoryAndSemaphores(IPCKey key)
|
||||
CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
|
||||
{
|
||||
int size;
|
||||
|
||||
@@ -98,7 +100,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key)
|
||||
* do process table stuff
|
||||
* ----------------
|
||||
*/
|
||||
InitProcGlobal(key);
|
||||
InitProcGlobal(key, maxBackends);
|
||||
on_shmem_exit(ProcFreeAllSemaphores, NULL);
|
||||
|
||||
CreateSharedInvalidationState(key);
|
||||
@@ -120,7 +122,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key)
|
||||
*/
|
||||
if (key == PrivateIPCKey)
|
||||
{
|
||||
CreateSharedMemoryAndSemaphores(key);
|
||||
CreateSharedMemoryAndSemaphores(key, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.16 1999/02/13 23:18:16 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.17 1999/02/19 06:06:03 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -119,7 +119,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
|
||||
|
||||
stateP = NULL;
|
||||
|
||||
for (index = 0; index < MaxBackendId; index += 1)
|
||||
for (index = 0; index < MAXBACKENDS; index++)
|
||||
{
|
||||
if (segInOutP->procState[index].tag == InvalidBackendTag ||
|
||||
segInOutP->procState[index].tag == backendTag)
|
||||
@@ -141,7 +141,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
|
||||
|
||||
/* verify that all "procState" entries checked for matching tags */
|
||||
|
||||
for (index += 1; index < MaxBackendId; index += 1)
|
||||
for (index++; index < MAXBACKENDS; index++)
|
||||
{
|
||||
if (segInOutP->procState[index].tag == backendTag)
|
||||
{
|
||||
@@ -565,7 +565,7 @@ SIDecProcLimit(SISeg *segP, int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MaxBackendId; i++)
|
||||
for (i = 0; i < MAXBACKENDS; i++)
|
||||
{
|
||||
/* decrement only, if there is a limit > 0 */
|
||||
if (segP->procState[i].limit > 0)
|
||||
@@ -622,7 +622,7 @@ SISetProcStateInvalid(SISeg *segP)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MaxBackendId; i++)
|
||||
for (i = 0; i < MAXBACKENDS; i++)
|
||||
{
|
||||
if (segP->procState[i].limit == 0)
|
||||
{
|
||||
@@ -696,7 +696,7 @@ SIDelExpiredDataEntries(SISeg *segP)
|
||||
h;
|
||||
|
||||
min = 9999999;
|
||||
for (i = 0; i < MaxBackendId; i++)
|
||||
for (i = 0; i < MAXBACKENDS; i++)
|
||||
{
|
||||
h = SIGetProcStateLimit(segP, i);
|
||||
if (h >= 0)
|
||||
@@ -740,7 +740,7 @@ SISegInit(SISeg *segP)
|
||||
SISetEndEntryChain(segP, InvalidOffset);
|
||||
SISetNumEntries(segP, 0);
|
||||
SISetMaxNumEntries(segP, MAXNUMMESSAGES);
|
||||
for (i = 0; i < MaxBackendId; i++)
|
||||
for (i = 0; i < MAXBACKENDS; i++)
|
||||
{
|
||||
segP->procState[i].limit = -1; /* no backend active !! */
|
||||
segP->procState[i].resetState = false;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.41 1999/02/13 23:18:25 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.42 1999/02/19 06:06:06 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@@ -1492,8 +1492,8 @@ LockShmemSize()
|
||||
nXidBuckets = 1 << (int) my_log2((NLOCKS_PER_XACT - 1) / DEF_FFACTOR + 1);
|
||||
nXidSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1);
|
||||
|
||||
size += MAXALIGN(NBACKENDS * sizeof(PROC)); /* each MyProc */
|
||||
size += MAXALIGN(NBACKENDS * sizeof(LOCKMETHODCTL)); /* each
|
||||
size += MAXALIGN(MAXBACKENDS * sizeof(PROC)); /* each MyProc */
|
||||
size += MAXALIGN(MAXBACKENDS * sizeof(LOCKMETHODCTL)); /* each
|
||||
* lockMethodTable->ctl */
|
||||
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
|
||||
|
||||
@@ -1504,10 +1504,10 @@ LockShmemSize()
|
||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
||||
MAXALIGN(sizeof(LOCK))); /* contains hash key */
|
||||
|
||||
size += MAXALIGN(my_log2(NBACKENDS) * sizeof(void *));
|
||||
size += MAXALIGN(my_log2(MAXBACKENDS) * sizeof(void *));
|
||||
size += MAXALIGN(sizeof(HHDR));
|
||||
size += nXidSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
|
||||
size += NBACKENDS * /* XXX not multiple of BUCKET_ALLOC_INCR? */
|
||||
size += MAXBACKENDS * /* XXX not multiple of BUCKET_ALLOC_INCR? */
|
||||
(MAXALIGN(sizeof(BUCKET_INDEX)) +
|
||||
MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */
|
||||
|
||||
@@ -1552,7 +1552,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
|
||||
HTAB *xidTable;
|
||||
bool found;
|
||||
|
||||
static PROC *checked_procs[MaxBackendId];
|
||||
static PROC *checked_procs[MAXBACKENDS];
|
||||
static int nprocs;
|
||||
static bool MyNHolding;
|
||||
|
||||
@@ -1674,7 +1674,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
|
||||
if (j >= nprocs && lock != findlock)
|
||||
{
|
||||
checked_procs[nprocs++] = proc;
|
||||
Assert(nprocs <= MaxBackendId);
|
||||
Assert(nprocs <= MAXBACKENDS);
|
||||
|
||||
/*
|
||||
* For non-MyProc entries, we are looking only
|
||||
|
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.48 1999/02/13 23:18:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.49 1999/02/19 06:06:08 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -46,7 +46,7 @@
|
||||
* This is so that we can support more backends. (system-wide semaphore
|
||||
* sets run out pretty fast.) -ay 4/95
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.48 1999/02/13 23:18:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.49 1999/02/19 06:06:08 tgl Exp $
|
||||
*/
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
@@ -108,13 +108,24 @@ static void ProcFreeSem(IpcSemaphoreKey semKey, int semNum);
|
||||
/*
|
||||
* InitProcGlobal -
|
||||
* initializes the global process table. We put it here so that
|
||||
* the postmaster can do this initialization. (ProcFreeAllSem needs
|
||||
* the postmaster can do this initialization. (ProcFreeAllSemaphores needs
|
||||
* to read this table on exiting the postmaster. If we have the first
|
||||
* backend do this, starting up and killing the postmaster without
|
||||
* starting any backends will be a problem.)
|
||||
*
|
||||
* We also allocate all the per-process semaphores we will need to support
|
||||
* the requested number of backends. We used to allocate semaphores
|
||||
* only when backends were actually started up, but that is bad because
|
||||
* it lets Postgres fail under load --- a lot of Unix systems are
|
||||
* (mis)configured with small limits on the number of semaphores, and
|
||||
* running out when trying to start another backend is a common failure.
|
||||
* So, now we grab enough semaphores to support the desired max number
|
||||
* of backends immediately at initialization --- if the sysadmin has set
|
||||
* MaxBackends higher than his kernel will support, he'll find out sooner
|
||||
* rather than later.
|
||||
*/
|
||||
void
|
||||
InitProcGlobal(IPCKey key)
|
||||
InitProcGlobal(IPCKey key, int maxBackends)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
@@ -134,6 +145,24 @@ InitProcGlobal(IPCKey key)
|
||||
ProcGlobal->currKey = IPCGetProcessSemaphoreInitKey(key);
|
||||
for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++)
|
||||
ProcGlobal->freeSemMap[i] = 0;
|
||||
/* Pre-create the semaphores for the first maxBackends processes */
|
||||
for (i = 0;
|
||||
i < (maxBackends+PROC_NSEMS_PER_SET-1) / PROC_NSEMS_PER_SET;
|
||||
i++)
|
||||
{
|
||||
IPCKey semKey = ProcGlobal->currKey + i;
|
||||
int semId;
|
||||
int semstat;
|
||||
|
||||
semId = IpcSemaphoreCreate(semKey,
|
||||
PROC_NSEMS_PER_SET,
|
||||
IPCProtection,
|
||||
IpcSemaphoreDefaultStartValue,
|
||||
0,
|
||||
&semstat);
|
||||
/* mark this sema set allocated */
|
||||
ProcGlobal->freeSemMap[i] = (1 << PROC_NSEMS_PER_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +251,11 @@ InitProcess(IPCKey key)
|
||||
|
||||
ProcGetNewSemKeyAndNum(&semKey, &semNum);
|
||||
|
||||
/* Note: because of the pre-allocation done in InitProcGlobal,
|
||||
* this call should always attach to an existing semaphore.
|
||||
* It will (try to) create a new group of semaphores only if
|
||||
* the postmaster tries to start more backends than it said it would.
|
||||
*/
|
||||
semId = IpcSemaphoreCreate(semKey,
|
||||
PROC_NSEMS_PER_SET,
|
||||
IPCProtection,
|
||||
@@ -823,20 +857,20 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum)
|
||||
{
|
||||
int i;
|
||||
int32 *freeSemMap = ProcGlobal->freeSemMap;
|
||||
unsigned int fullmask;
|
||||
int32 fullmask = (1 << (PROC_NSEMS_PER_SET+1)) - 1;
|
||||
|
||||
/*
|
||||
* we hold ProcStructLock when entering this routine. We scan through
|
||||
* the bitmap to look for a free semaphore.
|
||||
*/
|
||||
fullmask = ~0 >> (32 - PROC_NSEMS_PER_SET);
|
||||
|
||||
for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++)
|
||||
{
|
||||
int mask = 1;
|
||||
int j;
|
||||
|
||||
if (freeSemMap[i] == fullmask)
|
||||
continue; /* none free for this set */
|
||||
continue; /* this set is fully allocated */
|
||||
|
||||
for (j = 0; j < PROC_NSEMS_PER_SET; j++)
|
||||
{
|
||||
@@ -845,8 +879,9 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum)
|
||||
|
||||
/*
|
||||
* a free semaphore found. Mark it as allocated.
|
||||
* Also set the bit indicating whole set is allocated.
|
||||
*/
|
||||
freeSemMap[i] |= mask;
|
||||
freeSemMap[i] |= mask + (1 << PROC_NSEMS_PER_SET);
|
||||
|
||||
*key = ProcGlobal->currKey + i;
|
||||
*semNum = j;
|
||||
@@ -862,8 +897,7 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum)
|
||||
|
||||
/*
|
||||
* ProcFreeSem -
|
||||
* free up our semaphore in the semaphore set. If we're the last one
|
||||
* in the set, also remove the semaphore set.
|
||||
* free up our semaphore in the semaphore set.
|
||||
*/
|
||||
static void
|
||||
ProcFreeSem(IpcSemaphoreKey semKey, int semNum)
|
||||
@@ -876,14 +910,19 @@ ProcFreeSem(IpcSemaphoreKey semKey, int semNum)
|
||||
mask = ~(1 << semNum);
|
||||
freeSemMap[i] &= mask;
|
||||
|
||||
if (freeSemMap[i] == 0)
|
||||
IpcSemaphoreKill(semKey);
|
||||
/* Formerly we'd release a semaphore set if it was now completely unused,
|
||||
* but now we keep the semaphores to ensure we won't run out when
|
||||
* starting new backends --- cf. InitProcGlobal. Note that the
|
||||
* PROC_NSEMS_PER_SET+1'st bit of the freeSemMap entry remains set to
|
||||
* indicate it is still allocated; ProcFreeAllSemaphores() needs that.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* ProcFreeAllSemaphores -
|
||||
* on exiting the postmaster, we free up all the semaphores allocated
|
||||
* to the lmgrs of the backends.
|
||||
* called at shmem_exit time, ie when exiting the postmaster or
|
||||
* destroying shared state for a failed set of backends.
|
||||
* Free up all the semaphores allocated to the lmgrs of the backends.
|
||||
*/
|
||||
void
|
||||
ProcFreeAllSemaphores()
|
||||
|
Reference in New Issue
Block a user