* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/access/transam/clog.c,v 1.13 2003/05/02 21:52:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/clog.c,v 1.14 2003/05/02 21:59:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
* The value is automatically inherited by backends via fork, and
* doesn't need to be in shared memory.
*/
-static LWLockId *ClogBufferLocks; /* Per-buffer I/O locks */
+static LWLockId ClogBufferLocks[NUM_CLOG_BUFFERS]; /* Per-buffer I/O locks */
/*
* ClogDir is set during CLOGShmemInit and does not change thereafter.
/*
* Initialization of shared memory for CLOG
*/
+
int
CLOGShmemSize(void)
{
- return MAXALIGN(sizeof(ClogCtlData) + CLOG_BLCKSZ * NUM_CLOG_BUFFERS)
-#ifdef EXEC_BACKEND
- + MAXALIGN(NUM_CLOG_BUFFERS * sizeof(LWLockId))
-#endif
- ;
+ return MAXALIGN(sizeof(ClogCtlData) + CLOG_BLCKSZ * NUM_CLOG_BUFFERS);
}
-
void
CLOGShmemInit(void)
{
bool found;
+ char *bufptr;
int slotno;
- /* Handle ClogCtl */
-
/* this must agree with space requested by CLOGShmemSize() */
- ClogCtl = (ClogCtlData *) ShmemInitStruct("CLOG Ctl",
- MAXALIGN(sizeof(ClogCtlData) +
- CLOG_BLCKSZ * NUM_CLOG_BUFFERS), &found);
-
- if (!IsUnderPostmaster)
- /* Initialize ClogCtl shared memory area */
- {
- char *bufptr;
+ ClogCtl = (ClogCtlData *)
+ ShmemInitStruct("CLOG Ctl",
+ MAXALIGN(sizeof(ClogCtlData) +
+ CLOG_BLCKSZ * NUM_CLOG_BUFFERS),
+ &found);
+ Assert(!found);
- Assert(!found);
+ memset(ClogCtl, 0, sizeof(ClogCtlData));
- memset(ClogCtl, 0, sizeof(ClogCtlData));
-
- bufptr = (char *)ClogCtl + sizeof(ClogCtlData);
-
- for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++)
- {
- ClogCtl->page_buffer[slotno] = bufptr;
- ClogCtl->page_status[slotno] = CLOG_PAGE_EMPTY;
- bufptr += CLOG_BLCKSZ;
- }
+ bufptr = ((char *) ClogCtl) + sizeof(ClogCtlData);
- /* ClogCtl->latest_page_number will be set later */
+ for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++)
+ {
+ ClogCtl->page_buffer[slotno] = bufptr;
+ ClogCtl->page_status[slotno] = CLOG_PAGE_EMPTY;
+ ClogBufferLocks[slotno] = LWLockAssign();
+ bufptr += CLOG_BLCKSZ;
}
- else
- Assert(found);
-
- /* Handle ClogBufferLocks */
-
-#ifdef EXEC_BACKEND
- ClogBufferLocks = (LWLockId *) ShmemInitStruct("CLOG Buffer Locks",
- NUM_CLOG_BUFFERS * sizeof(LWLockId), &found);
- Assert((!found && !IsUnderPostmaster) || (found && IsUnderPostmaster));
-#else
- ClogBufferLocks = malloc(NUM_CLOG_BUFFERS * sizeof(LWLockId));
- Assert(ClogBufferLocks);
-#endif
-
- if (!IsUnderPostmaster)
- for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++)
- ClogBufferLocks[slotno] = LWLockAssign();
+
+ /* ClogCtl->latest_page_number will be set later */
/* Init CLOG directory path */
snprintf(ClogDir, MAXPGPATH, "%s/pg_clog", DataDir);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.149 2003/05/02 21:52:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.150 2003/05/02 21:59:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
Assert(dbName);
- if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */)
- {
- AttachSharedMemoryAndSemaphores();
- }
-
if (!IsUnderPostmaster)
{
if (!potential_DataDir)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.316 2003/05/02 21:52:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.317 2003/05/02 21:59:31 momjian Exp $
*
* NOTES
*
static int ServerSock_UNIX = INVALID_SOCK; /* stream socket server */
#endif
-/* Used to reduce macros tests */
-#ifdef EXEC_BACKEND
-const bool ExecBackend = true;
-#else
-const bool ExecBackend = false;
-#endif
-
/*
* Set by the -o option
*/
static void CleanupProc(int pid, int exitstatus);
static void LogChildExit(int lev, const char *procname,
int pid, int exitstatus);
-static int DoBackend(Port *port);
+static int BackendFinalize(Port *port);
void ExitPostmaster(int status);
static void usage(const char *);
static int ServerLoop(void);
static int BackendStartup(Port *port);
+static void BackendFork(Port *port, Backend *bn);
static int ProcessStartupPacket(Port *port, bool SSLdone);
static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask, fd_set *wmask);
SetDataDir(potential_DataDir);
ProcessConfigFile(PGC_POSTMASTER);
+#ifdef EXEC_BACKEND
+ write_nondefault_variables(PGC_POSTMASTER);
+#endif
/*
* Check for invalid combinations of GUC settings.
* Now fetch parameters out of startup packet and save them into the
* Port structure. All data structures attached to the Port struct
* must be allocated in TopMemoryContext so that they won't disappear
- * when we pass them to PostgresMain (see DoBackend). We need not worry
+ * when we pass them to PostgresMain (see BackendFinalize). We need not worry
* about leaking this storage on failure, since we aren't in the postmaster
* process anymore.
*/
elog(DEBUG1, "processCancelRequest: CheckPointPID in cancel request for process %d", backendPID);
return;
}
- else if (ExecBackend)
- {
- AttachSharedMemoryAndSemaphores();
- }
-
+
/* See if we have a matching backend */
for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
elog(LOG, "Received SIGHUP, reloading configuration files");
SignalChildren(SIGHUP);
ProcessConfigFile(PGC_SIGHUP);
+#ifdef EXEC_BACKEND
+ write_nondefault_variables(PGC_SIGHUP);
+#endif
load_hba();
load_ident();
}
pid = fork();
if (pid == 0) /* child */
- {
- int status;
-
-#ifdef LINUX_PROFILE
- setitimer(ITIMER_PROF, &prof_itimer, NULL);
-#endif
-
-#ifdef __BEOS__
- /* Specific beos backend startup actions */
- beos_backend_startup();
-#endif
- free(bn);
-
- status = DoBackend(port);
- if (status != 0)
- {
- elog(LOG, "connection startup failed");
- proc_exit(status);
- }
- else
- proc_exit(0);
- }
+ BackendFork(port, bn); /* never returns */
/* in parent, error */
if (pid < 0)
}
+static void
+BackendFork(Port *port, Backend *bn)
+{
+ int status;
+
+#ifdef LINUX_PROFILE
+ setitimer(ITIMER_PROF, &prof_itimer, NULL);
+#endif
+
+#ifdef __BEOS__
+ /* Specific beos backend startup actions */
+ beos_backend_startup();
+#endif
+ free(bn);
+
+ status = BackendFinalize(port);
+ if (status != 0)
+ {
+ elog(LOG, "connection startup failed");
+ proc_exit(status);
+ }
+ else
+ proc_exit(0);
+}
+
/*
* Try to report backend fork() failure to client before we close the
* connection. Since we do not care to risk blocking the postmaster on
}
/*
- * DoBackend -- perform authentication, and if successful, set up the
+ * BackendFinalize -- perform authentication, and if successful, set up the
* backend's argument list and invoke backend main().
*
* This used to perform an execv() but we no longer exec the backend;
* If PostgresMain() fails, return status.
*/
static int
-DoBackend(Port *port)
+BackendFinalize(Port *port)
{
char *remote_host;
char **av;
/* Reset MyProcPid to new backend's pid */
MyProcPid = getpid();
+#ifdef EXEC_BACKEND
+ read_nondefault_variables();
+#endif
+
/*
* Initialize libpq and enable reporting of elog errors to the client.
* Must do this now because authentication uses libpq to send
unsigned short remote_port;
char *host_addr;
#ifdef HAVE_IPV6
- char ip_hostinfo[INET6_ADDRSTRLEN];
+ char ip_hostinfo[INET6_ADDRSTRLEN];
#else
char ip_hostinfo[INET_ADDRSTRLEN];
#endif
}
else
{
- /* not AF_INET */
+ /* not AF_INET */
remote_host = "[local]";
if (Log_connections)
* indefinitely. PreAuthDelay doesn't count against the time limit.
*/
if (!enable_sig_alarm(AuthenticationTimeout * 1000, false))
- elog(FATAL, "DoBackend: Unable to set timer for auth timeout");
+ elog(FATAL, "BackendFinalize: Unable to set timer for auth timeout");
/*
* Receive the startup packet (which might turn out to be a cancel
* SIGTERM/SIGQUIT again until backend startup is complete.
*/
if (!disable_sig_alarm(false))
- elog(FATAL, "DoBackend: Unable to disable timer for auth timeout");
+ elog(FATAL, "BackendFinalize: Unable to disable timer for auth timeout");
PG_SETMASK(&BlockSig);
if (Log_connections)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.50 2003/05/02 21:52:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.51 2003/05/02 21:59:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
*/
PMSignalInit();
}
-
-
-/*
- * AttachSharedMemoryAndSemaphores
- * Attaches to the existing shared resources when exec()'d off
- * by the postmaster.
- */
-void
-AttachSharedMemoryAndSemaphores(void)
-{
- CLOGShmemInit();
-}
-
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.328 2003/05/02 21:52:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.329 2003/05/02 21:59:31 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
break;
}
-
/*
* -d is not the same as setting
* log_min_messages because it enables other
* restart... */
}
BaseInit();
-#ifdef EXECBACKEND
- AttachSharedMemoryAndSemaphores();
-#endif
}
else
{
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.328 $ $Date: 2003/05/02 21:52:42 $\n");
+ puts("$Revision: 1.329 $ $Date: 2003/05/02 21:59:31 $\n");
}
/*
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.119 2003/04/25 19:45:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.120 2003/05/02 21:59:31 momjian Exp $
*
*--------------------------------------------------------------------
*/
#define PG_KRB_SRVTAB ""
#endif
+#ifdef EXEC_BACKEND
+#define CONFIG_EXEC_PARAMS "global/config_exec_params"
+#endif
/* XXX these should appear in other modules' header files */
extern bool Log_connections;
}
+#ifdef EXEC_BACKEND
+/*
+ * This routine dumps out all non-default GUC options into a binary
+ * file that is read by all exec'ed backends. The format is:
+ *
+ * variable name, string, null terminated
+ * variable value, string, null terminated
+ * variable source, integer
+ */
+void
+write_nondefault_variables(GucContext context)
+{
+ int i;
+ char *new_filename, *filename;
+ int elevel;
+ FILE *fp;
+
+ Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
+ Assert(DataDir);
+ elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
+
+ /*
+ * Open file
+ */
+ new_filename = malloc(strlen(DataDir) + strlen(CONFIG_EXEC_PARAMS) +
+ strlen(".new") + 2);
+ filename = malloc(strlen(DataDir) + strlen(CONFIG_EXEC_PARAMS) + 2);
+ if (new_filename == NULL || filename == NULL)
+ {
+ elog(elevel, "out of memory");
+ return;
+ }
+ sprintf(new_filename, "%s/" CONFIG_EXEC_PARAMS ".new", DataDir);
+ sprintf(filename, "%s/" CONFIG_EXEC_PARAMS, DataDir);
+
+ fp = AllocateFile(new_filename, "w");
+ if (!fp)
+ {
+ free(new_filename);
+ free(filename);
+ elog(elevel, "could not write exec config params file `"
+ CONFIG_EXEC_PARAMS "': %s", strerror(errno));
+ return;
+ }
+
+ for (i = 0; i < num_guc_variables; i++)
+ {
+ struct config_generic *gconf = guc_variables[i];
+
+ if (gconf->source != PGC_S_DEFAULT)
+ {
+ fprintf(fp, "%s", gconf->name);
+ fputc(0, fp);
+
+ switch (gconf->vartype)
+ {
+ case PGC_BOOL:
+ {
+ struct config_bool *conf = (struct config_bool *) gconf;
+
+ if (*conf->variable == 0)
+ fprintf(fp, "false");
+ else
+ fprintf(fp, "true");
+ }
+ break;
+
+ case PGC_INT:
+ {
+ struct config_int *conf = (struct config_int *) gconf;
+
+ fprintf(fp, "%d", *conf->variable);
+ }
+ break;
+
+ case PGC_REAL:
+ {
+ struct config_real *conf = (struct config_real *) gconf;
+
+ /* Could lose precision here? */
+ fprintf(fp, "%f", *conf->variable);
+ }
+ break;
+
+ case PGC_STRING:
+ {
+ struct config_string *conf = (struct config_string *) gconf;
+
+ fprintf(fp, "%s", *conf->variable);
+ }
+ break;
+ }
+
+ fputc(0, fp);
+
+ fwrite(&gconf->source, sizeof(gconf->source), 1, fp);
+ }
+ }
+
+ FreeFile(fp);
+ /* Put new file in place, this could delay on Win32 */
+ rename(new_filename, filename);
+ free(new_filename);
+ free(filename);
+ return;
+}
+
+
+/*
+ * Read string, including null byte from file
+ *
+ * Return NULL on EOF and nothing read
+ */
+static char *
+read_string_with_null(FILE *fp)
+{
+ int i = 0, ch, maxlen = 256;
+ char *str = NULL;
+
+ do
+ {
+ if ((ch = fgetc(fp)) == EOF)
+ {
+ if (i == 0)
+ return NULL;
+ else
+ elog(FATAL, "Invalid format of exec config params file");
+ }
+ if (i == 0)
+ str = malloc(maxlen);
+ else if (i == maxlen)
+ str = realloc(str, maxlen *= 2);
+ str[i++] = ch;
+ } while (ch != 0);
+
+ return str;
+}
+
+
+/*
+ * This routine loads a previous postmaster dump of its non-default
+ * settings.
+ */
+void
+read_nondefault_variables(void)
+{
+ char *filename;
+ FILE *fp;
+ char *varname, *varvalue;
+ int varsource;
+
+ Assert(DataDir);
+
+ /*
+ * Open file
+ */
+ filename = malloc(strlen(DataDir) + strlen(CONFIG_EXEC_PARAMS) + 2);
+ if (filename == NULL)
+ {
+ elog(ERROR, "out of memory");
+ return;
+ }
+ sprintf(filename, "%s/" CONFIG_EXEC_PARAMS, DataDir);
+
+ fp = AllocateFile(filename, "r");
+ if (!fp)
+ {
+ free(filename);
+ /* File not found is fine */
+ if (errno != ENOENT)
+ elog(FATAL, "could not read exec config params file `"
+ CONFIG_EXEC_PARAMS "': %s", strerror(errno));
+ return;
+ }
+
+ while (1)
+ {
+ if ((varname = read_string_with_null(fp)) == NULL)
+ break;
+
+ if ((varvalue = read_string_with_null(fp)) == NULL)
+ elog(FATAL, "Invalid format of exec config params file");
+ if (fread(&varsource, sizeof(varsource), 1, fp) == 0)
+ elog(FATAL, "Invalid format of exec config params file");
+
+ (void) set_config_option(varname, varvalue, PGC_POSTMASTER,
+ varsource, false, true);
+ free(varname);
+ free(varvalue);
+ }
+
+ FreeFile(fp);
+ free(filename);
+ return;
+}
+#endif
+
+
/*
* A little "long argument" simulation, although not quite GNU
* compliant. Takes a string of the form "some-option=some value" and
#include "guc-file.c"
+
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: miscadmin.h,v 1.119 2003/05/02 21:52:42 momjian Exp $
+ * $Id: miscadmin.h,v 1.120 2003/05/02 21:59:31 momjian Exp $
*
* NOTES
* some of the information in this file should be moved to
*/
extern bool IsUnderPostmaster;
extern bool ClientAuthInProgress;
-extern const bool ExecBackend;
extern int PostmasterMain(int argc, char *argv[]);
extern void ClosePostmasterPorts(bool pgstat_too);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: ipc.h,v 1.58 2003/05/02 21:52:42 momjian Exp $
+ * $Id: ipc.h,v 1.59 2003/05/02 21:59:31 momjian Exp $
*
*-------------------------------------------------------------------------
*/
extern void CreateSharedMemoryAndSemaphores(bool makePrivate,
int maxBackends,
int port);
-extern void AttachSharedMemoryAndSemaphores(void);
#endif /* IPC_H */
* Copyright 2000-2003 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
- * $Id: guc.h,v 1.27 2003/04/25 19:45:09 tgl Exp $
+ * $Id: guc.h,v 1.28 2003/05/02 21:59:31 momjian Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name);
+#ifdef EXEC_BACKEND
+void write_nondefault_variables(GucContext context);
+void read_nondefault_variables(void);
+#endif
+
#endif /* GUC_H */