mirror of
https://github.com/postgres/postgres.git
synced 2025-06-06 00:02:36 -04: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:
parent
612b8434e4
commit
e77b630cf0
@ -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;
|
|||||||
* 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[])
|
|||||||
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[])
|
|||||||
* '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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
/* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
if (key == PrivateIPCKey)
|
if (key == PrivateIPCKey)
|
||||||
{
|
{
|
||||||
CreateSharedMemoryAndSemaphores(key);
|
CreateSharedMemoryAndSemaphores(key, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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()
|
|||||||
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()
|
|||||||
(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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
* 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);
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 */
|
|||||||
*/
|
*/
|
||||||
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,
|
||||||
|
674
src/configure
vendored
674
src/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -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 @@
|
|||||||
#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);
|
|||||||
/*
|
/*
|
||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
* 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_
|
|||||||
|
|
||||||
/* 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 @@
|
|||||||
*
|
*
|
||||||
* 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);
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
* 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;
|
|||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
* 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
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* 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 @@
|
|||||||
*
|
*
|
||||||
* 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 --------------
|
|||||||
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 -------
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* 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
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user