Commit e77b630c authored by Tom Lane's avatar Tom Lane

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.
parent 612b8434
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.101 1999/02/13 23:17:40 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.102 1999/02/19 06:06:00 tgl Exp $
* *
* NOTES * NOTES
* *
...@@ -162,8 +162,17 @@ static IpcMemoryKey ipc_key; ...@@ -162,8 +162,17 @@ static IpcMemoryKey ipc_key;
* adding to this. * adding to this.
*/ */
static int MaxBackends = MAXBACKENDS;
static int NextBackendId = MAXINT; /* XXX why? */ /*
* MaxBackends is the actual soft limit on the number of backends
* we will start. It defaults to the hard limit established at compilation
* time, but can be readjusted with postmaster's xxx switch.
* One reason to reduce MaxBackends is to allow startup under a kernel
* that won't let us get MAXBACKENDS semaphores!
*/
static int NextBackendTag = MAXINT; /* XXX why count down not up? */
static char *progname = (char *) NULL; static char *progname = (char *) NULL;
static char **real_argv; static char **real_argv;
static int real_argc; static int real_argc;
...@@ -388,7 +397,7 @@ PostmasterMain(int argc, char *argv[]) ...@@ -388,7 +397,7 @@ PostmasterMain(int argc, char *argv[])
DataDir = getenv("PGDATA"); /* default value */ DataDir = getenv("PGDATA"); /* default value */
opterr = 0; opterr = 0;
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:dim:Mno:p:Ss")) != EOF) while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:dim:MN:no:p:Ss")) != EOF)
{ {
switch (opt) switch (opt)
{ {
...@@ -463,6 +472,17 @@ PostmasterMain(int argc, char *argv[]) ...@@ -463,6 +472,17 @@ PostmasterMain(int argc, char *argv[])
* 'postmaster' * 'postmaster'
*/ */
break; break;
case 'N':
/*
* The max number of backends to start.
* Can't set to less than 1 or more than compiled-in limit.
*/
MaxBackends = atoi(optarg);
if (MaxBackends < 1)
MaxBackends = 1;
if (MaxBackends > MAXBACKENDS)
MaxBackends = MAXBACKENDS;
break;
case 'n': case 'n':
/* Don't reinit shared mem after abnormal exit */ /* Don't reinit shared mem after abnormal exit */
Reinit = false; Reinit = false;
...@@ -621,6 +641,8 @@ usage(const char *progname) ...@@ -621,6 +641,8 @@ usage(const char *progname)
fprintf(stderr, "\t-b backend\tuse a specific backend server executable\n"); fprintf(stderr, "\t-b backend\tuse a specific backend server executable\n");
fprintf(stderr, "\t-d [1|2|3]\tset debugging level\n"); fprintf(stderr, "\t-d [1|2|3]\tset debugging level\n");
fprintf(stderr, "\t-i \t\tlisten on TCP/IP sockets as well as Unix domain socket\n"); fprintf(stderr, "\t-i \t\tlisten on TCP/IP sockets as well as Unix domain socket\n");
fprintf(stderr, "\t-N nprocs\tset max number of backend servers (1..%d)\n",
MAXBACKENDS);
fprintf(stderr, "\t-n \t\tdon't reinitialize shared memory after abnormal exit\n"); fprintf(stderr, "\t-n \t\tdon't reinitialize shared memory after abnormal exit\n");
fprintf(stderr, "\t-o option\tpass 'option' to each backend servers\n"); fprintf(stderr, "\t-o option\tpass 'option' to each backend servers\n");
fprintf(stderr, "\t-p port\tspecify port for postmaster to listen on\n"); fprintf(stderr, "\t-p port\tspecify port for postmaster to listen on\n");
...@@ -765,7 +787,7 @@ ServerLoop(void) ...@@ -765,7 +787,7 @@ ServerLoop(void)
if (status == STATUS_OK && port->pktInfo.state == Idle) if (status == STATUS_OK && port->pktInfo.state == Idle)
{ {
/* Can't start backend if max backend count is exceeded. */ /* Can't start backend if max backend count is exceeded. */
if (CountChildren() >= MaxBackendId) if (CountChildren() >= MaxBackends)
PacketSendError(&port->pktInfo, PacketSendError(&port->pktInfo,
"Sorry, too many clients already"); "Sorry, too many clients already");
else else
...@@ -1009,7 +1031,7 @@ static void ...@@ -1009,7 +1031,7 @@ static void
reset_shared(short port) reset_shared(short port)
{ {
ipc_key = port * 1000 + shmem_seq * 100; ipc_key = port * 1000 + shmem_seq * 100;
CreateSharedMemoryAndSemaphores(ipc_key); CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends);
ActiveBackends = FALSE; ActiveBackends = FALSE;
shmem_seq += 1; shmem_seq += 1;
if (shmem_seq >= 10) if (shmem_seq >= 10)
...@@ -1272,7 +1294,7 @@ BackendStartup(Port *port) ...@@ -1272,7 +1294,7 @@ BackendStartup(Port *port)
*/ */
sprintf(envEntry[0], "POSTPORT=%d", PostPortName); sprintf(envEntry[0], "POSTPORT=%d", PostPortName);
putenv(envEntry[0]); putenv(envEntry[0]);
sprintf(envEntry[1], "POSTID=%d", NextBackendId); sprintf(envEntry[1], "POSTID=%d", NextBackendTag);
putenv(envEntry[1]); putenv(envEntry[1]);
sprintf(envEntry[2], "PG_USER=%s", port->user); sprintf(envEntry[2], "PG_USER=%s", port->user);
putenv(envEntry[2]); putenv(envEntry[2]);
...@@ -1348,9 +1370,11 @@ BackendStartup(Port *port) ...@@ -1348,9 +1370,11 @@ BackendStartup(Port *port)
progname, pid, port->user, port->database, progname, pid, port->user, port->database,
port->sock); port->sock);
/* adjust backend counter */ /* Generate a new backend tag for every backend we start */
/* XXX Don't know why this is done, but for now backend needs it */ /* XXX theoretically this could wrap around, if you have the patience
NextBackendId -= 1; * to start 2^31 backends ...
*/
NextBackendTag -= 1;
/* /*
* Everything's been successful, it's safe to add this backend to our * Everything's been successful, it's safe to add this backend to our
...@@ -1459,7 +1483,7 @@ DoBackend(Port *port) ...@@ -1459,7 +1483,7 @@ DoBackend(Port *port)
/* OK, let's unblock our signals, all together now... */ /* OK, let's unblock our signals, all together now... */
sigprocmask(SIG_SETMASK, &oldsigmask, 0); sigprocmask(SIG_SETMASK, &oldsigmask, 0);
/* Close the postmater sockets */ /* Close the postmaster sockets */
if (NetServer) if (NetServer)
StreamClose(ServerSock_INET); StreamClose(ServerSock_INET);
#ifndef __CYGWIN32__ #ifndef __CYGWIN32__
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -44,17 +44,19 @@ SystemPortAddressCreateIPCKey(SystemPortAddress address)
CreateSharedMemoryAndSemaphores CreateSharedMemoryAndSemaphores
is called exactly *ONCE* by the postmaster. 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 0) destroy any existing semaphores for both buffer
and lock managers. and lock managers.
1) create the appropriate *SHARED* memory segments 1) create the appropriate *SHARED* memory segments
for the two resource managers. for the two resource managers.
2) create shared semaphores as needed.
**************************************************/ **************************************************/
void void
CreateSharedMemoryAndSemaphores(IPCKey key) CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends)
{ {
int size; int size;
...@@ -98,7 +100,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key) ...@@ -98,7 +100,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key)
* do process table stuff * do process table stuff
* ---------------- * ----------------
*/ */
InitProcGlobal(key); InitProcGlobal(key, maxBackends);
on_shmem_exit(ProcFreeAllSemaphores, NULL); on_shmem_exit(ProcFreeAllSemaphores, NULL);
CreateSharedInvalidationState(key); CreateSharedInvalidationState(key);
...@@ -120,7 +122,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key) ...@@ -120,7 +122,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key)
*/ */
if (key == PrivateIPCKey) if (key == PrivateIPCKey)
{ {
CreateSharedMemoryAndSemaphores(key); CreateSharedMemoryAndSemaphores(key, 1);
return; return;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -119,7 +119,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
stateP = NULL; stateP = NULL;
for (index = 0; index < MaxBackendId; index += 1) for (index = 0; index < MAXBACKENDS; index++)
{ {
if (segInOutP->procState[index].tag == InvalidBackendTag || if (segInOutP->procState[index].tag == InvalidBackendTag ||
segInOutP->procState[index].tag == backendTag) segInOutP->procState[index].tag == backendTag)
...@@ -141,7 +141,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag) ...@@ -141,7 +141,7 @@ SIAssignBackendId(SISeg *segInOutP, BackendTag backendTag)
/* verify that all "procState" entries checked for matching tags */ /* 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) if (segInOutP->procState[index].tag == backendTag)
{ {
...@@ -565,7 +565,7 @@ SIDecProcLimit(SISeg *segP, int num) ...@@ -565,7 +565,7 @@ SIDecProcLimit(SISeg *segP, int num)
{ {
int i; int i;
for (i = 0; i < MaxBackendId; i++) for (i = 0; i < MAXBACKENDS; i++)
{ {
/* decrement only, if there is a limit > 0 */ /* decrement only, if there is a limit > 0 */
if (segP->procState[i].limit > 0) if (segP->procState[i].limit > 0)
...@@ -622,7 +622,7 @@ SISetProcStateInvalid(SISeg *segP) ...@@ -622,7 +622,7 @@ SISetProcStateInvalid(SISeg *segP)
{ {
int i; int i;
for (i = 0; i < MaxBackendId; i++) for (i = 0; i < MAXBACKENDS; i++)
{ {
if (segP->procState[i].limit == 0) if (segP->procState[i].limit == 0)
{ {
...@@ -696,7 +696,7 @@ SIDelExpiredDataEntries(SISeg *segP) ...@@ -696,7 +696,7 @@ SIDelExpiredDataEntries(SISeg *segP)
h; h;
min = 9999999; min = 9999999;
for (i = 0; i < MaxBackendId; i++) for (i = 0; i < MAXBACKENDS; i++)
{ {
h = SIGetProcStateLimit(segP, i); h = SIGetProcStateLimit(segP, i);
if (h >= 0) if (h >= 0)
...@@ -740,7 +740,7 @@ SISegInit(SISeg *segP) ...@@ -740,7 +740,7 @@ SISegInit(SISeg *segP)
SISetEndEntryChain(segP, InvalidOffset); SISetEndEntryChain(segP, InvalidOffset);
SISetNumEntries(segP, 0); SISetNumEntries(segP, 0);
SISetMaxNumEntries(segP, MAXNUMMESSAGES); 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].limit = -1; /* no backend active !! */
segP->procState[i].resetState = false; segP->procState[i].resetState = false;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Outside modules can create a lock table and acquire/release * Outside modules can create a lock table and acquire/release
...@@ -1492,8 +1492,8 @@ LockShmemSize() ...@@ -1492,8 +1492,8 @@ LockShmemSize()
nXidBuckets = 1 << (int) my_log2((NLOCKS_PER_XACT - 1) / DEF_FFACTOR + 1); nXidBuckets = 1 << (int) my_log2((NLOCKS_PER_XACT - 1) / DEF_FFACTOR + 1);
nXidSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1); nXidSegs = 1 << (int) my_log2((nLockBuckets - 1) / DEF_SEGSIZE + 1);
size += MAXALIGN(NBACKENDS * sizeof(PROC)); /* each MyProc */ size += MAXALIGN(MAXBACKENDS * sizeof(PROC)); /* each MyProc */
size += MAXALIGN(NBACKENDS * sizeof(LOCKMETHODCTL)); /* each size += MAXALIGN(MAXBACKENDS * sizeof(LOCKMETHODCTL)); /* each
* lockMethodTable->ctl */ * lockMethodTable->ctl */
size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */
...@@ -1504,10 +1504,10 @@ LockShmemSize() ...@@ -1504,10 +1504,10 @@ LockShmemSize()
(MAXALIGN(sizeof(BUCKET_INDEX)) + (MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(sizeof(LOCK))); /* contains hash key */ 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 += MAXALIGN(sizeof(HHDR));
size += nXidSegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT)); 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(BUCKET_INDEX)) +
MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */ MAXALIGN(sizeof(XIDLookupEnt))); /* contains hash key */
...@@ -1552,7 +1552,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check) ...@@ -1552,7 +1552,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
HTAB *xidTable; HTAB *xidTable;
bool found; bool found;
static PROC *checked_procs[MaxBackendId]; static PROC *checked_procs[MAXBACKENDS];
static int nprocs; static int nprocs;
static bool MyNHolding; static bool MyNHolding;
...@@ -1674,7 +1674,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check) ...@@ -1674,7 +1674,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
if (j >= nprocs && lock != findlock) if (j >= nprocs && lock != findlock)
{ {
checked_procs[nprocs++] = proc; checked_procs[nprocs++] = proc;
Assert(nprocs <= MaxBackendId); Assert(nprocs <= MAXBACKENDS);
/* /*
* For non-MyProc entries, we are looking only * For non-MyProc entries, we are looking only
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -46,7 +46,7 @@
* This is so that we can support more backends. (system-wide semaphore * This is so that we can support more backends. (system-wide semaphore
* sets run out pretty fast.) -ay 4/95 * 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 <sys/time.h>
#include <unistd.h> #include <unistd.h>
...@@ -108,13 +108,24 @@ static void ProcFreeSem(IpcSemaphoreKey semKey, int semNum); ...@@ -108,13 +108,24 @@ static void ProcFreeSem(IpcSemaphoreKey semKey, int semNum);
/* /*
* InitProcGlobal - * InitProcGlobal -
* initializes the global process table. We put it here so that * 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 * to read this table on exiting the postmaster. If we have the first
* backend do this, starting up and killing the postmaster without * backend do this, starting up and killing the postmaster without
* starting any backends will be a problem.) * 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 void
InitProcGlobal(IPCKey key) InitProcGlobal(IPCKey key, int maxBackends)
{ {
bool found = false; bool found = false;
...@@ -134,6 +145,24 @@ InitProcGlobal(IPCKey key) ...@@ -134,6 +145,24 @@ InitProcGlobal(IPCKey key)
ProcGlobal->currKey = IPCGetProcessSemaphoreInitKey(key); ProcGlobal->currKey = IPCGetProcessSemaphoreInitKey(key);
for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++) for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++)
ProcGlobal->freeSemMap[i] = 0; 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) ...@@ -222,6 +251,11 @@ InitProcess(IPCKey key)
ProcGetNewSemKeyAndNum(&semKey, &semNum); 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, semId = IpcSemaphoreCreate(semKey,
PROC_NSEMS_PER_SET, PROC_NSEMS_PER_SET,
IPCProtection, IPCProtection,
...@@ -823,20 +857,20 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum) ...@@ -823,20 +857,20 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum)
{ {
int i; int i;
int32 *freeSemMap = ProcGlobal->freeSemMap; 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 * we hold ProcStructLock when entering this routine. We scan through
* the bitmap to look for a free semaphore. * 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++) for (i = 0; i < MAX_PROC_SEMS / PROC_NSEMS_PER_SET; i++)
{ {
int mask = 1; int mask = 1;
int j; int j;
if (freeSemMap[i] == fullmask) 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++) for (j = 0; j < PROC_NSEMS_PER_SET; j++)
{ {
...@@ -845,8 +879,9 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum) ...@@ -845,8 +879,9 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum)
/* /*
* a free semaphore found. Mark it as allocated. * 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; *key = ProcGlobal->currKey + i;
*semNum = j; *semNum = j;
...@@ -862,8 +897,7 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum) ...@@ -862,8 +897,7 @@ ProcGetNewSemKeyAndNum(IPCKey *key, int *semNum)
/* /*
* ProcFreeSem - * ProcFreeSem -
* free up our semaphore in the semaphore set. If we're the last one * free up our semaphore in the semaphore set.
* in the set, also remove the semaphore set.
*/ */
static void static void
ProcFreeSem(IpcSemaphoreKey semKey, int semNum) ProcFreeSem(IpcSemaphoreKey semKey, int semNum)
...@@ -876,14 +910,19 @@ ProcFreeSem(IpcSemaphoreKey semKey, int semNum) ...@@ -876,14 +910,19 @@ ProcFreeSem(IpcSemaphoreKey semKey, int semNum)
mask = ~(1 << semNum); mask = ~(1 << semNum);
freeSemMap[i] &= mask; freeSemMap[i] &= mask;
if (freeSemMap[i] == 0) /* Formerly we'd release a semaphore set if it was now completely unused,
IpcSemaphoreKill(semKey); * 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 - * ProcFreeAllSemaphores -
* on exiting the postmaster, we free up all the semaphores allocated * called at shmem_exit time, ie when exiting the postmaster or
* to the lmgrs of the backends. * destroying shared state for a failed set of backends.
* Free up all the semaphores allocated to the lmgrs of the backends.
*/ */
void void
ProcFreeAllSemaphores() ProcFreeAllSemaphores()
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.37 1999/02/13 23:20:02 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.38 1999/02/19 06:06:10 tgl Exp $
* *
* NOTES * NOTES
* InitPostgres() is the function called from PostgresMain * InitPostgres() is the function called from PostgresMain
...@@ -571,7 +571,7 @@ InitPostgres(char *name) /* database name */ ...@@ -571,7 +571,7 @@ InitPostgres(char *name) /* database name */
*/ */
InitProcess(PostgresIpcKey); InitProcess(PostgresIpcKey);
if (MyBackendId > MaxBackendId || MyBackendId <= 0) if (MyBackendId > MAXBACKENDS || MyBackendId <= 0)
{ {
elog(FATAL, "cinit2: bad backend id %d (%d)", elog(FATAL, "cinit2: bad backend id %d (%d)",
MyBackendTag, MyBackendTag,
......
This diff is collapsed.
...@@ -255,7 +255,16 @@ AC_ARG_WITH( ...@@ -255,7 +255,16 @@ AC_ARG_WITH(
AC_DEFINE_UNQUOTED(DEF_PGPORT, "5432") AC_MSG_RESULT(5432) AC_DEFINE_UNQUOTED(DEF_PGPORT, "5432") AC_MSG_RESULT(5432)
) )
dnl We exclude tcl support unless we override it with --with-tcl dnl MAXBACKENDS can be set by --with-maxbackends. Default value is 64.
AC_MSG_CHECKING(setting MAXBACKENDS)
AC_ARG_WITH(
maxbackends,
[ --with-maxbackends=<n> set maximum number of server processes ],
AC_DEFINE_UNQUOTED(MAXBACKENDS, ${withval}) AC_MSG_RESULT($with_maxbackends),
AC_DEFINE_UNQUOTED(MAXBACKENDS, 64) AC_MSG_RESULT(64)
)
dnl We exclude tcl support unless user says --with-tcl
AC_MSG_CHECKING(setting USE_TCL) AC_MSG_CHECKING(setting USE_TCL)
AC_ARG_WITH( AC_ARG_WITH(
tcl, tcl,
......
...@@ -8,6 +8,16 @@ ...@@ -8,6 +8,16 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
/*
* Maximum number of backend server processes per postmaster.
* (Actual value is set by configure script.)
*/
#undef MAXBACKENDS
/*
* Size of a disk block --- currently, this limits the size of a tuple.
* You can set it bigger if you need bigger tuples.
*/
#define BLCKSZ 8192 #define BLCKSZ 8192
/* /*
...@@ -298,7 +308,7 @@ extern void srandom(unsigned int seed); ...@@ -298,7 +308,7 @@ extern void srandom(unsigned int seed);
/* /*
* DEF_PGPORT is the TCP port number on which the Postmaster listens by * DEF_PGPORT is the TCP port number on which the Postmaster listens by
* default. This can be overriden by command options, environment variables, * default. This can be overriden by command options, environment variables,
* and the postconfig hook. (set by build script) * and the postconfig hook. (set by configure script)
*/ */
#undef DEF_PGPORT #undef DEF_PGPORT
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: ipc.h,v 1.32 1999/02/13 23:22:05 momjian Exp $ * $Id: ipc.h,v 1.33 1999/02/19 06:06:33 tgl Exp $
* *
* NOTES * NOTES
* This file is very architecture-specific. This stuff should actually * This file is very architecture-specific. This stuff should actually
...@@ -201,7 +201,7 @@ typedef enum _LockId_ ...@@ -201,7 +201,7 @@ typedef enum _LockId_
/* ipci.c */ /* ipci.c */
extern IPCKey SystemPortAddressCreateIPCKey(SystemPortAddress address); extern IPCKey SystemPortAddressCreateIPCKey(SystemPortAddress address);
extern void CreateSharedMemoryAndSemaphores(IPCKey key); extern void CreateSharedMemoryAndSemaphores(IPCKey key, int maxBackends);
extern void AttachSharedMemoryAndSemaphores(IPCKey key); extern void AttachSharedMemoryAndSemaphores(IPCKey key);
#endif /* IPC_H */ #endif /* IPC_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: lmgr.h,v 1.17 1999/02/13 23:22:07 momjian Exp $ * $Id: lmgr.h,v 1.18 1999/02/19 06:06:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -61,6 +61,6 @@ extern void XactLockTableDelete(TransactionId xid); ...@@ -61,6 +61,6 @@ extern void XactLockTableDelete(TransactionId xid);
extern void XactLockTableWait(TransactionId xid); extern void XactLockTableWait(TransactionId xid);
/* proc.c */ /* proc.c */
extern void InitProcGlobal(IPCKey key); extern void InitProcGlobal(IPCKey key, int maxBackends);
#endif /* LMGR_H */ #endif /* LMGR_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: lock.h,v 1.21 1999/02/13 23:22:07 momjian Exp $ * $Id: lock.h,v 1.22 1999/02/19 06:06:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -29,14 +29,13 @@ typedef int MASK; ...@@ -29,14 +29,13 @@ typedef int MASK;
* The following defines are used to estimate how much shared * The following defines are used to estimate how much shared
* memory the lock manager is going to require. * memory the lock manager is going to require.
* *
* NBACKENDS - The number of concurrently running backends * MAXBACKENDS - The max number of concurrently running backends (config.h)
* NLOCKS_PER_XACT - The number of unique locks acquired in a transaction * NLOCKS_PER_XACT - The number of unique locks acquired in a transaction
* NLOCKENTS - The maximum number of lock entries in the lock table. * NLOCKENTS - The maximum number of lock entries in the lock table.
* ---------------------- * ----------------------
*/ */
#define NBACKENDS MaxBackendId
#define NLOCKS_PER_XACT 40 #define NLOCKS_PER_XACT 40
#define NLOCKENTS NLOCKS_PER_XACT*NBACKENDS #define NLOCKENTS (NLOCKS_PER_XACT*MAXBACKENDS)
typedef int LOCKMODE; typedef int LOCKMODE;
typedef int LOCKMETHOD; typedef int LOCKMETHOD;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: proc.h,v 1.18 1999/02/15 03:22:37 momjian Exp $ * $Id: proc.h,v 1.19 1999/02/19 06:06:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -58,19 +58,27 @@ typedef struct proc ...@@ -58,19 +58,27 @@ typedef struct proc
/* /*
* PROC_NSEMS_PER_SET is the number of semaphores in each sys-V semaphore set
* we allocate. It must be *less than* 32 (or however many bits in an int
* on your machine), or our free-semaphores bitmap won't work. You also must
* not set it higher than your kernel's SEMMSL (max semaphores per set)
* parameter, which is often around 25.
* MAX_PROC_SEMS is the maximum number of per-process semaphores (those used * MAX_PROC_SEMS is the maximum number of per-process semaphores (those used
* by the lock mgr) we can keep track of. PROC_NSEMS_PER_SET is the number * by the lock mgr) we can keep track of. It must be a multiple of
* of semaphores in each (sys-V) semaphore set allocated. (Be careful not * PROC_NSEMS_PER_SET.
* to set it to greater 32. Otherwise, the bitmap will overflow.)
*/ */
#define MAX_PROC_SEMS 128
#define PROC_NSEMS_PER_SET 16 #define PROC_NSEMS_PER_SET 16
#define MAX_PROC_SEMS (((MAXBACKENDS-1)/PROC_NSEMS_PER_SET+1)*PROC_NSEMS_PER_SET)
typedef struct procglobal typedef struct procglobal
{ {
SHMEM_OFFSET freeProcs; SHMEM_OFFSET freeProcs;
IPCKey currKey; IPCKey currKey;
int32 freeSemMap[MAX_PROC_SEMS / PROC_NSEMS_PER_SET]; int32 freeSemMap[MAX_PROC_SEMS / PROC_NSEMS_PER_SET];
/* In each freeSemMap entry, the PROC_NSEMS_PER_SET lsbs flag whether
* individual semaphores are in use, and the next higher bit is set to
* show that the entire set is allocated.
*/
} PROC_HDR; } PROC_HDR;
extern PROC *MyProc; extern PROC *MyProc;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: sinvaladt.h,v 1.11 1999/02/13 23:22:10 momjian Exp $ * $Id: sinvaladt.h,v 1.12 1999/02/19 06:06:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,7 +31,7 @@ A------------- Header info -------------- ...@@ -31,7 +31,7 @@ A------------- Header info --------------
endEntryChain (offset relative to B) endEntryChain (offset relative to B)
numEntries numEntries
maxNumEntries maxNumEntries
procState[MaxBackendId] --> limit procState[MAXBACKENDS] --> limit
resetState (bool) resetState (bool)
a tag (POSTID) a tag (POSTID)
B------------- Start entry section ------- B------------- Start entry section -------
...@@ -44,7 +44,6 @@ C----------------End shared segment ------- ...@@ -44,7 +44,6 @@ C----------------End shared segment -------
*/ */
/* Parameters (configurable) *******************************************/ /* Parameters (configurable) *******************************************/
#define MaxBackendId 64 /* maximum number of backends */
#define MAXNUMMESSAGES 4000 /* maximum number of messages in seg */ #define MAXNUMMESSAGES 4000 /* maximum number of messages in seg */
...@@ -71,7 +70,7 @@ typedef struct SISeg ...@@ -71,7 +70,7 @@ typedef struct SISeg
Offset endEntryChain; /* (offset relative to B) */ Offset endEntryChain; /* (offset relative to B) */
int numEntries; int numEntries;
int maxNumEntries; int maxNumEntries;
ProcState procState[MaxBackendId]; /* reflects the ProcState procState[MAXBACKENDS]; /* reflects the
* invalidation state */ * invalidation state */
/* here starts the entry section, controlled by offsets */ /* here starts the entry section, controlled by offsets */
} SISeg; } SISeg;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment