*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.220 2001/06/14 19:59:24 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.221 2001/06/16 22:58:12 tgl Exp $
*
* NOTES
*
return "The Data Base System is starting up";
if (FatalError)
return "The Data Base System is in recovery mode";
- /* Can't start backend if max backend count is exceeded. */
- if (CountChildren() >= MaxBackends)
+ /*
+ * Don't start too many children.
+ *
+ * We allow more connections than we can have backends here because
+ * some might still be authenticating; they might fail auth, or some
+ * existing backend might exit before the auth cycle is completed.
+ * The exact MaxBackends limit is enforced when a new backend tries
+ * to join the shared-inval backend array.
+ */
+ if (CountChildren() >= 2 * MaxBackends)
return "Sorry, too many clients already";
return NULL;
GetRedoRecPtr();
}
}
- else
- {
- /* Why is this done here, and not by the backend itself? */
- if (!FatalError)
- ProcRemove(pid);
- }
return;
}
bp = (Backend *) DLE_VAL(curr);
if (bp->pid != pid)
{
-
/*
* This backend is still alive. Unless we did so already,
* tell it to commit hara-kiri.
}
else
{
-
/*
* Found entry for freshly-dead backend, so remove it.
- *
- * Don't call ProcRemove() here, since shmem may be corrupted! We
- * are going to reinitialize shmem and semaphores anyway once
- * all the children are dead, so no need for it.
*/
DLRemove(curr);
free(bp);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.32 2001/06/01 20:07:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.33 2001/06/16 22:58:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
void
InitBackendSharedInvalidationState(void)
{
+ int flag;
+
SpinAcquire(SInvalLock);
- if (!SIBackendInit(shmInvalBuffer))
- {
- SpinRelease(SInvalLock);
- elog(FATAL, "Backend cache invalidation initialization failed");
- }
+ flag = SIBackendInit(shmInvalBuffer);
SpinRelease(SInvalLock);
+ if (flag < 0) /* unexpected problem */
+ elog(FATAL, "Backend cache invalidation initialization failed");
+ if (flag == 0) /* expected problem: MaxBackends exceeded */
+ elog(FATAL, "Sorry, too many clients already");
}
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.38 2001/03/22 03:59:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.39 2001/06/16 22:58:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* SIBackendInit
* Initialize a new backend to operate on the sinval buffer
*
+ * Returns:
+ * >0 A-OK
+ * 0 Failed to find a free procState slot (ie, MaxBackends exceeded)
+ * <0 Some other failure (not currently used)
+ *
* NB: this routine, and all following ones, must be executed with the
* SInvalLock spinlock held, since there may be multiple backends trying
* to access the buffer.
}
else
{
-
- /*
- * elog() with spinlock held is probably not too cool, but
- * this condition should never happen anyway.
- */
- elog(NOTICE, "SIBackendInit: no free procState slot available");
+ /* out of procState slots */
MyBackendId = InvalidBackendId;
return 0;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.102 2001/05/25 15:45:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.103 2001/06/16 22:58:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
!isCommit, GetCurrentTransactionId());
}
-/*
- * ProcRemove -
- * called by the postmaster to clean up the global tables after a
- * backend exits. This also frees up the proc's wait semaphore.
- */
-bool
-ProcRemove(int pid)
-{
- SHMEM_OFFSET location;
- PROC *proc;
-
- location = ShmemPIDDestroy(pid);
- if (location == INVALID_OFFSET)
- return FALSE;
- proc = (PROC *) MAKE_PTR(location);
-
- SpinAcquire(ProcStructLock);
-
- ProcFreeSem(proc->sem.semId, proc->sem.semNum);
-
- /* Add PROC struct to freelist so space can be recycled in future */
- proc->links.next = ProcGlobal->freeProcs;
- ProcGlobal->freeProcs = MAKE_OFFSET(proc);
-
- SpinRelease(ProcStructLock);
-
- return TRUE;
-}
/*
* ProcKill() -- Destroy the per-proc data structure for
* this process. Release any of its held spin locks.
- *
- * This is done inside the backend process before it exits.
- * ProcRemove, above, will be done by the postmaster afterwards.
*/
static void
ProcKill(void)
{
+ SHMEM_OFFSET location;
+
Assert(MyProc);
/* Release any spinlocks I am holding */
LockReleaseAll(USER_LOCKMETHOD, MyProc, true, InvalidTransactionId);
#endif
+ /* Remove my PROC struct from the shmem hash table */
+ location = ShmemPIDDestroy(MyProcPid);
+ Assert(location != INVALID_OFFSET);
+ Assert(MyProc == (PROC *) MAKE_PTR(location));
+
+ SpinAcquire(ProcStructLock);
+
+ /* Free up my wait semaphore */
+ ProcFreeSem(MyProc->sem.semId, MyProc->sem.semNum);
+
+ /* Add PROC struct to freelist so space can be recycled in future */
+ MyProc->links.next = ProcGlobal->freeProcs;
+ ProcGlobal->freeProcs = MAKE_OFFSET(MyProc);
+
+ SpinRelease(ProcStructLock);
+
MyProc = NULL;
}
+
/*
* ProcQueue package: routines for putting processes to sleep
* and waking them up
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.86 2001/05/30 20:52:32 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.87 2001/06/16 22:58:16 tgl Exp $
*
*
*-------------------------------------------------------------------------
static void
InitCommunication(void)
{
-
/*
* initialize shared memory and semaphores appropriately.
*/
if (!IsUnderPostmaster) /* postmaster already did this */
{
-
/*
* we're running a postgres backend by itself with no front end or
* postmaster. Create private "shmem" and semaphores. Setting
/*
* Early initialization of a backend (either standalone or under postmaster).
* This happens even before InitPostgres.
+ *
+ * If you're wondering why this is separate from InitPostgres at all:
+ * the critical distinction is that this stuff has to happen before we can
+ * run XLOG-related initialization, which is done before InitPostgres --- in
+ * fact, for cases such as checkpoint creation processes, InitPostgres may
+ * never be done at all.
*/
void
BaseInit(void)
{
-
/*
* Attach to shared memory and semaphores, and initialize our
* input/output/debugging file descriptors.
smgrinit();
InitBufferPoolAccess();
InitLocalBuffer();
-
- EnablePortalManager(); /* memory for portal/transaction stuff */
}
{
bool bootstrap = IsBootstrapProcessingMode();
- SetDatabaseName(dbname);
-
/*
- * initialize the database id used for system caches and lock tables
+ * Set up the global variables holding database name, id, and path.
+ *
+ * We take a shortcut in the bootstrap case, otherwise we have to look up
+ * the db name in pg_database.
*/
+ SetDatabaseName(dbname);
+
if (bootstrap)
{
MyDatabaseId = TemplateDbOid;
SetDatabasePath(GetDatabasePath(MyDatabaseId));
- LockDisable(true);
}
else
{
* Code after this point assumes we are in the proper directory!
*/
+ /*
+ * Set up my per-backend PROC struct in shared memory. (We need to
+ * know MyDatabaseId before we can do this, since it's entered into
+ * the PROC struct.)
+ */
+ InitProcess();
+
+ /*
+ * Initialize my entry in the shared-invalidation manager's array of
+ * per-backend data. (Formerly this came before InitProcess, but now
+ * it must happen after, because it uses MyProc.) Once I have done
+ * this, I am visible to other backends!
+ *
+ * Sets up MyBackendId, a unique backend identifier.
+ */
+ MyBackendId = InvalidBackendId;
+
+ InitBackendSharedInvalidationState();
+
+ if (MyBackendId > MAXBACKENDS || MyBackendId <= 0)
+ elog(FATAL, "InitPostgres: bad backend id %d", MyBackendId);
+
/*
* Initialize the transaction system and the relation descriptor
* cache. Note we have to make certain the lock manager is off while
LockDisable(false);
- /*
- * Set up my per-backend PROC struct in shared memory.
- */
- InitProcess();
-
- /*
- * Initialize my entry in the shared-invalidation manager's array of
- * per-backend data. (Formerly this came before InitProcess, but now
- * it must happen after, because it uses MyProc.) Once I have done
- * this, I am visible to other backends!
- *
- * Sets up MyBackendId, a unique backend identifier.
- */
- MyBackendId = InvalidBackendId;
-
- InitBackendSharedInvalidationState();
-
- if (MyBackendId > MAXBACKENDS || MyBackendId <= 0)
- elog(FATAL, "cinit2: bad backend id %d", MyBackendId);
-
/*
* Initialize the access methods. Does not touch files (?) - thomas
* 1997-11-01
*/
InitCatalogCache();
+ /* Initialize portal manager */
+ EnablePortalManager();
+
/*
* Initialize the deferred trigger manager --- must happen before
* first transaction start.
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: proc.h,v 1.43 2001/05/25 15:45:34 momjian Exp $
+ * $Id: proc.h,v 1.44 2001/06/16 22:58:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void InitProcGlobal(int maxBackends);
extern void InitProcess(void);
extern void ProcReleaseLocks(bool isCommit);
-extern bool ProcRemove(int pid);
extern void ProcQueueInit(PROC_QUEUE *queue);
extern int ProcSleep(LOCKMETHODTABLE *lockMethodTable, LOCKMODE lockmode,