From d75b2ec4ebbc7fdb51088e89da47c6523bf2c640 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Sat, 20 Dec 2003 17:31:21 +0000 Subject: [PATCH] This patch is the next step towards (re)allowing fork/exec. Claudio Natoli --- src/backend/access/transam/xlog.c | 27 +- src/backend/bootstrap/bootstrap.c | 7 +- src/backend/postmaster/pgstat.c | 4 +- src/backend/postmaster/postmaster.c | 286 +++++++++++++++++----- src/backend/storage/buffer/buf_init.c | 6 +- src/backend/storage/file/fd.c | 15 +- src/backend/storage/freespace/freespace.c | 22 +- src/backend/storage/ipc/ipci.c | 28 ++- src/backend/storage/ipc/pmsignal.c | 6 +- src/backend/storage/ipc/shmem.c | 133 ++++++---- src/backend/storage/ipc/sinvaladt.c | 7 +- src/backend/storage/lmgr/lock.c | 48 ++-- src/backend/storage/lmgr/lwlock.c | 4 +- src/backend/storage/lmgr/proc.c | 5 +- src/backend/tcop/postgres.c | 61 +++-- src/include/access/xlogdefs.h | 9 +- src/include/c.h | 9 +- src/include/libpq/libpq-be.h | 8 +- src/include/storage/fd.h | 6 +- src/include/storage/ipc.h | 4 +- src/include/storage/lock.h | 4 +- src/include/storage/lwlock.h | 3 +- src/include/storage/shmem.h | 4 +- 23 files changed, 490 insertions(+), 216 deletions(-) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 794e392f78..1f8eb50795 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.128 2003/12/14 00:34:47 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.129 2003/12/20 17:31:20 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -166,7 +166,7 @@ XLogRecPtr ProcLastRecEnd = {0, 0}; * to update from XLogCtl->Insert.RedoRecPtr if we hold the info_lck; * see GetRedoRecPtr. */ -static XLogRecPtr RedoRecPtr; +NON_EXEC_STATIC XLogRecPtr RedoRecPtr; /*---------- * Shared-memory data structures for XLOG control @@ -231,12 +231,6 @@ typedef struct XLogwrtRqst XLogRecPtr Flush; /* last byte + 1 to flush */ } XLogwrtRqst; -typedef struct XLogwrtResult -{ - XLogRecPtr Write; /* last byte + 1 written out */ - XLogRecPtr Flush; /* last byte + 1 flushed */ -} XLogwrtResult; - /* * Shared state data for XLogInsert. */ @@ -404,7 +398,7 @@ static char ControlFilePath[MAXPGPATH]; * Private, possibly out-of-date copy of shared LogwrtResult. * See discussion above. */ -static XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}}; +NON_EXEC_STATIC XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}}; /* * openLogFile is -1 or a kernel FD for an open log file segment. @@ -2398,7 +2392,7 @@ XLOGShmemSize(void) void XLOGShmemInit(void) { - bool found; + bool foundXLog, foundCFile; /* this must agree with space requested by XLOGShmemSize() */ if (XLOGbuffers < MinXLOGbuffers) @@ -2409,11 +2403,16 @@ XLOGShmemInit(void) MAXALIGN(sizeof(XLogCtlData) + sizeof(XLogRecPtr) * XLOGbuffers) + BLCKSZ * XLOGbuffers, - &found); - Assert(!found); + &foundXLog); ControlFile = (ControlFileData *) - ShmemInitStruct("Control File", sizeof(ControlFileData), &found); - Assert(!found); + ShmemInitStruct("Control File", sizeof(ControlFileData), &foundCFile); + + if (foundXLog || foundCFile) + { + /* both should be present or neither */ + Assert(foundXLog && foundCFile); + return; + } memset(XLogCtl, 0, sizeof(XLogCtlData)); diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 94daf94355..4820582eb3 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 - * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.170 2003/12/12 18:45:08 petere Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.171 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -347,9 +347,10 @@ BootstrapMain(int argc, char *argv[]) if (!dbname || argc != optind) usage(); - - if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */ ) +#ifdef EXEC_BACKEND + if (IsUnderPostmaster && MyProc /* ordinary backend */ ) AttachSharedMemoryAndSemaphores(); +#endif if (!IsUnderPostmaster /* when exec || ExecBackend */ ) { diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 7eef116303..38323f45ba 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -13,7 +13,7 @@ * * Copyright (c) 2001-2003, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.48 2003/11/29 19:51:55 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.49 2003/12/20 17:31:21 momjian Exp $ * ---------- */ #include "postgres.h" @@ -71,7 +71,7 @@ bool pgstat_is_running = false; * Local data * ---------- */ -static int pgStatSock = -1; +NON_EXEC_STATIC int pgStatSock = -1; static int pgStatPipe[2]; static struct sockaddr_storage pgStatAddr; static int pgStatPmPipe[2] = {-1, -1}; diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index b17ade7376..f0560ce6f7 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.351 2003/12/01 22:15:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.352 2003/12/20 17:31:21 momjian Exp $ * * NOTES * @@ -273,6 +273,7 @@ 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); +NON_EXEC_STATIC bool BackendInit(Port *port); static int BackendFork(Port *port); static void ExitPostmaster(int status); static void usage(const char *); @@ -282,10 +283,6 @@ static int ProcessStartupPacket(Port *port, bool SSLdone); static void processCancelRequest(Port *port, void *pkt); static int initMasks(fd_set *rmask); static void report_fork_failure_to_client(Port *port, int errnum); -enum CAC_state -{ - CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY -}; static enum CAC_state canAcceptConnections(void); static long PostmasterRandom(void); static void RandomSalt(char *cryptSalt, char *md5Salt); @@ -298,6 +295,11 @@ postmaster_error(const char *fmt,...) /* This lets gcc check the format string for consistency. */ __attribute__((format(printf, 1, 2))); +#ifdef EXEC_BACKEND +static void +write_backend_variables(pid_t pid, Port *port); +#endif + #define StartupDataBase() SSDataBase(BS_XLOG_STARTUP) #define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT) #define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER) @@ -1185,7 +1187,6 @@ initMasks(fd_set *rmask) static int ProcessStartupPacket(Port *port, bool SSLdone) { - enum CAC_state cac; int32 len; void *buf; ProtocolVersion proto; @@ -1244,7 +1245,11 @@ ProcessStartupPacket(Port *port, bool SSLdone) if (proto == CANCEL_REQUEST_CODE) { +#ifdef EXEC_BACKEND + abort(); /* FIXME: [fork/exec] Whoops. Not handled... yet */ +#else processCancelRequest(port, buf); +#endif return 127; /* XXX */ } @@ -1435,9 +1440,7 @@ ProcessStartupPacket(Port *port, bool SSLdone) * so now instead of wasting cycles on an authentication exchange. * (This also allows a pg_ping utility to be written.) */ - cac = canAcceptConnections(); - - switch (cac) + switch (port->canAcceptConnections) { case CAC_STARTUP: ereport(FATAL, @@ -1499,8 +1502,10 @@ processCancelRequest(Port *port, void *pkt) backendPID))); return; } - else if (ExecBackend) +#ifdef EXEC_BACKEND + else AttachSharedMemoryAndSemaphores(); +#endif /* See if we have a matching backend */ @@ -2341,40 +2346,25 @@ split_opts(char **argv, int *argcp, char *s) } } + /* - * BackendFork -- 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; - * it's the same executable as the postmaster. + * BackendInit/Fork -- perform authentication [BackendInit], and if successful, + * set up the backend's argument list [BackendFork] and invoke + * backend main() [or exec in EXEC_BACKEND case] * * returns: * Shouldn't return at all. * If PostgresMain() fails, return status. */ -static int -BackendFork(Port *port) +NON_EXEC_STATIC bool +BackendInit(Port *port) { - char **av; - int maxac; - int ac; - char debugbuf[32]; - char protobuf[32]; - -#ifdef EXEC_BACKEND - char pbuf[NAMEDATALEN + 256]; -#endif - int i; int status; struct timeval now; struct timezone tz; char remote_host[NI_MAXHOST]; char remote_port[NI_MAXSERV]; - /* - * Let's clean up ourselves as the postmaster child - */ - IsUnderPostmaster = true; /* we are a postmaster subprocess now */ ClientAuthInProgress = true; /* limit visibility of log messages */ @@ -2386,9 +2376,6 @@ BackendFork(Port *port) * Signal handlers setting is moved to tcop/postgres... */ - /* Close the postmaster's other sockets */ - ClosePostmasterPorts(true); - /* Save port etc. for ps status */ MyProcPort = port; @@ -2444,16 +2431,6 @@ BackendFork(Port *port) StrNCpy(remote_host, tmphost, sizeof(remote_host)); } - /* - * PreAuthDelay is a debugging aid for investigating problems in the - * authentication cycle: it can be set in postgresql.conf to allow - * time to attach to the newly-forked backend with a debugger. (See - * also the -W backend switch, which we allow clients to pass through - * PGOPTIONS, but it is not honored until after authentication.) - */ - if (PreAuthDelay > 0) - sleep(PreAuthDelay); - /* * Ready to begin client interaction. We will give up and exit(0) * after a time delay, so that a broken client can't hog a connection @@ -2469,7 +2446,7 @@ BackendFork(Port *port) status = ProcessStartupPacket(port, false); if (status != STATUS_OK) - return 0; /* cancel request processed, or error */ + return false; /* cancel request processed, or error */ /* * Now that we have the user and database name, we can set the process @@ -2506,6 +2483,50 @@ BackendFork(Port *port) gettimeofday(&now, &tz); srandom((unsigned int) now.tv_usec); +#ifdef EXEC_BACKEND + ClientAuthInProgress = false; /* client_min_messages is active + * now */ +#endif + return true; +} + + +static int +BackendFork(Port *port) +{ + char **av; + int maxac; + int ac; + char debugbuf[32]; +#ifndef EXEC_BACKEND + char protobuf[32]; +#endif + int i; + char tmpExtraOptions[MAXPGPATH]; + + /* + * Let's clean up ourselves as the postmaster child, and + * close the postmaster's other sockets + */ + ClosePostmasterPorts(true); + + /* + * PreAuthDelay is a debugging aid for investigating problems in the + * authentication cycle: it can be set in postgresql.conf to allow + * time to attach to the newly-forked backend with a debugger. (See + * also the -W backend switch, which we allow clients to pass through + * PGOPTIONS, but it is not honored until after authentication.) + */ + if (PreAuthDelay > 0) + sleep(PreAuthDelay); + + port->canAcceptConnections = canAcceptConnections(); + +#ifndef EXEC_BACKEND + if (!BackendInit(port)) + return -1; +#endif + /* ---------------- * Now, build the argv vector that will be given to PostgresMain. * @@ -2540,30 +2561,38 @@ BackendFork(Port *port) /* * Pass any backend switches specified with -o in the postmaster's own - * command line. We assume these are secure. (It's OK to mangle - * ExtraOptions since we are now in the child process; this won't - * change the postmaster's copy.) + * command line. We assume these are secure. + * [Note: now makes a copy to protect against future fork/exec changes] */ - split_opts(av, &ac, ExtraOptions); + strcpy(tmpExtraOptions,ExtraOptions); + split_opts(av, &ac, tmpExtraOptions); +#ifndef EXEC_BACKEND /* Tell the backend what protocol the frontend is using. */ snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto); av[ac++] = protobuf; +#endif /* * Tell the backend it is being called from the postmaster, and which * database to use. -p marks the end of secure switches. */ - av[ac++] = "-p"; #ifdef EXEC_BACKEND - Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL); - /* database name at the end because it might contain commas */ - snprintf(pbuf, sizeof(pbuf), "%d,%d,%lu,%p,%s", - port->sock, canAcceptConnections(), - UsedShmemSegID, UsedShmemSegAddr, - port->database_name); - av[ac++] = pbuf; + write_backend_variables(getpid(),port); + + /* pass data dir before end of secure switches (-p) */ + av[ac++] = "-D"; + av[ac++] = DataDir; + + /* + * This is totally bogus. We need to pass an arg to -p, but we'll + * actually get the dbname by ProcessStartupPacket in the exec'd + * process + */ + av[ac++] = "-p"; + av[ac++] = "FORK_EXEC"; #else + av[ac++] = "-p"; av[ac++] = port->database_name; #endif @@ -2571,6 +2600,10 @@ BackendFork(Port *port) * Pass the (insecure) option switches from the connection request. * (It's OK to mangle port->cmdline_options now.) */ + /* FIXME: [fork/exec] Hmmm.. we won't see these until after we BackendInit. + * Should we add code to BackendInit to add these (somehow!) into + * the PostgresMain argument list in the EXEC_BACKEND case? + */ if (port->cmdline_options) split_opts(av, &ac, port->cmdline_options); @@ -2594,17 +2627,21 @@ BackendFork(Port *port) */ ereport(DEBUG3, (errmsg_internal("%s child[%d]: starting with (", - progname, MyProcPid))); + progname, getpid()))); for (i = 0; i < ac; ++i) ereport(DEBUG3, (errmsg_internal("\t%s", av[i]))); ereport(DEBUG3, (errmsg_internal(")"))); +#ifdef EXEC_BACKEND + return execv(pg_pathname,av); +#else ClientAuthInProgress = false; /* client_min_messages is active * now */ return (PostgresMain(ac, av, port->user_name)); +#endif } /* @@ -3051,3 +3088,136 @@ postmaster_error(const char *fmt,...) va_end(ap); fprintf(stderr, "\n"); } + + +#ifdef EXEC_BACKEND + +/* + * The following need to be available to the read/write_backend_variables + * functions + */ +extern XLogRecPtr RedoRecPtr; +extern XLogwrtResult LogwrtResult; +extern slock_t *ShmemLock; +extern slock_t *ShmemIndexLock; +extern void *ShmemIndexAlloc; +typedef struct LWLock LWLock; +extern LWLock *LWLockArray; +extern slock_t *ProcStructLock; +extern int pgStatSock; + +#define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp) +#define read_var(var,fp) fread((void*)&(var),sizeof(var),1,fp); +#define get_tmp_backend_file_name(buf,id) \ + do { \ + Assert(DataDir); \ + sprintf((buf), \ + "%s/%s/%s.backend_var.%d", \ + DataDir, \ + PG_TEMP_FILES_DIR, \ + PG_TEMP_FILE_PREFIX, \ + (id)); \ + } while (0) + +static void +write_backend_variables(pid_t pid, Port *port) +{ + char filename[MAXPGPATH]; + FILE *fp; + get_tmp_backend_file_name(filename,pid); + + /* Open file */ + fp = AllocateFile(filename, PG_BINARY_W); + if (!fp) + { + /* As per OpenTemporaryFile... */ + char dirname[MAXPGPATH]; + sprintf(dirname,"%s/%s",DataDir,PG_TEMP_FILES_DIR); + mkdir(dirname, S_IRWXU); + + fp = AllocateFile(filename, PG_BINARY_W); + if (!fp) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not write to file \"%s\": %m", filename))); + return; + } + } + + /* Write vars */ + write_var(port->sock,fp); + write_var(port->proto,fp); + write_var(port->laddr,fp); + write_var(port->raddr,fp); + write_var(port->canAcceptConnections,fp); + write_var(MyCancelKey,fp); + + write_var(RedoRecPtr,fp); + write_var(LogwrtResult,fp); + + write_var(UsedShmemSegID,fp); + write_var(UsedShmemSegAddr,fp); + + write_var(ShmemLock,fp); + write_var(ShmemIndexLock,fp); + write_var(ShmemVariableCache,fp); + write_var(ShmemIndexAlloc,fp); + + write_var(LWLockArray,fp); + write_var(ProcStructLock,fp); + write_var(pgStatSock,fp); + + /* Release file */ + FreeFile(fp); +} + +void +read_backend_variables(pid_t pid, Port *port) +{ + char filename[MAXPGPATH]; + FILE *fp; + get_tmp_backend_file_name(filename,pid); + + /* Open file */ + fp = AllocateFile(filename, PG_BINARY_R); + if (!fp) + { + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not read from backend_variables file \"%s\": %m", filename))); + return; + } + + /* Read vars */ + read_var(port->sock,fp); + read_var(port->proto,fp); + read_var(port->laddr,fp); + read_var(port->raddr,fp); + read_var(port->canAcceptConnections,fp); + read_var(MyCancelKey,fp); + + read_var(RedoRecPtr,fp); + read_var(LogwrtResult,fp); + + read_var(UsedShmemSegID,fp); + read_var(UsedShmemSegAddr,fp); + + read_var(ShmemLock,fp); + read_var(ShmemIndexLock,fp); + read_var(ShmemVariableCache,fp); + read_var(ShmemIndexAlloc,fp); + + read_var(LWLockArray,fp); + read_var(ProcStructLock,fp); + read_var(pgStatSock,fp); + + /* Release file */ + FreeFile(fp); + if (unlink(filename) != 0) + ereport(WARNING, + (errcode_for_file_access(), + errmsg("could not remove file \"%s\": %m", filename))); +} + +#endif diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index 1c66b950a5..1a707568b5 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.59 2003/12/14 00:34:47 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.60 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -125,7 +125,9 @@ InitBufferPool(void) * anyone else attached to the shmem at this point, we've got * problems. */ +#ifndef EXEC_BACKEND LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); +#endif BufferDescriptors = (BufferDesc *) ShmemInitStruct("Buffer Descriptors", @@ -177,7 +179,9 @@ InitBufferPool(void) /* Init other shared buffer-management stuff */ StrategyInitialize(!foundDescs); +#ifndef EXEC_BACKEND LWLockRelease(BufMgrLock); +#endif } /* diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 78814d77b6..4875b7f2bc 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.104 2003/12/12 18:45:09 petere Exp $ + * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.105 2003/12/20 17:31:21 momjian Exp $ * * NOTES: * @@ -53,11 +53,6 @@ #include "storage/ipc.h" -/* Filename components for OpenTemporaryFile */ -#define PG_TEMP_FILES_DIR "pgsql_tmp" -#define PG_TEMP_FILE_PREFIX "pgsql_tmp" - - /* * Problem: Postgres does a system(ld...) to do dynamic loading. * This will open several extra files in addition to those used by @@ -1217,8 +1212,12 @@ RemovePgTempFiles(void) { while ((db_de = readdir(db_dir)) != NULL) { - if (strcmp(db_de->d_name, ".") == 0 || - strcmp(db_de->d_name, "..") == 0) + if (strcmp(db_de->d_name, ".") == 0 +#ifndef EXEC_BACKEND + /* no PG_TEMP_FILES_DIR in DataDir in non EXEC_BACKEND case */ + || strcmp(db_de->d_name, "..") == 0 +#endif + ) continue; snprintf(temp_path, sizeof(temp_path), diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index a7bffb5c73..84f5c65c92 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.27 2003/12/12 18:45:09 petere Exp $ + * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.28 2003/12/20 17:31:21 momjian Exp $ * * * NOTES: @@ -180,7 +180,6 @@ typedef struct FSMRelation FSMRelation; /* Header for whole map */ struct FSMHeader { - HTAB *relHash; /* hashtable of FSMRelation entries */ FSMRelation *usageList; /* FSMRelations in usage-recency order */ FSMRelation *usageListTail; /* tail of usage-recency list */ FSMRelation *firstRel; /* FSMRelations in arena storage order */ @@ -218,6 +217,7 @@ int MaxFSMRelations; /* these are set by guc.c */ int MaxFSMPages; static FSMHeader *FreeSpaceMap; /* points to FSMHeader in shared memory */ +static HTAB *FreeSpaceMapRelHash; /* points to (what used to be) FSMHeader->relHash */ static FSMRelation *lookup_fsm_rel(RelFileNode *rel); @@ -265,13 +265,15 @@ InitFreeSpaceMap(void) { HASHCTL info; int nchunks; + bool found; /* Create table header */ - FreeSpaceMap = (FSMHeader *) ShmemAlloc(sizeof(FSMHeader)); + FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header",sizeof(FSMHeader),&found); if (FreeSpaceMap == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("insufficient shared memory for free space map"))); + if (!found) MemSet(FreeSpaceMap, 0, sizeof(FSMHeader)); /* Create hashtable for FSMRelations */ @@ -279,17 +281,21 @@ InitFreeSpaceMap(void) info.entrysize = sizeof(FSMRelation); info.hash = tag_hash; - FreeSpaceMap->relHash = ShmemInitHash("Free Space Map Hash", + FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash", MaxFSMRelations / 10, MaxFSMRelations, &info, (HASH_ELEM | HASH_FUNCTION)); - if (!FreeSpaceMap->relHash) + if (!FreeSpaceMapRelHash) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("insufficient shared memory for free space map"))); + if (found) + return; + + /* Allocate page-storage arena */ nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1; /* This check ensures spareChunks will be greater than zero */ @@ -974,7 +980,7 @@ lookup_fsm_rel(RelFileNode *rel) { FSMRelation *fsmrel; - fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash, + fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash, (void *) rel, HASH_FIND, NULL); @@ -995,7 +1001,7 @@ create_fsm_rel(RelFileNode *rel) FSMRelation *fsmrel; bool found; - fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash, + fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash, (void *) rel, HASH_ENTER, &found); @@ -1050,7 +1056,7 @@ delete_fsm_rel(FSMRelation *fsmrel) unlink_fsm_rel_usage(fsmrel); unlink_fsm_rel_storage(fsmrel); FreeSpaceMap->numRels--; - result = (FSMRelation *) hash_search(FreeSpaceMap->relHash, + result = (FSMRelation *) hash_search(FreeSpaceMapRelHash, (void *) &(fsmrel->key), HASH_REMOVE, NULL); diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 982846843a..eaf22a095f 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.59 2003/12/01 21:59:25 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.60 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -87,7 +87,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, /* * Set up shared memory allocation mechanism */ - InitShmemAllocation(seghdr); + InitShmemAllocation(seghdr, true); /* * Now initialize LWLocks, which do shared memory allocation and are @@ -135,12 +135,36 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, } +#ifdef EXEC_BACKEND /* * AttachSharedMemoryAndSemaphores * Attaches to the existing shared resources. */ + +/* FIXME: [fork/exec] This function is starting to look pretty much like + CreateSharedMemoryAndSemaphores. Refactor? */ void AttachSharedMemoryAndSemaphores(void) { + PGShmemHeader *seghdr = PGSharedMemoryCreate(-1,false,-1); + + InitShmemAllocation(seghdr, false); + + InitShmemIndex(); + + XLOGShmemInit(); CLOGShmemInit(); + InitBufferPool(); + + InitLocks(); + InitLockTable(MaxBackends); + + InitProcGlobal(MaxBackends); + + CreateSharedInvalidationState(MaxBackends); + + InitFreeSpaceMap(); + + PMSignalInit(); } +#endif diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c index 6545c748d3..fb2b2faca0 100644 --- a/src/backend/storage/ipc/pmsignal.c +++ b/src/backend/storage/ipc/pmsignal.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.6 2003/11/29 19:51:56 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.7 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -44,9 +44,11 @@ static volatile sig_atomic_t *PMSignalFlags; void PMSignalInit(void) { + bool found; PMSignalFlags = (sig_atomic_t *) - ShmemAlloc(NUM_PMSIGNALS * sizeof(sig_atomic_t)); + ShmemInitStruct("PMSignalFlags",NUM_PMSIGNALS * sizeof(sig_atomic_t),&found); + if (!found) MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t)); } diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index b4e1439d15..598597f0aa 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.74 2003/11/29 19:51:56 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.75 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -74,7 +74,11 @@ SHMEM_OFFSET ShmemBase; /* start address of shared memory */ static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */ -static slock_t *ShmemLock; /* spinlock for shared memory allocation */ +NON_EXEC_STATIC slock_t *ShmemLock; /* spinlock for shared memory allocation */ + +NON_EXEC_STATIC slock_t *ShmemIndexLock; /* spinlock for ShmemIndex */ + +NON_EXEC_STATIC void *ShmemIndexAlloc = NULL; /* Memory actually allocated for ShmemIndex */ static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */ @@ -88,7 +92,7 @@ static bool ShmemBootstrap = false; /* bootstrapping shmem index? */ * but we use void to avoid having to include ipc.h in shmem.h. */ void -InitShmemAllocation(void *seghdr) +InitShmemAllocation(void *seghdr, bool init) { PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; @@ -97,26 +101,34 @@ InitShmemAllocation(void *seghdr) ShmemBase = (SHMEM_OFFSET) shmhdr; ShmemEnd = ShmemBase + shmhdr->totalsize; - /* - * Initialize the spinlock used by ShmemAlloc. We have to do the - * space allocation the hard way, since ShmemAlloc can't be called - * yet. - */ - ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); - shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); - Assert(shmhdr->freeoffset <= shmhdr->totalsize); + if (init) + { + /* + * Initialize the spinlocks used by ShmemAlloc/ShmemInitStruct. We + * have to do the space allocation the hard way, since ShmemAlloc + * can't be called yet. + */ + ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); + shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); + Assert(shmhdr->freeoffset <= shmhdr->totalsize); - SpinLockInit(ShmemLock); + ShmemIndexLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); + shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); + Assert(shmhdr->freeoffset <= shmhdr->totalsize); - /* ShmemIndex can't be set up yet (need LWLocks first) */ - ShmemIndex = (HTAB *) NULL; - - /* - * Initialize ShmemVariableCache for transaction manager. - */ - ShmemVariableCache = (VariableCache) + SpinLockInit(ShmemLock); + SpinLockInit(ShmemIndexLock); + + /* ShmemIndex can't be set up yet (need LWLocks first) */ + ShmemIndex = (HTAB *) NULL; + + /* + * Initialize ShmemVariableCache for transaction manager. + */ + ShmemVariableCache = (VariableCache) ShmemAlloc(sizeof(*ShmemVariableCache)); - memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); + memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); + } } /* @@ -218,25 +230,28 @@ InitShmemIndex(void) /* * Now, create an entry in the hashtable for the index itself. */ - MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE); - strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE); - - result = (ShmemIndexEnt *) - hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found); - if (!result) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of shared memory"))); - - Assert(ShmemBootstrap && !found); - - result->location = MAKE_OFFSET(ShmemIndex->hctl); - result->size = SHMEM_INDEX_SIZE; - - ShmemBootstrap = false; + if (!IsUnderPostmaster) + { + MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE); + strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE); + + result = (ShmemIndexEnt *) + hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found); + if (!result) + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of shared memory"))); + + Assert(ShmemBootstrap && !found); + + result->location = MAKE_OFFSET(ShmemIndex->hctl); + result->size = SHMEM_INDEX_SIZE; + + ShmemBootstrap = false; + } /* now release the lock acquired in ShmemInitStruct */ - LWLockRelease(ShmemIndexLock); + SpinLockRelease(ShmemIndexLock); } /* @@ -320,21 +335,33 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) strncpy(item.key, name, SHMEM_INDEX_KEYSIZE); item.location = BAD_LOCATION; - LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); + SpinLockAcquire(ShmemIndexLock); if (!ShmemIndex) { - /* - * If the shmem index doesn't exist, we are bootstrapping: we must - * be trying to init the shmem index itself. - * - * Notice that the ShmemIndexLock is held until the shmem index has - * been completely initialized. - */ - Assert(strcmp(name, "ShmemIndex") == 0); - Assert(ShmemBootstrap); - *foundPtr = FALSE; - return ShmemAlloc(size); + if (IsUnderPostmaster) + { + /* Must be initializing a (non-standalone) backend */ + Assert(strcmp(name, "ShmemIndex") == 0); + Assert(ShmemBootstrap); + Assert(ShmemIndexAlloc); + *foundPtr = TRUE; + } + else + { + /* + * If the shmem index doesn't exist, we are bootstrapping: we must + * be trying to init the shmem index itself. + * + * Notice that the ShmemIndexLock is held until the shmem index has + * been completely initialized. + */ + Assert(strcmp(name, "ShmemIndex") == 0); + Assert(ShmemBootstrap); + *foundPtr = FALSE; + ShmemIndexAlloc = ShmemAlloc(size); + } + return ShmemIndexAlloc; } /* look it up in the shmem index */ @@ -343,7 +370,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) if (!result) { - LWLockRelease(ShmemIndexLock); + SpinLockRelease(ShmemIndexLock); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); @@ -359,7 +386,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) */ if (result->size != size) { - LWLockRelease(ShmemIndexLock); + SpinLockRelease(ShmemIndexLock); elog(WARNING, "ShmemIndex entry size is wrong"); /* let caller print its message too */ @@ -376,7 +403,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) /* out of memory */ Assert(ShmemIndex); hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL); - LWLockRelease(ShmemIndexLock); + SpinLockRelease(ShmemIndexLock); ereport(WARNING, (errcode(ERRCODE_OUT_OF_MEMORY), @@ -389,6 +416,6 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr) } Assert(ShmemIsValid((unsigned long) structPtr)); - LWLockRelease(ShmemIndexLock); + SpinLockRelease(ShmemIndexLock); return structPtr; } diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c index ff26f9b86e..a50cc4601e 100644 --- a/src/backend/storage/ipc/sinvaladt.c +++ b/src/backend/storage/ipc/sinvaladt.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.53 2003/11/29 19:51:56 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.54 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -50,10 +50,13 @@ SIBufferInit(int maxBackends) int segSize; SISeg *segP; int i; + bool found; /* Allocate space in shared memory */ segSize = SInvalShmemSize(maxBackends); - shmInvalBuffer = segP = (SISeg *) ShmemAlloc(segSize); + shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer",segSize,&found); + if (found) + return; /* Clear message counters, save size of procState array */ segP->minMsgNum = 0; diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 6b450a1d35..8cb25b4ccd 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.130 2003/12/01 21:59:25 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.131 2003/12/20 17:31:21 momjian Exp $ * * NOTES * Outside modules can create a lock table and acquire/release @@ -153,9 +153,11 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP) * map from lock method id to the lock table structure */ static LockMethod LockMethods[MAX_LOCK_METHODS]; - +static HTAB* LockMethodLockHash[MAX_LOCK_METHODS]; +static HTAB* LockMethodProcLockHash[MAX_LOCK_METHODS]; static int NumLockMethods; + /* * InitLocks -- Init the lock module. Create a private data * structure for constructing conflict masks. @@ -245,8 +247,9 @@ LockMethodTableInit(char *tabName, /* * Lock the LWLock for the table (probably not necessary here) */ +#ifndef EXEC_BACKEND LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); - +#endif /* * no zero-th table */ @@ -279,15 +282,15 @@ LockMethodTableInit(char *tabName, hash_flags = (HASH_ELEM | HASH_FUNCTION); sprintf(shmemName, "%s (lock hash)", tabName); - newLockMethod->lockHash = ShmemInitHash(shmemName, + LockMethodLockHash[NumLockMethods-1] = ShmemInitHash(shmemName, init_table_size, max_table_size, &info, hash_flags); - if (!newLockMethod->lockHash) + if (!LockMethodLockHash[NumLockMethods-1]) elog(FATAL, "could not initialize lock table \"%s\"", tabName); - Assert(newLockMethod->lockHash->hash == tag_hash); + Assert(LockMethodLockHash[NumLockMethods-1]->hash == tag_hash); /* * allocate a hash table for PROCLOCK structs. This is used to store @@ -299,20 +302,21 @@ LockMethodTableInit(char *tabName, hash_flags = (HASH_ELEM | HASH_FUNCTION); sprintf(shmemName, "%s (proclock hash)", tabName); - newLockMethod->proclockHash = ShmemInitHash(shmemName, + LockMethodProcLockHash[NumLockMethods-1] = ShmemInitHash(shmemName, init_table_size, max_table_size, &info, hash_flags); - if (!newLockMethod->proclockHash) + if (!LockMethodProcLockHash[NumLockMethods-1]) elog(FATAL, "could not initialize lock table \"%s\"", tabName); /* init data structures */ LockMethodInit(newLockMethod, conflictsP, numModes); +#ifndef EXEC_BACKEND LWLockRelease(LockMgrLock); - +#endif pfree(shmemName); return newLockMethod->lockmethodid; @@ -449,8 +453,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag, /* * Find or create a lock with this tag */ - Assert(lockMethodTable->lockHash->hash == tag_hash); - lock = (LOCK *) hash_search(lockMethodTable->lockHash, + Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); + lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) locktag, HASH_ENTER, &found); if (!lock) @@ -497,7 +501,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag, /* * Find or create a proclock entry with this tag */ - proclockTable = lockMethodTable->proclockHash; + proclockTable = LockMethodProcLockHash[lockmethodid]; proclock = (PROCLOCK *) hash_search(proclockTable, (void *) &proclocktag, HASH_ENTER, &found); @@ -988,8 +992,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag, /* * Find a lock with this tag */ - Assert(lockMethodTable->lockHash->hash == tag_hash); - lock = (LOCK *) hash_search(lockMethodTable->lockHash, + Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); + lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) locktag, HASH_FIND, NULL); @@ -1014,7 +1018,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag, proclocktag.proc = MAKE_OFFSET(MyProc); TransactionIdStore(xid, &proclocktag.xid); - proclockTable = lockMethodTable->proclockHash; + proclockTable = LockMethodProcLockHash[lockmethodid]; proclock = (PROCLOCK *) hash_search(proclockTable, (void *) &proclocktag, HASH_FIND_SAVE, NULL); @@ -1086,8 +1090,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag, * if there's no one waiting in the queue, we just released the * last lock on this object. Delete it from the lock table. */ - Assert(lockMethodTable->lockHash->hash == tag_hash); - lock = (LOCK *) hash_search(lockMethodTable->lockHash, + Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); + lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) &(lock->tag), HASH_REMOVE, NULL); @@ -1269,7 +1273,7 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc, /* * remove the proclock entry from the hashtable */ - proclock = (PROCLOCK *) hash_search(lockMethodTable->proclockHash, + proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid], (void *) proclock, HASH_REMOVE, NULL); @@ -1287,8 +1291,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc, * lock object. */ LOCK_PRINT("LockReleaseAll: deleting", lock, 0); - Assert(lockMethodTable->lockHash->hash == tag_hash); - lock = (LOCK *) hash_search(lockMethodTable->lockHash, + Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); + lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) &(lock->tag), HASH_REMOVE, NULL); if (!lock) @@ -1367,7 +1371,7 @@ GetLockStatusData(void) LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); - proclockTable = LockMethods[DEFAULT_LOCKMETHOD]->proclockHash; + proclockTable = LockMethodProcLockHash[DEFAULT_LOCKMETHOD]; data->nelements = i = proclockTable->hctl->nentries; @@ -1480,7 +1484,7 @@ DumpAllLocks(void) if (!lockMethodTable) return; - proclockTable = lockMethodTable->proclockHash; + proclockTable = LockMethodProcLockHash[lockmethodid]; if (proc->waitLock) LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0); diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 4142bb5198..efb3ac4a90 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.18 2003/11/29 19:51:57 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.19 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -43,7 +43,7 @@ typedef struct LWLock * the pointer by fork from the postmaster. LWLockIds are indexes into * the array. */ -static LWLock *LWLockArray = NULL; +NON_EXEC_STATIC LWLock *LWLockArray = NULL; /* shared counter for dynamic allocation of LWLockIds */ static int *LWLockCounter; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index effe5ac524..a4bab87e24 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.140 2003/12/12 18:45:09 petere Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.141 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -66,7 +66,7 @@ PGPROC *MyProc = NULL; * relatively infrequently (only at backend startup or shutdown) and not for * very long, so a spinlock is okay. */ -static slock_t *ProcStructLock = NULL; +NON_EXEC_STATIC slock_t *ProcStructLock = NULL; static PROC_HDR *ProcGlobal = NULL; @@ -248,6 +248,7 @@ InitProcess(void) MyProc->waitHolder = NULL; SHMQueueInit(&(MyProc->procHolders)); + /* * Arrange to clean up at backend exit. */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 0162cdc2d4..66f6dc063c 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.379 2003/12/01 22:15:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.380 2003/12/20 17:31:21 momjian Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -68,6 +68,10 @@ extern int optind; extern char *optarg; +#ifdef EXEC_BACKEND +extern bool BackendInit(Port*); +extern void read_backend_variables(pid_t, Port*); +#endif /* ---------------- * global variables @@ -2052,7 +2056,6 @@ PostgresMain(int argc, char *argv[], const char *username) * initialize globals (already done if under postmaster, but not if * standalone; cheap enough to do over) */ - MyProcPid = getpid(); /* @@ -2060,7 +2063,7 @@ PostgresMain(int argc, char *argv[], const char *username) * * If we are running under the postmaster, this is done already. */ - if (!IsUnderPostmaster) + if (!IsUnderPostmaster /* when exec || ExecBackend */) MemoryContextInit(); set_ps_display("startup"); @@ -2268,7 +2271,6 @@ PostgresMain(int argc, char *argv[], const char *username) break; case 'p': - /* * p - special flag passed if backend was forked by a * postmaster. @@ -2276,23 +2278,11 @@ PostgresMain(int argc, char *argv[], const char *username) if (secure) { #ifdef EXEC_BACKEND - char *p; - int i; - int PMcanAcceptConnections; /* will eventually be - * global or static, - * when fork */ - - sscanf(optarg, "%d,%d,%lu,%p,", - &MyProcPort->sock, &PMcanAcceptConnections, - &UsedShmemSegID, &UsedShmemSegAddr); - /* Grab dbname as last param */ - for (i = 0, p = optarg - 1; i < 4 && p; i++) - p = strchr(p + 1, ','); - if (i == 4 && p) - dbname = strdup(p + 1); + IsUnderPostmaster = true; #else dbname = strdup(optarg); #endif + secure = false; /* subsequent switches are NOT * secure */ ctx = PGC_BACKEND; @@ -2477,7 +2467,7 @@ PostgresMain(int argc, char *argv[], const char *username) SetConfigOption("log_statement_stats", "false", ctx, gucsource); } - if (!IsUnderPostmaster) + if (!IsUnderPostmaster || ExecBackend) { if (!potential_DataDir) { @@ -2497,10 +2487,27 @@ PostgresMain(int argc, char *argv[], const char *username) if (IsUnderPostmaster) { #ifdef EXEC_BACKEND + Port *port =(Port*)malloc(sizeof(Port)); + if (port == NULL) + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("insufficient memory to allocate port"))); + read_nondefault_variables(); + read_backend_variables(getpid(),port); + + /* FIXME: [fork/exec] Ugh */ + load_hba(); + load_ident(); + load_user(); + load_group(); + + if (!BackendInit(port)) + return -1; + + dbname = port->database_name; #endif - } - else + } else ProcessConfigFile(PGC_POSTMASTER); /* @@ -2517,7 +2524,6 @@ PostgresMain(int argc, char *argv[], const char *username) * course, this isn't an issue for signals that are locally generated, * such as SIGALRM and SIGPIPE.) */ - pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */ pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */ pqsignal(SIGTERM, die); /* cancel current query and exit */ @@ -2565,10 +2571,12 @@ PostgresMain(int argc, char *argv[], const char *username) errmsg("invalid command-line arguments for server process"), errhint("Try \"%s --help\" for more information.", argv[0]))); } - BaseInit(); -#ifdef EXECBACKEND +#ifdef EXEC_BACKEND AttachSharedMemoryAndSemaphores(); #endif + XLOGPathInit(); + + BaseInit(); } else { @@ -2845,7 +2853,11 @@ PostgresMain(int argc, char *argv[], const char *username) if (got_SIGHUP) { got_SIGHUP = false; +#ifdef EXEC_BACKEND + read_nondefault_variables(); +#else ProcessConfigFile(PGC_SIGHUP); +#endif } /* @@ -3199,4 +3211,3 @@ ShowUsage(const char *title) pfree(str.data); } - diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h index 023469c1cc..057236e4ed 100644 --- a/src/include/access/xlogdefs.h +++ b/src/include/access/xlogdefs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/xlogdefs.h,v 1.10 2003/11/29 22:40:55 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/access/xlogdefs.h,v 1.11 2003/12/20 17:31:21 momjian Exp $ */ #ifndef XLOG_DEFS_H #define XLOG_DEFS_H @@ -33,6 +33,13 @@ typedef struct XLogRecPtr uint32 xrecoff; /* byte offset of location in log file */ } XLogRecPtr; +typedef struct XLogwrtResult +{ + XLogRecPtr Write; /* last byte + 1 written out */ + XLogRecPtr Flush; /* last byte + 1 flushed */ +} XLogwrtResult; + + /* * Macros for comparing XLogRecPtrs * diff --git a/src/include/c.h b/src/include/c.h index f08f56633d..984bf14fca 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/c.h,v 1.157 2003/11/29 22:40:53 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/c.h,v 1.158 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -793,6 +793,13 @@ extern int fdatasync(int fildes); #define HAVE_STRTOULL 1 #endif +/* EXEC_BACKEND defines */ +#ifdef EXEC_BACKEND +#define NON_EXEC_STATIC +#else +#define NON_EXEC_STATIC static +#endif + /* /port compatibility functions */ #include "port.h" diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h index a7dc475f57..f011afed86 100644 --- a/src/include/libpq/libpq-be.h +++ b/src/include/libpq/libpq-be.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.38 2003/11/29 22:41:03 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.39 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -27,6 +27,11 @@ #endif +typedef enum CAC_state +{ + CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY +} CAC_state; + /* * This is used by the postmaster in its communication with frontends. It * contains all state information needed during this communication before the @@ -42,6 +47,7 @@ typedef struct Port ProtocolVersion proto; /* FE/BE protocol version */ SockAddr laddr; /* local addr (postmaster) */ SockAddr raddr; /* remote addr (client) */ + CAC_state canAcceptConnections; /* postmaster connection status */ /* * Information that needs to be saved from the startup packet and diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index cb81f36a8a..35a75a3671 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.40 2003/11/29 22:41:13 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.41 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -77,4 +77,8 @@ extern void RemovePgTempFiles(void); extern int pg_fsync(int fd); extern int pg_fdatasync(int fd); +/* Filename components for OpenTemporaryFile */ +#define PG_TEMP_FILES_DIR "pgsql_tmp" +#define PG_TEMP_FILE_PREFIX "pgsql_tmp" + #endif /* FD_H */ diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h index fb59cd0200..3c2765cc48 100644 --- a/src/include/storage/ipc.h +++ b/src/include/storage/ipc.h @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/ipc.h,v 1.63 2003/12/12 18:45:10 petere Exp $ + * $PostgreSQL: pgsql/src/include/storage/ipc.h,v 1.64 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -32,6 +32,8 @@ extern void on_exit_reset(void); extern void CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends, int port); +#ifdef EXEC_BACKEND extern void AttachSharedMemoryAndSemaphores(void); +#endif #endif /* IPC_H */ diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index a7d66b835e..2d13e9df11 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.75 2003/12/01 21:59:25 momjian Exp $ + * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.76 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -86,8 +86,6 @@ typedef uint16 LOCKMETHODID; */ typedef struct LockMethodData { - HTAB *lockHash; - HTAB *proclockHash; LOCKMETHODID lockmethodid; int numLockModes; LOCKMASK conflictTab[MAX_LOCKMODES]; diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h index db5b3d49bb..34f9c6613c 100644 --- a/src/include/storage/lwlock.h +++ b/src/include/storage/lwlock.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.9 2003/11/29 22:41:13 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/storage/lwlock.h,v 1.10 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,6 @@ typedef enum LWLockId LockMgrLock, OidGenLock, XidGenLock, - ShmemIndexLock, SInvalLock, FreeSpaceLock, MMCacheLock, diff --git a/src/include/storage/shmem.h b/src/include/storage/shmem.h index a818f65fe9..648cdf8c3a 100644 --- a/src/include/storage/shmem.h +++ b/src/include/storage/shmem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.40 2003/11/29 22:41:13 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/storage/shmem.h,v 1.41 2003/12/20 17:31:21 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -61,7 +61,7 @@ typedef struct SHM_QUEUE } SHM_QUEUE; /* shmem.c */ -extern void InitShmemAllocation(void *seghdr); +extern void InitShmemAllocation(void *seghdr, bool init); extern void *ShmemAlloc(Size size); extern bool ShmemIsValid(unsigned long addr); extern void InitShmemIndex(void);