diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 42e12b6282..8b055aa960 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -13,7 +13,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -157,7 +157,7 @@ static ClogCtlData *ClogCtl = NULL; * 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. @@ -271,67 +271,41 @@ TransactionIdGetStatus(TransactionId xid) /* * 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); + ClogCtl = (ClogCtlData *) + ShmemInitStruct("CLOG Ctl", + MAXALIGN(sizeof(ClogCtlData) + + CLOG_BLCKSZ * NUM_CLOG_BUFFERS), + &found); + Assert(!found); - if (!IsUnderPostmaster) - /* Initialize ClogCtl shared memory area */ + memset(ClogCtl, 0, sizeof(ClogCtlData)); + + bufptr = ((char *) ClogCtl) + sizeof(ClogCtlData); + + for (slotno = 0; slotno < NUM_CLOG_BUFFERS; slotno++) { - char *bufptr; - - Assert(!found); - - 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; - } - - /* ClogCtl->latest_page_number will be set later */ + 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); diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 9c971ff931..8040dd5bb8 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -8,7 +8,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -301,11 +301,6 @@ BootstrapMain(int argc, char *argv[]) Assert(dbName); - if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */) - { - AttachSharedMemoryAndSemaphores(); - } - if (!IsUnderPostmaster) { if (!potential_DataDir) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 0e52aff2c5..1e3edfcb90 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * 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 * @@ -172,13 +172,6 @@ static int ServerSock_INET = INVALID_SOCK; /* stream socket server */ 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 */ @@ -263,11 +256,12 @@ static void dummy_handler(SIGNAL_ARGS); 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); @@ -577,6 +571,9 @@ PostmasterMain(int argc, char *argv[]) SetDataDir(potential_DataDir); ProcessConfigFile(PGC_POSTMASTER); +#ifdef EXEC_BACKEND + write_nondefault_variables(PGC_POSTMASTER); +#endif /* * Check for invalid combinations of GUC settings. @@ -1238,7 +1235,7 @@ ProcessStartupPacket(Port *port, bool SSLdone) * 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. */ @@ -1410,11 +1407,7 @@ processCancelRequest(Port *port, void *pkt) 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)) @@ -1579,6 +1572,9 @@ SIGHUP_handler(SIGNAL_ARGS) 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(); } @@ -2064,28 +2060,7 @@ BackendStartup(Port *port) 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) @@ -2119,6 +2094,31 @@ BackendStartup(Port *port) } +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 @@ -2184,7 +2184,7 @@ split_opts(char **argv, int *argcp, char *s) } /* - * 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; @@ -2195,7 +2195,7 @@ split_opts(char **argv, int *argcp, char *s) * If PostgresMain() fails, return status. */ static int -DoBackend(Port *port) +BackendFinalize(Port *port) { char *remote_host; char **av; @@ -2232,6 +2232,10 @@ DoBackend(Port *port) /* 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 @@ -2259,7 +2263,7 @@ DoBackend(Port *port) 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 @@ -2305,7 +2309,7 @@ DoBackend(Port *port) } else { - /* not AF_INET */ + /* not AF_INET */ remote_host = "[local]"; if (Log_connections) @@ -2329,7 +2333,7 @@ DoBackend(Port *port) * 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 @@ -2358,7 +2362,7 @@ DoBackend(Port *port) * 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) diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 094f3c145a..ae27a3ce40 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -8,7 +8,7 @@ * * * 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 $ * *------------------------------------------------------------------------- */ @@ -134,16 +134,3 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, */ PMSignalInit(); } - - -/* - * AttachSharedMemoryAndSemaphores - * Attaches to the existing shared resources when exec()'d off - * by the postmaster. - */ -void -AttachSharedMemoryAndSemaphores(void) -{ - CLOGShmemInit(); -} - diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 2bd147cc57..e201bc77e5 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * 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 @@ -1453,7 +1453,6 @@ PostgresMain(int argc, char *argv[], const char *username) break; } - /* * -d is not the same as setting * log_min_messages because it enables other @@ -1578,9 +1577,6 @@ PostgresMain(int argc, char *argv[], const char *username) * restart... */ } BaseInit(); -#ifdef EXECBACKEND - AttachSharedMemoryAndSemaphores(); -#endif } else { @@ -1676,7 +1672,7 @@ PostgresMain(int argc, char *argv[], const char *username) 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"); } /* diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index f18c74c472..5d71c3b7a4 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * 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 $ * *-------------------------------------------------------------------- */ @@ -60,6 +60,9 @@ #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; @@ -2801,6 +2804,204 @@ _ShowOption(struct config_generic * record) } +#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 @@ -3203,3 +3404,4 @@ assign_msglvl(int *var, const char *newval, bool doit, bool interactive) #include "guc-file.c" + diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 4b6a6621f0..ce2fad6d4a 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * 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 @@ -106,7 +106,6 @@ extern void ProcessInterrupts(void); */ extern bool IsUnderPostmaster; extern bool ClientAuthInProgress; -extern const bool ExecBackend; extern int PostmasterMain(int argc, char *argv[]); extern void ClosePostmasterPorts(bool pgstat_too); diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index 0798ea4bb3..a01dc2cb22 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -11,7 +11,7 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,5 @@ extern void on_exit_reset(void); extern void CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends, int port); -extern void AttachSharedMemoryAndSemaphores(void); #endif /* IPC_H */ diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 47a5eeab18..ecc09fdd99 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -7,7 +7,7 @@ * Copyright 2000-2003 by PostgreSQL Global Development Group * Written by Peter Eisentraut . * - * $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 @@ -135,4 +135,9 @@ extern void ProcessGUCArray(ArrayType *array, GucSource source); 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 */