This patch is the next step towards (re)allowing fork/exec.

Claudio Natoli
This commit is contained in:
Bruce Momjian 2003-12-20 17:31:21 +00:00
parent 1ee0ddf91d
commit d75b2ec4eb
23 changed files with 490 additions and 216 deletions

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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; * to update from XLogCtl->Insert.RedoRecPtr if we hold the info_lck;
* see GetRedoRecPtr. * see GetRedoRecPtr.
*/ */
static XLogRecPtr RedoRecPtr; NON_EXEC_STATIC XLogRecPtr RedoRecPtr;
/*---------- /*----------
* Shared-memory data structures for XLOG control * Shared-memory data structures for XLOG control
@ -231,12 +231,6 @@ typedef struct XLogwrtRqst
XLogRecPtr Flush; /* last byte + 1 to flush */ XLogRecPtr Flush; /* last byte + 1 to flush */
} XLogwrtRqst; } XLogwrtRqst;
typedef struct XLogwrtResult
{
XLogRecPtr Write; /* last byte + 1 written out */
XLogRecPtr Flush; /* last byte + 1 flushed */
} XLogwrtResult;
/* /*
* Shared state data for XLogInsert. * Shared state data for XLogInsert.
*/ */
@ -404,7 +398,7 @@ static char ControlFilePath[MAXPGPATH];
* Private, possibly out-of-date copy of shared LogwrtResult. * Private, possibly out-of-date copy of shared LogwrtResult.
* See discussion above. * 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. * openLogFile is -1 or a kernel FD for an open log file segment.
@ -2398,7 +2392,7 @@ XLOGShmemSize(void)
void void
XLOGShmemInit(void) XLOGShmemInit(void)
{ {
bool found; bool foundXLog, foundCFile;
/* this must agree with space requested by XLOGShmemSize() */ /* this must agree with space requested by XLOGShmemSize() */
if (XLOGbuffers < MinXLOGbuffers) if (XLOGbuffers < MinXLOGbuffers)
@ -2409,11 +2403,16 @@ XLOGShmemInit(void)
MAXALIGN(sizeof(XLogCtlData) + MAXALIGN(sizeof(XLogCtlData) +
sizeof(XLogRecPtr) * XLOGbuffers) sizeof(XLogRecPtr) * XLOGbuffers)
+ BLCKSZ * XLOGbuffers, + BLCKSZ * XLOGbuffers,
&found); &foundXLog);
Assert(!found);
ControlFile = (ControlFileData *) ControlFile = (ControlFileData *)
ShmemInitStruct("Control File", sizeof(ControlFileData), &found); ShmemInitStruct("Control File", sizeof(ControlFileData), &foundCFile);
Assert(!found);
if (foundXLog || foundCFile)
{
/* both should be present or neither */
Assert(foundXLog && foundCFile);
return;
}
memset(XLogCtl, 0, sizeof(XLogCtlData)); memset(XLogCtl, 0, sizeof(XLogCtlData));

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) if (!dbname || argc != optind)
usage(); usage();
#ifdef EXEC_BACKEND
if (IsUnderPostmaster && ExecBackend && MyProc /* ordinary backend */ ) if (IsUnderPostmaster && MyProc /* ordinary backend */ )
AttachSharedMemoryAndSemaphores(); AttachSharedMemoryAndSemaphores();
#endif
if (!IsUnderPostmaster /* when exec || ExecBackend */ ) if (!IsUnderPostmaster /* when exec || ExecBackend */ )
{ {

View File

@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2003, PostgreSQL Global Development Group * 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" #include "postgres.h"
@ -71,7 +71,7 @@ bool pgstat_is_running = false;
* Local data * Local data
* ---------- * ----------
*/ */
static int pgStatSock = -1; NON_EXEC_STATIC int pgStatSock = -1;
static int pgStatPipe[2]; static int pgStatPipe[2];
static struct sockaddr_storage pgStatAddr; static struct sockaddr_storage pgStatAddr;
static int pgStatPmPipe[2] = {-1, -1}; static int pgStatPmPipe[2] = {-1, -1};

View File

@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* *
@ -273,6 +273,7 @@ static void dummy_handler(SIGNAL_ARGS);
static void CleanupProc(int pid, int exitstatus); static void CleanupProc(int pid, int exitstatus);
static void LogChildExit(int lev, const char *procname, static void LogChildExit(int lev, const char *procname,
int pid, int exitstatus); int pid, int exitstatus);
NON_EXEC_STATIC bool BackendInit(Port *port);
static int BackendFork(Port *port); static int BackendFork(Port *port);
static void ExitPostmaster(int status); static void ExitPostmaster(int status);
static void usage(const char *); static void usage(const char *);
@ -282,10 +283,6 @@ static int ProcessStartupPacket(Port *port, bool SSLdone);
static void processCancelRequest(Port *port, void *pkt); static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask); static int initMasks(fd_set *rmask);
static void report_fork_failure_to_client(Port *port, int errnum); 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 enum CAC_state canAcceptConnections(void);
static long PostmasterRandom(void); static long PostmasterRandom(void);
static void RandomSalt(char *cryptSalt, char *md5Salt); 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. */ /* This lets gcc check the format string for consistency. */
__attribute__((format(printf, 1, 2))); __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 StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT) #define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
#define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER) #define StartBackgroundWriter() SSDataBase(BS_XLOG_BGWRITER)
@ -1185,7 +1187,6 @@ initMasks(fd_set *rmask)
static int static int
ProcessStartupPacket(Port *port, bool SSLdone) ProcessStartupPacket(Port *port, bool SSLdone)
{ {
enum CAC_state cac;
int32 len; int32 len;
void *buf; void *buf;
ProtocolVersion proto; ProtocolVersion proto;
@ -1244,7 +1245,11 @@ ProcessStartupPacket(Port *port, bool SSLdone)
if (proto == CANCEL_REQUEST_CODE) if (proto == CANCEL_REQUEST_CODE)
{ {
#ifdef EXEC_BACKEND
abort(); /* FIXME: [fork/exec] Whoops. Not handled... yet */
#else
processCancelRequest(port, buf); processCancelRequest(port, buf);
#endif
return 127; /* XXX */ return 127; /* XXX */
} }
@ -1435,9 +1440,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
* so now instead of wasting cycles on an authentication exchange. * so now instead of wasting cycles on an authentication exchange.
* (This also allows a pg_ping utility to be written.) * (This also allows a pg_ping utility to be written.)
*/ */
cac = canAcceptConnections(); switch (port->canAcceptConnections)
switch (cac)
{ {
case CAC_STARTUP: case CAC_STARTUP:
ereport(FATAL, ereport(FATAL,
@ -1499,8 +1502,10 @@ processCancelRequest(Port *port, void *pkt)
backendPID))); backendPID)));
return; return;
} }
else if (ExecBackend) #ifdef EXEC_BACKEND
else
AttachSharedMemoryAndSemaphores(); AttachSharedMemoryAndSemaphores();
#endif
/* See if we have a matching backend */ /* 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 * BackendInit/Fork -- perform authentication [BackendInit], and if successful,
* backend's argument list and invoke backend main(). * set up the backend's argument list [BackendFork] and invoke
* * backend main() [or exec in EXEC_BACKEND case]
* This used to perform an execv() but we no longer exec the backend;
* it's the same executable as the postmaster.
* *
* returns: * returns:
* Shouldn't return at all. * Shouldn't return at all.
* If PostgresMain() fails, return status. * If PostgresMain() fails, return status.
*/ */
static int NON_EXEC_STATIC bool
BackendFork(Port *port) 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; int status;
struct timeval now; struct timeval now;
struct timezone tz; struct timezone tz;
char remote_host[NI_MAXHOST]; char remote_host[NI_MAXHOST];
char remote_port[NI_MAXSERV]; char remote_port[NI_MAXSERV];
/*
* Let's clean up ourselves as the postmaster child
*/
IsUnderPostmaster = true; /* we are a postmaster subprocess now */ IsUnderPostmaster = true; /* we are a postmaster subprocess now */
ClientAuthInProgress = true; /* limit visibility of log messages */ ClientAuthInProgress = true; /* limit visibility of log messages */
@ -2386,9 +2376,6 @@ BackendFork(Port *port)
* Signal handlers setting is moved to tcop/postgres... * Signal handlers setting is moved to tcop/postgres...
*/ */
/* Close the postmaster's other sockets */
ClosePostmasterPorts(true);
/* Save port etc. for ps status */ /* Save port etc. for ps status */
MyProcPort = port; MyProcPort = port;
@ -2444,16 +2431,6 @@ BackendFork(Port *port)
StrNCpy(remote_host, tmphost, sizeof(remote_host)); 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) * 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 * 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); status = ProcessStartupPacket(port, false);
if (status != STATUS_OK) 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 * Now that we have the user and database name, we can set the process
@ -2506,6 +2483,50 @@ BackendFork(Port *port)
gettimeofday(&now, &tz); gettimeofday(&now, &tz);
srandom((unsigned int) now.tv_usec); 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. * 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 * Pass any backend switches specified with -o in the postmaster's own
* command line. We assume these are secure. (It's OK to mangle * command line. We assume these are secure.
* ExtraOptions since we are now in the child process; this won't * [Note: now makes a copy to protect against future fork/exec changes]
* change the postmaster's copy.)
*/ */
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. */ /* Tell the backend what protocol the frontend is using. */
snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto); snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto);
av[ac++] = protobuf; av[ac++] = protobuf;
#endif
/* /*
* Tell the backend it is being called from the postmaster, and which * Tell the backend it is being called from the postmaster, and which
* database to use. -p marks the end of secure switches. * database to use. -p marks the end of secure switches.
*/ */
av[ac++] = "-p";
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
Assert(UsedShmemSegID != 0 && UsedShmemSegAddr != NULL); write_backend_variables(getpid(),port);
/* database name at the end because it might contain commas */
snprintf(pbuf, sizeof(pbuf), "%d,%d,%lu,%p,%s", /* pass data dir before end of secure switches (-p) */
port->sock, canAcceptConnections(), av[ac++] = "-D";
UsedShmemSegID, UsedShmemSegAddr, av[ac++] = DataDir;
port->database_name);
av[ac++] = pbuf; /*
* 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 #else
av[ac++] = "-p";
av[ac++] = port->database_name; av[ac++] = port->database_name;
#endif #endif
@ -2571,6 +2600,10 @@ BackendFork(Port *port)
* Pass the (insecure) option switches from the connection request. * Pass the (insecure) option switches from the connection request.
* (It's OK to mangle port->cmdline_options now.) * (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) if (port->cmdline_options)
split_opts(av, &ac, port->cmdline_options); split_opts(av, &ac, port->cmdline_options);
@ -2594,17 +2627,21 @@ BackendFork(Port *port)
*/ */
ereport(DEBUG3, ereport(DEBUG3,
(errmsg_internal("%s child[%d]: starting with (", (errmsg_internal("%s child[%d]: starting with (",
progname, MyProcPid))); progname, getpid())));
for (i = 0; i < ac; ++i) for (i = 0; i < ac; ++i)
ereport(DEBUG3, ereport(DEBUG3,
(errmsg_internal("\t%s", av[i]))); (errmsg_internal("\t%s", av[i])));
ereport(DEBUG3, ereport(DEBUG3,
(errmsg_internal(")"))); (errmsg_internal(")")));
#ifdef EXEC_BACKEND
return execv(pg_pathname,av);
#else
ClientAuthInProgress = false; /* client_min_messages is active ClientAuthInProgress = false; /* client_min_messages is active
* now */ * now */
return (PostgresMain(ac, av, port->user_name)); return (PostgresMain(ac, av, port->user_name));
#endif
} }
/* /*
@ -3051,3 +3088,136 @@ postmaster_error(const char *fmt,...)
va_end(ap); va_end(ap);
fprintf(stderr, "\n"); 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

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * anyone else attached to the shmem at this point, we've got
* problems. * problems.
*/ */
#ifndef EXEC_BACKEND
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
#endif
BufferDescriptors = (BufferDesc *) BufferDescriptors = (BufferDesc *)
ShmemInitStruct("Buffer Descriptors", ShmemInitStruct("Buffer Descriptors",
@ -177,7 +179,9 @@ InitBufferPool(void)
/* Init other shared buffer-management stuff */ /* Init other shared buffer-management stuff */
StrategyInitialize(!foundDescs); StrategyInitialize(!foundDescs);
#ifndef EXEC_BACKEND
LWLockRelease(BufMgrLock); LWLockRelease(BufMgrLock);
#endif
} }
/* /*

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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: * NOTES:
* *
@ -53,11 +53,6 @@
#include "storage/ipc.h" #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. * Problem: Postgres does a system(ld...) to do dynamic loading.
* This will open several extra files in addition to those used by * 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) while ((db_de = readdir(db_dir)) != NULL)
{ {
if (strcmp(db_de->d_name, ".") == 0 || if (strcmp(db_de->d_name, ".") == 0
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; continue;
snprintf(temp_path, sizeof(temp_path), snprintf(temp_path, sizeof(temp_path),

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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: * NOTES:
@ -180,7 +180,6 @@ typedef struct FSMRelation FSMRelation;
/* Header for whole map */ /* Header for whole map */
struct FSMHeader struct FSMHeader
{ {
HTAB *relHash; /* hashtable of FSMRelation entries */
FSMRelation *usageList; /* FSMRelations in usage-recency order */ FSMRelation *usageList; /* FSMRelations in usage-recency order */
FSMRelation *usageListTail; /* tail of usage-recency list */ FSMRelation *usageListTail; /* tail of usage-recency list */
FSMRelation *firstRel; /* FSMRelations in arena storage order */ FSMRelation *firstRel; /* FSMRelations in arena storage order */
@ -218,6 +217,7 @@ int MaxFSMRelations; /* these are set by guc.c */
int MaxFSMPages; int MaxFSMPages;
static FSMHeader *FreeSpaceMap; /* points to FSMHeader in shared memory */ 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); static FSMRelation *lookup_fsm_rel(RelFileNode *rel);
@ -265,13 +265,15 @@ InitFreeSpaceMap(void)
{ {
HASHCTL info; HASHCTL info;
int nchunks; int nchunks;
bool found;
/* Create table header */ /* Create table header */
FreeSpaceMap = (FSMHeader *) ShmemAlloc(sizeof(FSMHeader)); FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header",sizeof(FSMHeader),&found);
if (FreeSpaceMap == NULL) if (FreeSpaceMap == NULL)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY), (errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("insufficient shared memory for free space map"))); errmsg("insufficient shared memory for free space map")));
if (!found)
MemSet(FreeSpaceMap, 0, sizeof(FSMHeader)); MemSet(FreeSpaceMap, 0, sizeof(FSMHeader));
/* Create hashtable for FSMRelations */ /* Create hashtable for FSMRelations */
@ -279,17 +281,21 @@ InitFreeSpaceMap(void)
info.entrysize = sizeof(FSMRelation); info.entrysize = sizeof(FSMRelation);
info.hash = tag_hash; info.hash = tag_hash;
FreeSpaceMap->relHash = ShmemInitHash("Free Space Map Hash", FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash",
MaxFSMRelations / 10, MaxFSMRelations / 10,
MaxFSMRelations, MaxFSMRelations,
&info, &info,
(HASH_ELEM | HASH_FUNCTION)); (HASH_ELEM | HASH_FUNCTION));
if (!FreeSpaceMap->relHash) if (!FreeSpaceMapRelHash)
ereport(FATAL, ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY), (errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("insufficient shared memory for free space map"))); errmsg("insufficient shared memory for free space map")));
if (found)
return;
/* Allocate page-storage arena */ /* Allocate page-storage arena */
nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1; nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
/* This check ensures spareChunks will be greater than zero */ /* This check ensures spareChunks will be greater than zero */
@ -974,7 +980,7 @@ lookup_fsm_rel(RelFileNode *rel)
{ {
FSMRelation *fsmrel; FSMRelation *fsmrel;
fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash, fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash,
(void *) rel, (void *) rel,
HASH_FIND, HASH_FIND,
NULL); NULL);
@ -995,7 +1001,7 @@ create_fsm_rel(RelFileNode *rel)
FSMRelation *fsmrel; FSMRelation *fsmrel;
bool found; bool found;
fsmrel = (FSMRelation *) hash_search(FreeSpaceMap->relHash, fsmrel = (FSMRelation *) hash_search(FreeSpaceMapRelHash,
(void *) rel, (void *) rel,
HASH_ENTER, HASH_ENTER,
&found); &found);
@ -1050,7 +1056,7 @@ delete_fsm_rel(FSMRelation *fsmrel)
unlink_fsm_rel_usage(fsmrel); unlink_fsm_rel_usage(fsmrel);
unlink_fsm_rel_storage(fsmrel); unlink_fsm_rel_storage(fsmrel);
FreeSpaceMap->numRels--; FreeSpaceMap->numRels--;
result = (FSMRelation *) hash_search(FreeSpaceMap->relHash, result = (FSMRelation *) hash_search(FreeSpaceMapRelHash,
(void *) &(fsmrel->key), (void *) &(fsmrel->key),
HASH_REMOVE, HASH_REMOVE,
NULL); NULL);

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * Set up shared memory allocation mechanism
*/ */
InitShmemAllocation(seghdr); InitShmemAllocation(seghdr, true);
/* /*
* Now initialize LWLocks, which do shared memory allocation and are * Now initialize LWLocks, which do shared memory allocation and are
@ -135,12 +135,36 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
} }
#ifdef EXEC_BACKEND
/* /*
* AttachSharedMemoryAndSemaphores * AttachSharedMemoryAndSemaphores
* Attaches to the existing shared resources. * Attaches to the existing shared resources.
*/ */
/* FIXME: [fork/exec] This function is starting to look pretty much like
CreateSharedMemoryAndSemaphores. Refactor? */
void void
AttachSharedMemoryAndSemaphores(void) AttachSharedMemoryAndSemaphores(void)
{ {
PGShmemHeader *seghdr = PGSharedMemoryCreate(-1,false,-1);
InitShmemAllocation(seghdr, false);
InitShmemIndex();
XLOGShmemInit();
CLOGShmemInit(); CLOGShmemInit();
InitBufferPool();
InitLocks();
InitLockTable(MaxBackends);
InitProcGlobal(MaxBackends);
CreateSharedInvalidationState(MaxBackends);
InitFreeSpaceMap();
PMSignalInit();
} }
#endif

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 void
PMSignalInit(void) PMSignalInit(void)
{ {
bool found;
PMSignalFlags = (sig_atomic_t *) 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)); MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t));
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 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 */ 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. * but we use void to avoid having to include ipc.h in shmem.h.
*/ */
void void
InitShmemAllocation(void *seghdr) InitShmemAllocation(void *seghdr, bool init)
{ {
PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr; PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr;
@ -97,26 +101,34 @@ InitShmemAllocation(void *seghdr)
ShmemBase = (SHMEM_OFFSET) shmhdr; ShmemBase = (SHMEM_OFFSET) shmhdr;
ShmemEnd = ShmemBase + shmhdr->totalsize; ShmemEnd = ShmemBase + shmhdr->totalsize;
/* if (init)
* Initialize the spinlock used by ShmemAlloc. We have to do the {
* space allocation the hard way, since ShmemAlloc can't be called /*
* yet. * Initialize the spinlocks used by ShmemAlloc/ShmemInitStruct. We
*/ * have to do the space allocation the hard way, since ShmemAlloc
ShmemLock = (slock_t *) (((char *) shmhdr) + shmhdr->freeoffset); * can't be called yet.
shmhdr->freeoffset += MAXALIGN(sizeof(slock_t)); */
Assert(shmhdr->freeoffset <= shmhdr->totalsize); 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) */ SpinLockInit(ShmemLock);
ShmemIndex = (HTAB *) NULL; SpinLockInit(ShmemIndexLock);
/* /* ShmemIndex can't be set up yet (need LWLocks first) */
* Initialize ShmemVariableCache for transaction manager. ShmemIndex = (HTAB *) NULL;
*/
ShmemVariableCache = (VariableCache) /*
* Initialize ShmemVariableCache for transaction manager.
*/
ShmemVariableCache = (VariableCache)
ShmemAlloc(sizeof(*ShmemVariableCache)); 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. * Now, create an entry in the hashtable for the index itself.
*/ */
MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE); if (!IsUnderPostmaster)
strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE); {
MemSet(item.key, 0, SHMEM_INDEX_KEYSIZE);
result = (ShmemIndexEnt *) strncpy(item.key, "ShmemIndex", SHMEM_INDEX_KEYSIZE);
hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found);
if (!result) result = (ShmemIndexEnt *)
ereport(FATAL, hash_search(ShmemIndex, (void *) &item, HASH_ENTER, &found);
(errcode(ERRCODE_OUT_OF_MEMORY), if (!result)
errmsg("out of shared memory"))); ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
Assert(ShmemBootstrap && !found); errmsg("out of shared memory")));
result->location = MAKE_OFFSET(ShmemIndex->hctl); Assert(ShmemBootstrap && !found);
result->size = SHMEM_INDEX_SIZE;
result->location = MAKE_OFFSET(ShmemIndex->hctl);
ShmemBootstrap = false; result->size = SHMEM_INDEX_SIZE;
ShmemBootstrap = false;
}
/* now release the lock acquired in ShmemInitStruct */ /* 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); strncpy(item.key, name, SHMEM_INDEX_KEYSIZE);
item.location = BAD_LOCATION; item.location = BAD_LOCATION;
LWLockAcquire(ShmemIndexLock, LW_EXCLUSIVE); SpinLockAcquire(ShmemIndexLock);
if (!ShmemIndex) if (!ShmemIndex)
{ {
/* if (IsUnderPostmaster)
* If the shmem index doesn't exist, we are bootstrapping: we must {
* be trying to init the shmem index itself. /* Must be initializing a (non-standalone) backend */
* Assert(strcmp(name, "ShmemIndex") == 0);
* Notice that the ShmemIndexLock is held until the shmem index has Assert(ShmemBootstrap);
* been completely initialized. Assert(ShmemIndexAlloc);
*/ *foundPtr = TRUE;
Assert(strcmp(name, "ShmemIndex") == 0); }
Assert(ShmemBootstrap); else
*foundPtr = FALSE; {
return ShmemAlloc(size); /*
* 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 */ /* look it up in the shmem index */
@ -343,7 +370,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
if (!result) if (!result)
{ {
LWLockRelease(ShmemIndexLock); SpinLockRelease(ShmemIndexLock);
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY), (errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory"))); errmsg("out of shared memory")));
@ -359,7 +386,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
*/ */
if (result->size != size) if (result->size != size)
{ {
LWLockRelease(ShmemIndexLock); SpinLockRelease(ShmemIndexLock);
elog(WARNING, "ShmemIndex entry size is wrong"); elog(WARNING, "ShmemIndex entry size is wrong");
/* let caller print its message too */ /* let caller print its message too */
@ -376,7 +403,7 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
/* out of memory */ /* out of memory */
Assert(ShmemIndex); Assert(ShmemIndex);
hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL); hash_search(ShmemIndex, (void *) &item, HASH_REMOVE, NULL);
LWLockRelease(ShmemIndexLock); SpinLockRelease(ShmemIndexLock);
ereport(WARNING, ereport(WARNING,
(errcode(ERRCODE_OUT_OF_MEMORY), (errcode(ERRCODE_OUT_OF_MEMORY),
@ -389,6 +416,6 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
} }
Assert(ShmemIsValid((unsigned long) structPtr)); Assert(ShmemIsValid((unsigned long) structPtr));
LWLockRelease(ShmemIndexLock); SpinLockRelease(ShmemIndexLock);
return structPtr; return structPtr;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; int segSize;
SISeg *segP; SISeg *segP;
int i; int i;
bool found;
/* Allocate space in shared memory */ /* Allocate space in shared memory */
segSize = SInvalShmemSize(maxBackends); 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 */ /* Clear message counters, save size of procState array */
segP->minMsgNum = 0; segP->minMsgNum = 0;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Outside modules can create a lock table and acquire/release * 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 * map from lock method id to the lock table structure
*/ */
static LockMethod LockMethods[MAX_LOCK_METHODS]; static LockMethod LockMethods[MAX_LOCK_METHODS];
static HTAB* LockMethodLockHash[MAX_LOCK_METHODS];
static HTAB* LockMethodProcLockHash[MAX_LOCK_METHODS];
static int NumLockMethods; static int NumLockMethods;
/* /*
* InitLocks -- Init the lock module. Create a private data * InitLocks -- Init the lock module. Create a private data
* structure for constructing conflict masks. * structure for constructing conflict masks.
@ -245,8 +247,9 @@ LockMethodTableInit(char *tabName,
/* /*
* Lock the LWLock for the table (probably not necessary here) * Lock the LWLock for the table (probably not necessary here)
*/ */
#ifndef EXEC_BACKEND
LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
#endif
/* /*
* no zero-th table * no zero-th table
*/ */
@ -279,15 +282,15 @@ LockMethodTableInit(char *tabName,
hash_flags = (HASH_ELEM | HASH_FUNCTION); hash_flags = (HASH_ELEM | HASH_FUNCTION);
sprintf(shmemName, "%s (lock hash)", tabName); sprintf(shmemName, "%s (lock hash)", tabName);
newLockMethod->lockHash = ShmemInitHash(shmemName, LockMethodLockHash[NumLockMethods-1] = ShmemInitHash(shmemName,
init_table_size, init_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); hash_flags);
if (!newLockMethod->lockHash) if (!LockMethodLockHash[NumLockMethods-1])
elog(FATAL, "could not initialize lock table \"%s\"", tabName); 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 * 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); hash_flags = (HASH_ELEM | HASH_FUNCTION);
sprintf(shmemName, "%s (proclock hash)", tabName); sprintf(shmemName, "%s (proclock hash)", tabName);
newLockMethod->proclockHash = ShmemInitHash(shmemName, LockMethodProcLockHash[NumLockMethods-1] = ShmemInitHash(shmemName,
init_table_size, init_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); hash_flags);
if (!newLockMethod->proclockHash) if (!LockMethodProcLockHash[NumLockMethods-1])
elog(FATAL, "could not initialize lock table \"%s\"", tabName); elog(FATAL, "could not initialize lock table \"%s\"", tabName);
/* init data structures */ /* init data structures */
LockMethodInit(newLockMethod, conflictsP, numModes); LockMethodInit(newLockMethod, conflictsP, numModes);
#ifndef EXEC_BACKEND
LWLockRelease(LockMgrLock); LWLockRelease(LockMgrLock);
#endif
pfree(shmemName); pfree(shmemName);
return newLockMethod->lockmethodid; return newLockMethod->lockmethodid;
@ -449,8 +453,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
/* /*
* Find or create a lock with this tag * Find or create a lock with this tag
*/ */
Assert(lockMethodTable->lockHash->hash == tag_hash); Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
lock = (LOCK *) hash_search(lockMethodTable->lockHash, lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
(void *) locktag, (void *) locktag,
HASH_ENTER, &found); HASH_ENTER, &found);
if (!lock) if (!lock)
@ -497,7 +501,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
/* /*
* Find or create a proclock entry with this tag * Find or create a proclock entry with this tag
*/ */
proclockTable = lockMethodTable->proclockHash; proclockTable = LockMethodProcLockHash[lockmethodid];
proclock = (PROCLOCK *) hash_search(proclockTable, proclock = (PROCLOCK *) hash_search(proclockTable,
(void *) &proclocktag, (void *) &proclocktag,
HASH_ENTER, &found); HASH_ENTER, &found);
@ -988,8 +992,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
/* /*
* Find a lock with this tag * Find a lock with this tag
*/ */
Assert(lockMethodTable->lockHash->hash == tag_hash); Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
lock = (LOCK *) hash_search(lockMethodTable->lockHash, lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
(void *) locktag, (void *) locktag,
HASH_FIND, NULL); HASH_FIND, NULL);
@ -1014,7 +1018,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
proclocktag.proc = MAKE_OFFSET(MyProc); proclocktag.proc = MAKE_OFFSET(MyProc);
TransactionIdStore(xid, &proclocktag.xid); TransactionIdStore(xid, &proclocktag.xid);
proclockTable = lockMethodTable->proclockHash; proclockTable = LockMethodProcLockHash[lockmethodid];
proclock = (PROCLOCK *) hash_search(proclockTable, proclock = (PROCLOCK *) hash_search(proclockTable,
(void *) &proclocktag, (void *) &proclocktag,
HASH_FIND_SAVE, NULL); 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 * if there's no one waiting in the queue, we just released the
* last lock on this object. Delete it from the lock table. * last lock on this object. Delete it from the lock table.
*/ */
Assert(lockMethodTable->lockHash->hash == tag_hash); Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
lock = (LOCK *) hash_search(lockMethodTable->lockHash, lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
(void *) &(lock->tag), (void *) &(lock->tag),
HASH_REMOVE, HASH_REMOVE,
NULL); NULL);
@ -1269,7 +1273,7 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc,
/* /*
* remove the proclock entry from the hashtable * remove the proclock entry from the hashtable
*/ */
proclock = (PROCLOCK *) hash_search(lockMethodTable->proclockHash, proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid],
(void *) proclock, (void *) proclock,
HASH_REMOVE, HASH_REMOVE,
NULL); NULL);
@ -1287,8 +1291,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc,
* lock object. * lock object.
*/ */
LOCK_PRINT("LockReleaseAll: deleting", lock, 0); LOCK_PRINT("LockReleaseAll: deleting", lock, 0);
Assert(lockMethodTable->lockHash->hash == tag_hash); Assert(LockMethodLockHash[lockmethodid]->hash == tag_hash);
lock = (LOCK *) hash_search(lockMethodTable->lockHash, lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
(void *) &(lock->tag), (void *) &(lock->tag),
HASH_REMOVE, NULL); HASH_REMOVE, NULL);
if (!lock) if (!lock)
@ -1367,7 +1371,7 @@ GetLockStatusData(void)
LWLockAcquire(LockMgrLock, LW_EXCLUSIVE); LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
proclockTable = LockMethods[DEFAULT_LOCKMETHOD]->proclockHash; proclockTable = LockMethodProcLockHash[DEFAULT_LOCKMETHOD];
data->nelements = i = proclockTable->hctl->nentries; data->nelements = i = proclockTable->hctl->nentries;
@ -1480,7 +1484,7 @@ DumpAllLocks(void)
if (!lockMethodTable) if (!lockMethodTable)
return; return;
proclockTable = lockMethodTable->proclockHash; proclockTable = LockMethodProcLockHash[lockmethodid];
if (proc->waitLock) if (proc->waitLock)
LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0); LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0);

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 pointer by fork from the postmaster. LWLockIds are indexes into
* the array. * the array.
*/ */
static LWLock *LWLockArray = NULL; NON_EXEC_STATIC LWLock *LWLockArray = NULL;
/* shared counter for dynamic allocation of LWLockIds */ /* shared counter for dynamic allocation of LWLockIds */
static int *LWLockCounter; static int *LWLockCounter;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * relatively infrequently (only at backend startup or shutdown) and not for
* very long, so a spinlock is okay. * very long, so a spinlock is okay.
*/ */
static slock_t *ProcStructLock = NULL; NON_EXEC_STATIC slock_t *ProcStructLock = NULL;
static PROC_HDR *ProcGlobal = NULL; static PROC_HDR *ProcGlobal = NULL;
@ -248,6 +248,7 @@ InitProcess(void)
MyProc->waitHolder = NULL; MyProc->waitHolder = NULL;
SHMQueueInit(&(MyProc->procHolders)); SHMQueueInit(&(MyProc->procHolders));
/* /*
* Arrange to clean up at backend exit. * Arrange to clean up at backend exit.
*/ */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
@ -68,6 +68,10 @@
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
#ifdef EXEC_BACKEND
extern bool BackendInit(Port*);
extern void read_backend_variables(pid_t, Port*);
#endif
/* ---------------- /* ----------------
* global variables * global variables
@ -2052,7 +2056,6 @@ PostgresMain(int argc, char *argv[], const char *username)
* initialize globals (already done if under postmaster, but not if * initialize globals (already done if under postmaster, but not if
* standalone; cheap enough to do over) * standalone; cheap enough to do over)
*/ */
MyProcPid = getpid(); 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 we are running under the postmaster, this is done already.
*/ */
if (!IsUnderPostmaster) if (!IsUnderPostmaster /* when exec || ExecBackend */)
MemoryContextInit(); MemoryContextInit();
set_ps_display("startup"); set_ps_display("startup");
@ -2268,7 +2271,6 @@ PostgresMain(int argc, char *argv[], const char *username)
break; break;
case 'p': case 'p':
/* /*
* p - special flag passed if backend was forked by a * p - special flag passed if backend was forked by a
* postmaster. * postmaster.
@ -2276,23 +2278,11 @@ PostgresMain(int argc, char *argv[], const char *username)
if (secure) if (secure)
{ {
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
char *p; IsUnderPostmaster = true;
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 #else
dbname = strdup(optarg); dbname = strdup(optarg);
#endif #endif
secure = false; /* subsequent switches are NOT secure = false; /* subsequent switches are NOT
* secure */ * secure */
ctx = PGC_BACKEND; ctx = PGC_BACKEND;
@ -2477,7 +2467,7 @@ PostgresMain(int argc, char *argv[], const char *username)
SetConfigOption("log_statement_stats", "false", ctx, gucsource); SetConfigOption("log_statement_stats", "false", ctx, gucsource);
} }
if (!IsUnderPostmaster) if (!IsUnderPostmaster || ExecBackend)
{ {
if (!potential_DataDir) if (!potential_DataDir)
{ {
@ -2497,10 +2487,27 @@ PostgresMain(int argc, char *argv[], const char *username)
if (IsUnderPostmaster) if (IsUnderPostmaster)
{ {
#ifdef EXEC_BACKEND #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_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 #endif
} } else
else
ProcessConfigFile(PGC_POSTMASTER); 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, * course, this isn't an issue for signals that are locally generated,
* such as SIGALRM and SIGPIPE.) * such as SIGALRM and SIGPIPE.)
*/ */
pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */ pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */
pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */ pqsignal(SIGINT, StatementCancelHandler); /* cancel current query */
pqsignal(SIGTERM, die); /* cancel current query and exit */ 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"), errmsg("invalid command-line arguments for server process"),
errhint("Try \"%s --help\" for more information.", argv[0]))); errhint("Try \"%s --help\" for more information.", argv[0])));
} }
BaseInit(); #ifdef EXEC_BACKEND
#ifdef EXECBACKEND
AttachSharedMemoryAndSemaphores(); AttachSharedMemoryAndSemaphores();
#endif #endif
XLOGPathInit();
BaseInit();
} }
else else
{ {
@ -2845,7 +2853,11 @@ PostgresMain(int argc, char *argv[], const char *username)
if (got_SIGHUP) if (got_SIGHUP)
{ {
got_SIGHUP = false; got_SIGHUP = false;
#ifdef EXEC_BACKEND
read_nondefault_variables();
#else
ProcessConfigFile(PGC_SIGHUP); ProcessConfigFile(PGC_SIGHUP);
#endif
} }
/* /*
@ -3199,4 +3211,3 @@ ShowUsage(const char *title)
pfree(str.data); pfree(str.data);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #ifndef XLOG_DEFS_H
#define XLOG_DEFS_H #define XLOG_DEFS_H
@ -33,6 +33,13 @@ typedef struct XLogRecPtr
uint32 xrecoff; /* byte offset of location in log file */ uint32 xrecoff; /* byte offset of location in log file */
} XLogRecPtr; } XLogRecPtr;
typedef struct XLogwrtResult
{
XLogRecPtr Write; /* last byte + 1 written out */
XLogRecPtr Flush; /* last byte + 1 flushed */
} XLogwrtResult;
/* /*
* Macros for comparing XLogRecPtrs * Macros for comparing XLogRecPtrs
* *

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #define HAVE_STRTOULL 1
#endif #endif
/* EXEC_BACKEND defines */
#ifdef EXEC_BACKEND
#define NON_EXEC_STATIC
#else
#define NON_EXEC_STATIC static
#endif
/* /port compatibility functions */ /* /port compatibility functions */
#include "port.h" #include "port.h"

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 #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 * This is used by the postmaster in its communication with frontends. It
* contains all state information needed during this communication before the * contains all state information needed during this communication before the
@ -42,6 +47,7 @@ typedef struct Port
ProtocolVersion proto; /* FE/BE protocol version */ ProtocolVersion proto; /* FE/BE protocol version */
SockAddr laddr; /* local addr (postmaster) */ SockAddr laddr; /* local addr (postmaster) */
SockAddr raddr; /* remote addr (client) */ SockAddr raddr; /* remote addr (client) */
CAC_state canAcceptConnections; /* postmaster connection status */
/* /*
* Information that needs to be saved from the startup packet and * Information that needs to be saved from the startup packet and

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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_fsync(int fd);
extern int pg_fdatasync(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 */ #endif /* FD_H */

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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, extern void CreateSharedMemoryAndSemaphores(bool makePrivate,
int maxBackends, int maxBackends,
int port); int port);
#ifdef EXEC_BACKEND
extern void AttachSharedMemoryAndSemaphores(void); extern void AttachSharedMemoryAndSemaphores(void);
#endif
#endif /* IPC_H */ #endif /* IPC_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 typedef struct LockMethodData
{ {
HTAB *lockHash;
HTAB *proclockHash;
LOCKMETHODID lockmethodid; LOCKMETHODID lockmethodid;
int numLockModes; int numLockModes;
LOCKMASK conflictTab[MAX_LOCKMODES]; LOCKMASK conflictTab[MAX_LOCKMODES];

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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, LockMgrLock,
OidGenLock, OidGenLock,
XidGenLock, XidGenLock,
ShmemIndexLock,
SInvalLock, SInvalLock,
FreeSpaceLock, FreeSpaceLock,
MMCacheLock, MMCacheLock,

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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; } SHM_QUEUE;
/* shmem.c */ /* shmem.c */
extern void InitShmemAllocation(void *seghdr); extern void InitShmemAllocation(void *seghdr, bool init);
extern void *ShmemAlloc(Size size); extern void *ShmemAlloc(Size size);
extern bool ShmemIsValid(unsigned long addr); extern bool ShmemIsValid(unsigned long addr);
extern void InitShmemIndex(void); extern void InitShmemIndex(void);