Index: src/backend/access/transam/xlog.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/access/transam/xlog.c,v retrieving revision 1.127 diff -c -w -r1.127 xlog.c *** src/backend/access/transam/xlog.c 12 Dec 2003 18:45:08 -0000 1.127 --- src/backend/access/transam/xlog.c 13 Dec 2003 06:18:30 -0000 *************** *** 166,172 **** * to update from XLogCtl->Insert.RedoRecPtr if we hold the info_lck; * see GetRedoRecPtr. */ ! static XLogRecPtr RedoRecPtr; /*---------- * Shared-memory data structures for XLOG control --- 166,172 ---- * to update from XLogCtl->Insert.RedoRecPtr if we hold the info_lck; * see GetRedoRecPtr. */ ! NON_EXEC_STATIC XLogRecPtr RedoRecPtr; /*---------- * Shared-memory data structures for XLOG control *************** *** 231,242 **** 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. */ --- 231,236 ---- *************** *** 404,410 **** * Private, possibly out-of-date copy of shared LogwrtResult. * See discussion above. */ ! static XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}}; /* * openLogFile is -1 or a kernel FD for an open log file segment. --- 398,404 ---- * Private, possibly out-of-date copy of shared LogwrtResult. * See discussion above. */ ! NON_EXEC_STATIC XLogwrtResult LogwrtResult = {{0, 0}, {0, 0}}; /* * openLogFile is -1 or a kernel FD for an open log file segment. *************** *** 2397,2403 **** void XLOGShmemInit(void) { ! bool found; /* this must agree with space requested by XLOGShmemSize() */ if (XLOGbuffers < MinXLOGbuffers) --- 2391,2397 ---- void XLOGShmemInit(void) { ! bool foundXLog, foundCFile; /* this must agree with space requested by XLOGShmemSize() */ if (XLOGbuffers < MinXLOGbuffers) *************** *** 2408,2418 **** MAXALIGN(sizeof(XLogCtlData) + sizeof(XLogRecPtr) * XLOGbuffers) + BLCKSZ * XLOGbuffers, ! &found); ! Assert(!found); ControlFile = (ControlFileData *) ! ShmemInitStruct("Control File", sizeof(ControlFileData), &found); ! Assert(!found); memset(XLogCtl, 0, sizeof(XLogCtlData)); --- 2402,2417 ---- MAXALIGN(sizeof(XLogCtlData) + sizeof(XLogRecPtr) * XLOGbuffers) + BLCKSZ * XLOGbuffers, ! &foundXLog); ControlFile = (ControlFileData *) ! ShmemInitStruct("Control File", sizeof(ControlFileData), &foundCFile); ! ! if (foundXLog || foundCFile) ! { ! /* both should be present or neither */ ! Assert(foundXLog && foundCFile); ! return; ! } memset(XLogCtl, 0, sizeof(XLogCtlData)); Index: src/backend/bootstrap/bootstrap.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/bootstrap/bootstrap.c,v retrieving revision 1.170 diff -c -w -r1.170 bootstrap.c *** src/backend/bootstrap/bootstrap.c 12 Dec 2003 18:45:08 -0000 1.170 --- src/backend/bootstrap/bootstrap.c 13 Dec 2003 06:18:31 -0000 *************** *** 347,355 **** if (!dbname || argc != optind) usage(); ! ! if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */ ) AttachSharedMemoryAndSemaphores(); if (!IsUnderPostmaster /* when exec || ExecBackend */ ) { --- 347,356 ---- if (!dbname || argc != optind) usage(); ! #ifdef EXEC_BACKEND ! if (IsUnderPostmaster && MyProc /* ordinary backend */ ) AttachSharedMemoryAndSemaphores(); + #endif if (!IsUnderPostmaster /* when exec || ExecBackend */ ) { Index: src/backend/postmaster/pgstat.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/pgstat.c,v retrieving revision 1.48 diff -c -w -r1.48 pgstat.c *** src/backend/postmaster/pgstat.c 29 Nov 2003 19:51:55 -0000 1.48 --- src/backend/postmaster/pgstat.c 13 Dec 2003 06:18:33 -0000 *************** *** 71,77 **** * Local data * ---------- */ ! static int pgStatSock = -1; static int pgStatPipe[2]; static struct sockaddr_storage pgStatAddr; static int pgStatPmPipe[2] = {-1, -1}; --- 71,77 ---- * Local data * ---------- */ ! NON_EXEC_STATIC int pgStatSock = -1; static int pgStatPipe[2]; static struct sockaddr_storage pgStatAddr; static int pgStatPmPipe[2] = {-1, -1}; Index: src/backend/postmaster/postmaster.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v retrieving revision 1.351 diff -c -w -r1.351 postmaster.c *** src/backend/postmaster/postmaster.c 1 Dec 2003 22:15:37 -0000 1.351 --- src/backend/postmaster/postmaster.c 13 Dec 2003 06:18:36 -0000 *************** *** 282,291 **** 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); --- 282,287 ---- *************** *** 298,303 **** --- 294,302 ---- /* This lets gcc check the format string for consistency. */ __attribute__((format(printf, 1, 2))); + static void + write_backend_variables(pid_t pid, Port *port); + #define StartupDataBase() SSDataBase(BS_XLOG_STARTUP) #define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT) #define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER) *************** *** 1185,1191 **** static int ProcessStartupPacket(Port *port, bool SSLdone) { - enum CAC_state cac; int32 len; void *buf; ProtocolVersion proto; --- 1184,1189 ---- *************** *** 1244,1250 **** --- 1242,1252 ---- 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,1443 **** * so now instead of wasting cycles on an authentication exchange. * (This also allows a pg_ping utility to be written.) */ ! cac = canAcceptConnections(); ! ! switch (cac) { case CAC_STARTUP: ereport(FATAL, --- 1437,1443 ---- * so now instead of wasting cycles on an authentication exchange. * (This also allows a pg_ping utility to be written.) */ ! switch (port->canAcceptConnections) { case CAC_STARTUP: ereport(FATAL, *************** *** 1499,1506 **** backendPID))); return; } ! else if (ExecBackend) AttachSharedMemoryAndSemaphores(); /* See if we have a matching backend */ --- 1499,1508 ---- backendPID))); return; } ! #ifdef EXEC_BACKEND ! else AttachSharedMemoryAndSemaphores(); + #endif /* See if we have a matching backend */ *************** *** 2341,2380 **** } } /* ! * 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. * * returns: * Shouldn't return at all. * If PostgresMain() fails, return status. */ ! static int ! BackendFork(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 */ --- 2343,2366 ---- } } + /* ! * 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. */ ! bool BackendInit(Port *port) { int status; struct timeval now; struct timezone tz; char remote_host[NI_MAXHOST]; char remote_port[NI_MAXSERV]; IsUnderPostmaster = true; /* we are a postmaster subprocess now */ ClientAuthInProgress = true; /* limit visibility of log messages */ *************** *** 2386,2394 **** * Signal handlers setting is moved to tcop/postgres... */ - /* Close the postmaster's other sockets */ - ClosePostmasterPorts(true); - /* Save port etc. for ps status */ MyProcPort = port; --- 2372,2377 ---- *************** *** 2445,2460 **** } /* - * 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 * indefinitely. PreAuthDelay doesn't count against the time limit. --- 2428,2433 ---- *************** *** 2469,2475 **** status = ProcessStartupPacket(port, false); if (status != STATUS_OK) ! return 0; /* cancel request processed, or error */ /* * Now that we have the user and database name, we can set the process --- 2442,2448 ---- status = ProcessStartupPacket(port, false); if (status != STATUS_OK) ! return false; /* cancel request processed, or error */ /* * Now that we have the user and database name, we can set the process *************** *** 2506,2511 **** --- 2479,2528 ---- 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,2569 **** /* * 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.) */ ! split_opts(av, &ac, ExtraOptions); /* Tell the backend what protocol the frontend is using. */ snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto); av[ac++] = protobuf; /* * 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; #else av[ac++] = port->database_name; #endif --- 2557,2594 ---- /* * Pass any backend switches specified with -o in the postmaster's own ! * command line. We assume these are secure. ! * [Note: now makes a copy to protect against future fork/exec changes] */ ! 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. */ #ifdef EXEC_BACKEND ! 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,2576 **** --- 2596,2605 ---- * 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,2610 **** */ ereport(DEBUG3, (errmsg_internal("%s child[%d]: starting with (", ! progname, MyProcPid))); for (i = 0; i < ac; ++i) ereport(DEBUG3, (errmsg_internal("\t%s", av[i]))); ereport(DEBUG3, (errmsg_internal(")"))); ClientAuthInProgress = false; /* client_min_messages is active * now */ return (PostgresMain(ac, av, port->user_name)); } /* --- 2623,2643 ---- */ ereport(DEBUG3, (errmsg_internal("%s child[%d]: starting with (", ! 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,3053 **** --- 3084,3216 ---- 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_var_dir(buf) \ + sprintf((buf),"%s/%s",DataDir,PG_TEMP_FILES_DIR) + #define get_tmp_backend_var_file_name(buf,id) \ + Assert(DataDir); \ + sprintf((buf), \ + "%s/%s/%s.backend_var.%d", \ + DataDir, \ + PG_TEMP_FILES_DIR, \ + PG_TEMP_FILE_PREFIX, \ + (id)) + + static void + write_backend_variables(pid_t pid, Port *port) + { + char filename[MAXPGPATH]; + FILE *fp; + get_tmp_backend_var_file_name(filename,pid); + + /* Open file */ + fp = AllocateFile(filename, PG_BINARY_W); + if (!fp) + { + /* As per OpenTemporaryFile... */ + char dirname[MAXPGPATH]; + get_tmp_backend_var_dir(dirname); + mkdir(dirname, S_IRWXU); + + fp = AllocateFile(filename, PG_BINARY_W); + if (!fp) + { + ereport(FATAL, + (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_var_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); + unlink(filename); + } + + #endif Index: src/backend/storage/buffer/buf_init.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/buffer/buf_init.c,v retrieving revision 1.58 diff -c -w -r1.58 buf_init.c *** src/backend/storage/buffer/buf_init.c 29 Nov 2003 19:51:56 -0000 1.58 --- src/backend/storage/buffer/buf_init.c 13 Dec 2003 06:18:36 -0000 *************** *** 136,142 **** --- 136,144 ---- * anyone else attached to the shmem at this point, we've got * problems. */ + #ifndef EXEC_BACKEND LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); + #endif #ifdef BMTRACE CurTraceBuf = (long *) ShmemInitStruct("Buffer trace", *************** *** 198,204 **** --- 200,208 ---- /* Init other shared buffer-management stuff */ StrategyInitialize(!foundDescs); + #ifndef EXEC_BACKEND LWLockRelease(BufMgrLock); + #endif } /* Index: src/backend/storage/file/fd.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/file/fd.c,v retrieving revision 1.104 diff -c -w -r1.104 fd.c *** src/backend/storage/file/fd.c 12 Dec 2003 18:45:09 -0000 1.104 --- src/backend/storage/file/fd.c 13 Dec 2003 06:18:37 -0000 *************** *** 53,63 **** #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 --- 53,58 ---- *************** *** 1217,1224 **** { while ((db_de = readdir(db_dir)) != NULL) { ! if (strcmp(db_de->d_name, ".") == 0 || ! strcmp(db_de->d_name, "..") == 0) continue; snprintf(temp_path, sizeof(temp_path), --- 1212,1223 ---- { while ((db_de = readdir(db_dir)) != NULL) { ! 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), Index: src/backend/storage/freespace/freespace.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/freespace/freespace.c,v retrieving revision 1.27 diff -c -w -r1.27 freespace.c *** src/backend/storage/freespace/freespace.c 12 Dec 2003 18:45:09 -0000 1.27 --- src/backend/storage/freespace/freespace.c 13 Dec 2003 06:18:38 -0000 *************** *** 180,186 **** /* 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 */ --- 180,185 ---- *************** *** 218,223 **** --- 217,223 ---- 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,277 **** { HASHCTL info; int nchunks; /* Create table header */ ! FreeSpaceMap = (FSMHeader *) ShmemAlloc(sizeof(FSMHeader)); if (FreeSpaceMap == NULL) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("insufficient shared memory for free space map"))); MemSet(FreeSpaceMap, 0, sizeof(FSMHeader)); /* Create hashtable for FSMRelations */ --- 265,279 ---- { HASHCTL info; int nchunks; + bool found; /* Create table header */ ! 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,295 **** info.entrysize = sizeof(FSMRelation); info.hash = tag_hash; ! FreeSpaceMap->relHash = ShmemInitHash("Free Space Map Hash", MaxFSMRelations / 10, MaxFSMRelations, &info, (HASH_ELEM | HASH_FUNCTION)); ! if (!FreeSpaceMap->relHash) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("insufficient shared memory for free space map"))); /* Allocate page-storage arena */ nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1; /* This check ensures spareChunks will be greater than zero */ --- 281,301 ---- info.entrysize = sizeof(FSMRelation); info.hash = tag_hash; ! FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash", MaxFSMRelations / 10, MaxFSMRelations, &info, (HASH_ELEM | HASH_FUNCTION)); ! 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,980 **** { FSMRelation *fsmrel; ! fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash, (void *) rel, HASH_FIND, NULL); --- 980,986 ---- { FSMRelation *fsmrel; ! fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash, (void *) rel, HASH_FIND, NULL); *************** *** 995,1001 **** FSMRelation *fsmrel; bool found; ! fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash, (void *) rel, HASH_ENTER, &found); --- 1001,1007 ---- FSMRelation *fsmrel; bool found; ! fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash, (void *) rel, HASH_ENTER, &found); *************** *** 1050,1056 **** unlink_fsm_rel_usage(fsmrel); unlink_fsm_rel_storage(fsmrel); FreeSpaceMap->numRels--; ! result = (FSMRelation *) hash_search(FreeSpaceMap->relHash, (void *) &(fsmrel->key), HASH_REMOVE, NULL); --- 1056,1062 ---- unlink_fsm_rel_usage(fsmrel); unlink_fsm_rel_storage(fsmrel); FreeSpaceMap->numRels--; ! result = (FSMRelation *) hash_search(FreeSpaceMapRelHash, (void *) &(fsmrel->key), HASH_REMOVE, NULL); Index: src/backend/storage/ipc/ipci.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/ipci.c,v retrieving revision 1.59 diff -c -w -r1.59 ipci.c *** src/backend/storage/ipc/ipci.c 1 Dec 2003 21:59:25 -0000 1.59 --- src/backend/storage/ipc/ipci.c 13 Dec 2003 06:18:38 -0000 *************** *** 87,93 **** /* * Set up shared memory allocation mechanism */ ! InitShmemAllocation(seghdr); /* * Now initialize LWLocks, which do shared memory allocation and are --- 87,93 ---- /* * Set up shared memory allocation mechanism */ ! InitShmemAllocation(seghdr, true); /* * Now initialize LWLocks, which do shared memory allocation and are *************** *** 135,146 **** --- 135,170 ---- } + #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 Index: src/backend/storage/ipc/pmsignal.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/pmsignal.c,v retrieving revision 1.6 diff -c -w -r1.6 pmsignal.c *** src/backend/storage/ipc/pmsignal.c 29 Nov 2003 19:51:56 -0000 1.6 --- src/backend/storage/ipc/pmsignal.c 13 Dec 2003 06:18:38 -0000 *************** *** 44,52 **** void PMSignalInit(void) { PMSignalFlags = (sig_atomic_t *) ! ShmemAlloc(NUM_PMSIGNALS * sizeof(sig_atomic_t)); MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t)); } --- 44,54 ---- void PMSignalInit(void) { + bool found; PMSignalFlags = (sig_atomic_t *) ! ShmemInitStruct("PMSignalFlags",NUM_PMSIGNALS * sizeof(sig_atomic_t),&found); + if (!found) MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t)); } Index: src/backend/storage/ipc/shmem.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/shmem.c,v retrieving revision 1.74 diff -c -w -r1.74 shmem.c *** src/backend/storage/ipc/shmem.c 29 Nov 2003 19:51:56 -0000 1.74 --- src/backend/storage/ipc/shmem.c 13 Dec 2003 06:18:39 -0000 *************** *** 74,80 **** static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */ ! static slock_t *ShmemLock; /* spinlock for shared memory allocation */ static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */ --- 74,84 ---- static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */ ! 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,94 **** * but we use void to avoid having to include ipc.h in shmem.h. */ void ! InitShmemAllocation(void *seghdr) { PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; --- 92,98 ---- * but we use void to avoid having to include ipc.h in shmem.h. */ void ! InitShmemAllocation(void *seghdr, bool init) { PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; *************** *** 97,112 **** 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); SpinLockInit(ShmemLock); /* ShmemIndex can't be set up yet (need LWLocks first) */ ShmemIndex = (HTAB *) NULL; --- 101,123 ---- ShmemBase = (SHMEM_OFFSET) shmhdr; ShmemEnd = ShmemBase + 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); + ShmemIndexLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); + shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); + Assert(shmhdr->freeoffset <= shmhdr->totalsize); + SpinLockInit(ShmemLock); + SpinLockInit(ShmemIndexLock); /* ShmemIndex can't be set up yet (need LWLocks first) */ ShmemIndex = (HTAB *) NULL; *************** *** 118,123 **** --- 129,135 ---- ShmemAlloc(sizeof(*ShmemVariableCache)); memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache)); } + } /* * ShmemAlloc -- allocate max-aligned chunk from shared memory *************** *** 218,223 **** --- 230,237 ---- /* * Now, create an entry in the hashtable for the index itself. */ + if (!IsUnderPostmaster) + { MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE); strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE); *************** *** 234,242 **** result->size = SHMEM_INDEX_SIZE; ShmemBootstrap = false; /* now release the lock acquired in ShmemInitStruct */ ! LWLockRelease(ShmemIndexLock); } /* --- 248,257 ---- result->size = SHMEM_INDEX_SIZE; ShmemBootstrap = false; + } /* now release the lock acquired in ShmemInitStruct */ ! SpinLockRelease(ShmemIndexLock); } /* *************** *** 320,340 **** strncpy(item.key, name, SHMEM_INDEX_KEYSIZE); item.location = BAD_LOCATION; ! LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); 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); } /* look it up in the shmem index */ --- 335,367 ---- strncpy(item.key, name, SHMEM_INDEX_KEYSIZE); item.location = BAD_LOCATION; ! SpinLockAcquire(ShmemIndexLock); if (!ShmemIndex) { + 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 ShmemLock 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,349 **** if (!result) { ! LWLockRelease(ShmemIndexLock); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); --- 370,376 ---- if (!result) { ! SpinLockRelease(ShmemIndexLock); ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of shared memory"))); *************** *** 359,365 **** */ if (result->size != size) { ! LWLockRelease(ShmemIndexLock); elog(WARNING, "ShmemIndex entry size is wrong"); /* let caller print its message too */ --- 386,392 ---- */ if (result->size != size) { ! SpinLockRelease(ShmemIndexLock); elog(WARNING, "ShmemIndex entry size is wrong"); /* let caller print its message too */ *************** *** 376,382 **** /* out of memory */ Assert(ShmemIndex); hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL); ! LWLockRelease(ShmemIndexLock); ereport(WARNING, (errcode(ERRCODE_OUT_OF_MEMORY), --- 403,409 ---- /* out of memory */ Assert(ShmemIndex); hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL); ! SpinLockRelease(ShmemIndexLock); ereport(WARNING, (errcode(ERRCODE_OUT_OF_MEMORY), *************** *** 389,394 **** } Assert(ShmemIsValid((unsigned long) structPtr)); ! LWLockRelease(ShmemIndexLock); return structPtr; } --- 416,421 ---- } Assert(ShmemIsValid((unsigned long) structPtr)); ! SpinLockRelease(ShmemIndexLock); return structPtr; } Index: src/backend/storage/ipc/sinvaladt.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/ipc/sinvaladt.c,v retrieving revision 1.53 diff -c -w -r1.53 sinvaladt.c *** src/backend/storage/ipc/sinvaladt.c 29 Nov 2003 19:51:56 -0000 1.53 --- src/backend/storage/ipc/sinvaladt.c 13 Dec 2003 06:18:39 -0000 *************** *** 50,59 **** int segSize; SISeg *segP; int i; /* Allocate space in shared memory */ segSize = SInvalShmemSize(maxBackends); ! shmInvalBuffer = segP = (SISeg *) ShmemAlloc(segSize); /* Clear message counters, save size of procState array */ segP->minMsgNum = 0; --- 50,62 ---- int segSize; SISeg *segP; int i; + bool found; /* Allocate space in shared memory */ segSize = SInvalShmemSize(maxBackends); ! shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer",segSize,&found); ! if (found) ! return; /* Clear message counters, save size of procState array */ segP->minMsgNum = 0; Index: src/backend/storage/lmgr/lock.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/lmgr/lock.c,v retrieving revision 1.130 diff -c -w -r1.130 lock.c *** src/backend/storage/lmgr/lock.c 1 Dec 2003 21:59:25 -0000 1.130 --- src/backend/storage/lmgr/lock.c 13 Dec 2003 06:18:40 -0000 *************** *** 153,161 **** * map from lock method id to the lock table structure */ static LockMethod LockMethods[MAX_LOCK_METHODS]; ! static int NumLockMethods; /* * InitLocks -- Init the lock module. Create a private data * structure for constructing conflict masks. --- 153,163 ---- * 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,252 **** /* * Lock the LWLock for the table (probably not necessary here) */ LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); ! /* * no zero-th table */ --- 247,255 ---- /* * Lock the LWLock for the table (probably not necessary here) */ + #ifndef EXEC_BACKEND LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); ! #endif /* * no zero-th table */ *************** *** 279,293 **** hash_flags = (HASH_ELEM | HASH_FUNCTION); sprintf(shmemName, "%s (lock hash)", tabName); ! newLockMethod->lockHash = ShmemInitHash(shmemName, init_table_size, max_table_size, &info, hash_flags); ! if (!newLockMethod->lockHash) elog(FATAL, "could not initialize lock table \"%s\"", tabName); ! Assert(newLockMethod->lockHash->hash == tag_hash); /* * allocate a hash table for PROCLOCK structs. This is used to store --- 282,296 ---- hash_flags = (HASH_ELEM | HASH_FUNCTION); sprintf(shmemName, "%s (lock hash)", tabName); ! LockMethodLockHash[NumLockMethods-1] = ShmemInitHash(shmemName, init_table_size, max_table_size, &info, hash_flags); ! if (!LockMethodLockHash[NumLockMethods-1]) elog(FATAL, "could not initialize lock table \"%s\"", tabName); ! Assert(LockMethodLockHash[NumLockMethods-1]->hash == tag_hash); /* * allocate a hash table for PROCLOCK structs. This is used to store *************** *** 299,318 **** hash_flags = (HASH_ELEM | HASH_FUNCTION); sprintf(shmemName, "%s (proclock hash)", tabName); ! newLockMethod->proclockHash = ShmemInitHash(shmemName, init_table_size, max_table_size, &info, hash_flags); ! if (!newLockMethod->proclockHash) elog(FATAL, "could not initialize lock table \"%s\"", tabName); /* init data structures */ LockMethodInit(newLockMethod, conflictsP, numModes); LWLockRelease(LockMgrLock); ! pfree(shmemName); return newLockMethod->lockmethodid; --- 302,322 ---- hash_flags = (HASH_ELEM | HASH_FUNCTION); sprintf(shmemName, "%s (proclock hash)", tabName); ! LockMethodProcLockHash[NumLockMethods-1] = ShmemInitHash(shmemName, init_table_size, max_table_size, &info, hash_flags); ! 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,456 **** /* * Find or create a lock with this tag */ ! Assert(lockMethodTable->lockHash->hash == tag_hash); ! lock = (LOCK *) hash_search(lockMethodTable->lockHash, (void *) locktag, HASH_ENTER, &found); if (!lock) --- 453,460 ---- /* * Find or create a lock with this tag */ ! Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); ! lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) locktag, HASH_ENTER, &found); if (!lock) *************** *** 497,503 **** /* * Find or create a proclock entry with this tag */ ! proclockTable = lockMethodTable->proclockHash; proclock = (PROCLOCK *) hash_search(proclockTable, (void *) &proclocktag, HASH_ENTER, &found); --- 501,507 ---- /* * Find or create a proclock entry with this tag */ ! proclockTable = LockMethodProcLockHash[lockmethodid]; proclock = (PROCLOCK *) hash_search(proclockTable, (void *) &proclocktag, HASH_ENTER, &found); *************** *** 988,995 **** /* * Find a lock with this tag */ ! Assert(lockMethodTable->lockHash->hash == tag_hash); ! lock = (LOCK *) hash_search(lockMethodTable->lockHash, (void *) locktag, HASH_FIND, NULL); --- 992,999 ---- /* * Find a lock with this tag */ ! Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); ! lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) locktag, HASH_FIND, NULL); *************** *** 1014,1020 **** proclocktag.proc = MAKE_OFFSET(MyProc); TransactionIdStore(xid, &proclocktag.xid); ! proclockTable = lockMethodTable->proclockHash; proclock = (PROCLOCK *) hash_search(proclockTable, (void *) &proclocktag, HASH_FIND_SAVE, NULL); --- 1018,1024 ---- proclocktag.proc = MAKE_OFFSET(MyProc); TransactionIdStore(xid, &proclocktag.xid); ! proclockTable = LockMethodProcLockHash[lockmethodid]; proclock = (PROCLOCK *) hash_search(proclockTable, (void *) &proclocktag, HASH_FIND_SAVE, NULL); *************** *** 1086,1093 **** * 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, (void *) &(lock->tag), HASH_REMOVE, NULL); --- 1090,1097 ---- * 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(LockMethodLockHash[lockmethodid]->hash == tag_hash); ! lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) &(lock->tag), HASH_REMOVE, NULL); *************** *** 1269,1275 **** /* * remove the proclock entry from the hashtable */ ! proclock = (PROCLOCK *) hash_search(lockMethodTable->proclockHash, (void *) proclock, HASH_REMOVE, NULL); --- 1273,1279 ---- /* * remove the proclock entry from the hashtable */ ! proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid], (void *) proclock, HASH_REMOVE, NULL); *************** *** 1287,1294 **** * lock object. */ LOCK_PRINT("LockReleaseAll: deleting", lock, 0); ! Assert(lockMethodTable->lockHash->hash == tag_hash); ! lock = (LOCK *) hash_search(lockMethodTable->lockHash, (void *) &(lock->tag), HASH_REMOVE, NULL); if (!lock) --- 1291,1298 ---- * lock object. */ LOCK_PRINT("LockReleaseAll: deleting", lock, 0); ! Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash); ! lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid], (void *) &(lock->tag), HASH_REMOVE, NULL); if (!lock) *************** *** 1367,1373 **** LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); ! proclockTable = LockMethods[DEFAULT_LOCKMETHOD]->proclockHash; data->nelements = i = proclockTable->hctl->nentries; --- 1371,1377 ---- LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); ! proclockTable = LockMethodProcLockHash[DEFAULT_LOCKMETHOD]; data->nelements = i = proclockTable->hctl->nentries; *************** *** 1480,1486 **** if (!lockMethodTable) return; ! proclockTable = lockMethodTable->proclockHash; if (proc->waitLock) LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0); --- 1484,1490 ---- if (!lockMethodTable) return; ! proclockTable = LockMethodProcLockHash[lockmethodid]; if (proc->waitLock) LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0); Index: src/backend/storage/lmgr/lwlock.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/lmgr/lwlock.c,v retrieving revision 1.18 diff -c -w -r1.18 lwlock.c *** src/backend/storage/lmgr/lwlock.c 29 Nov 2003 19:51:57 -0000 1.18 --- src/backend/storage/lmgr/lwlock.c 13 Dec 2003 06:18:40 -0000 *************** *** 43,49 **** * the pointer by fork from the postmaster. LWLockIds are indexes into * the array. */ ! static LWLock *LWLockArray = NULL; /* shared counter for dynamic allocation of LWLockIds */ static int *LWLockCounter; --- 43,49 ---- * the pointer by fork from the postmaster. LWLockIds are indexes into * the array. */ ! NON_EXEC_STATIC LWLock *LWLockArray = NULL; /* shared counter for dynamic allocation of LWLockIds */ static int *LWLockCounter; Index: src/backend/storage/lmgr/proc.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/storage/lmgr/proc.c,v retrieving revision 1.140 diff -c -w -r1.140 proc.c *** src/backend/storage/lmgr/proc.c 12 Dec 2003 18:45:09 -0000 1.140 --- src/backend/storage/lmgr/proc.c 13 Dec 2003 06:18:41 -0000 *************** *** 66,72 **** * relatively infrequently (only at backend startup or shutdown) and not for * very long, so a spinlock is okay. */ ! static slock_t *ProcStructLock = NULL; static PROC_HDR *ProcGlobal = NULL; --- 66,72 ---- * relatively infrequently (only at backend startup or shutdown) and not for * very long, so a spinlock is okay. */ ! NON_EXEC_STATIC slock_t *ProcStructLock = NULL; static PROC_HDR *ProcGlobal = NULL; *************** *** 247,252 **** --- 247,253 ---- MyProc->waitLock = NULL; MyProc->waitHolder = NULL; SHMQueueInit(&(MyProc->procHolders)); + /* * Arrange to clean up at backend exit. Index: src/backend/tcop/postgres.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/backend/tcop/postgres.c,v retrieving revision 1.379 diff -c -w -r1.379 postgres.c *** src/backend/tcop/postgres.c 1 Dec 2003 22:15:37 -0000 1.379 --- src/backend/tcop/postgres.c 13 Dec 2003 06:18:44 -0000 *************** *** 68,73 **** --- 68,77 ---- extern int optind; extern char *optarg; + #ifdef EXEC_BACKEND + extern int BackendInit(Port*); + extern void read_backend_variables(pid_t, Port*); + #endif /* ---------------- * global variables *************** *** 2052,2058 **** * initialize globals (already done if under postmaster, but not if * standalone; cheap enough to do over) */ - MyProcPid = getpid(); /* --- 2056,2061 ---- *************** *** 2060,2066 **** * * If we are running under the postmaster, this is done already. */ ! if (!IsUnderPostmaster) MemoryContextInit(); set_ps_display("startup"); --- 2063,2069 ---- * * If we are running under the postmaster, this is done already. */ ! if (!IsUnderPostmaster /* when exec || ExecBackend */) MemoryContextInit(); set_ps_display("startup"); *************** *** 2133,2139 **** case 'D': /* PGDATA directory */ if (secure) potential_DataDir = optarg; - break; case 'd': /* debug level */ { --- 2136,2141 ---- *************** *** 2268,2274 **** break; case 'p': - /* * p - special flag passed if backend was forked by a * postmaster. --- 2270,2275 ---- *************** *** 2276,2298 **** 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); #else dbname = strdup(optarg); #endif secure = false; /* subsequent switches are NOT * secure */ ctx = PGC_BACKEND; --- 2277,2287 ---- if (secure) { #ifdef EXEC_BACKEND ! IsUnderPostmaster = true; #else dbname = strdup(optarg); #endif + secure = false; /* subsequent switches are NOT * secure */ ctx = PGC_BACKEND; *************** *** 2477,2483 **** SetConfigOption("log_statement_stats", "false", ctx, gucsource); } ! if (!IsUnderPostmaster) { if (!potential_DataDir) { --- 2466,2472 ---- SetConfigOption("log_statement_stats", "false", ctx, gucsource); } ! if (!IsUnderPostmaster || ExecBackend) { if (!potential_DataDir) { *************** *** 2497,2506 **** if (IsUnderPostmaster) { #ifdef EXEC_BACKEND read_nondefault_variables(); #endif ! } ! else ProcessConfigFile(PGC_POSTMASTER); /* --- 2486,2512 ---- 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 ProcessConfigFile(PGC_POSTMASTER); /* *************** *** 2517,2523 **** * 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 */ --- 2523,2528 ---- *************** *** 2565,2574 **** errmsg("invalid command-line arguments for server process"), errhint("Try \"%s --help\" for more information.", argv[0]))); } ! BaseInit(); ! #ifdef EXECBACKEND AttachSharedMemoryAndSemaphores(); #endif } else { --- 2570,2581 ---- errmsg("invalid command-line arguments for server process"), errhint("Try \"%s --help\" for more information.", argv[0]))); } ! #ifdef EXEC_BACKEND AttachSharedMemoryAndSemaphores(); #endif + XLOGPathInit(); + + BaseInit(); } else { *************** *** 2845,2851 **** --- 2852,2862 ---- if (got_SIGHUP) { got_SIGHUP = false; + #ifdef EXEC_BACKEND + read_nondefault_variables(); + #else ProcessConfigFile(PGC_SIGHUP); + #endif } /* *************** *** 3199,3202 **** pfree(str.data); } - --- 3210,3212 ---- Index: src/include/c.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/c.h,v retrieving revision 1.157 diff -c -w -r1.157 c.h *** src/include/c.h 29 Nov 2003 22:40:53 -0000 1.157 --- src/include/c.h 13 Dec 2003 06:18:45 -0000 *************** *** 793,798 **** --- 793,805 ---- #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" Index: src/include/access/xlogdefs.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/access/xlogdefs.h,v retrieving revision 1.10 diff -c -w -r1.10 xlogdefs.h *** src/include/access/xlogdefs.h 29 Nov 2003 22:40:55 -0000 1.10 --- src/include/access/xlogdefs.h 13 Dec 2003 06:18:46 -0000 *************** *** 33,38 **** --- 33,45 ---- 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 * Index: src/include/libpq/libpq-be.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/libpq/libpq-be.h,v retrieving revision 1.38 diff -c -w -r1.38 libpq-be.h *** src/include/libpq/libpq-be.h 29 Nov 2003 22:41:03 -0000 1.38 --- src/include/libpq/libpq-be.h 13 Dec 2003 06:18:46 -0000 *************** *** 27,32 **** --- 27,37 ---- #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,47 **** --- 47,53 ---- 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 Index: src/include/storage/fd.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/storage/fd.h,v retrieving revision 1.40 diff -c -w -r1.40 fd.h *** src/include/storage/fd.h 29 Nov 2003 22:41:13 -0000 1.40 --- src/include/storage/fd.h 13 Dec 2003 06:18:46 -0000 *************** *** 77,80 **** --- 77,84 ---- 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 */ Index: src/include/storage/ipc.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/storage/ipc.h,v retrieving revision 1.63 diff -c -w -r1.63 ipc.h *** src/include/storage/ipc.h 12 Dec 2003 18:45:10 -0000 1.63 --- src/include/storage/ipc.h 13 Dec 2003 06:18:46 -0000 *************** *** 32,37 **** --- 32,39 ---- extern void CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends, int port); + #ifdef EXEC_BACKEND extern void AttachSharedMemoryAndSemaphores(void); + #endif #endif /* IPC_H */ Index: src/include/storage/lock.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/storage/lock.h,v retrieving revision 1.75 diff -c -w -r1.75 lock.h *** src/include/storage/lock.h 1 Dec 2003 21:59:25 -0000 1.75 --- src/include/storage/lock.h 13 Dec 2003 06:18:46 -0000 *************** *** 86,93 **** */ typedef struct LockMethodData { - HTAB *lockHash; - HTAB *proclockHash; LOCKMETHODID lockmethodid; int numLockModes; LOCKMASK conflictTab[MAX_LOCKMODES]; --- 86,91 ---- Index: src/include/storage/lwlock.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/storage/lwlock.h,v retrieving revision 1.9 diff -c -w -r1.9 lwlock.h *** src/include/storage/lwlock.h 29 Nov 2003 22:41:13 -0000 1.9 --- src/include/storage/lwlock.h 13 Dec 2003 06:18:47 -0000 *************** *** 29,35 **** LockMgrLock, OidGenLock, XidGenLock, - ShmemIndexLock, SInvalLock, FreeSpaceLock, MMCacheLock, --- 29,34 ---- Index: src/include/storage/shmem.h =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/include/storage/shmem.h,v retrieving revision 1.40 diff -c -w -r1.40 shmem.h *** src/include/storage/shmem.h 29 Nov 2003 22:41:13 -0000 1.40 --- src/include/storage/shmem.h 13 Dec 2003 06:18:47 -0000 *************** *** 61,67 **** } SHM_QUEUE; /* shmem.c */ ! extern void InitShmemAllocation(void *seghdr); extern void *ShmemAlloc(Size size); extern bool ShmemIsValid(unsigned long addr); extern void InitShmemIndex(void); --- 61,67 ---- } SHM_QUEUE; /* shmem.c */ ! extern void InitShmemAllocation(void *seghdr, bool init); extern void *ShmemAlloc(Size size); extern bool ShmemIsValid(unsigned long addr); extern void InitShmemIndex(void);