1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-28 18:48:04 +03:00

Pgindent run for 8.0.

This commit is contained in:
Bruce Momjian
2004-08-29 05:07:03 +00:00
parent 90cb9c3051
commit b6b71b85bc
527 changed files with 20550 additions and 18283 deletions

View File

@@ -6,11 +6,11 @@
* to keep regular backends from having to write out dirty shared buffers
* (which they would only do when needing to free a shared buffer to read in
* another page). In the best scenario all writes from shared buffers will
* be issued by the background writer process. However, regular backends are
* be issued by the background writer process. However, regular backends are
* still empowered to issue writes if the bgwriter fails to maintain enough
* clean shared buffers.
*
* The bgwriter is also charged with handling all checkpoints. It will
* The bgwriter is also charged with handling all checkpoints. It will
* automatically dispatch a checkpoint after a certain amount of time has
* elapsed since the last one, and it can be signaled to perform requested
* checkpoints as well. (The GUC parameter that mandates a checkpoint every
@@ -21,7 +21,7 @@
* The bgwriter is started by the postmaster as soon as the startup subprocess
* finishes. It remains alive until the postmaster commands it to terminate.
* Normal termination is by SIGUSR2, which instructs the bgwriter to execute
* a shutdown checkpoint and then exit(0). (All backends must be stopped
* a shutdown checkpoint and then exit(0). (All backends must be stopped
* before SIGUSR2 is issued!) Emergency termination is by SIGQUIT; like any
* backend, the bgwriter will simply abort and exit on SIGQUIT.
*
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.7 2004/08/29 04:12:46 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.8 2004/08/29 05:06:46 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -92,22 +92,22 @@
*/
typedef struct
{
RelFileNode rnode;
BlockNumber segno;
RelFileNode rnode;
BlockNumber segno;
/* might add a request-type field later */
} BgWriterRequest;
typedef struct
{
pid_t bgwriter_pid; /* PID of bgwriter (0 if not started) */
pid_t bgwriter_pid; /* PID of bgwriter (0 if not started) */
sig_atomic_t ckpt_started; /* advances when checkpoint starts */
sig_atomic_t ckpt_done; /* advances when checkpoint done */
sig_atomic_t ckpt_failed; /* advances when checkpoint fails */
sig_atomic_t ckpt_started; /* advances when checkpoint starts */
sig_atomic_t ckpt_done; /* advances when checkpoint done */
sig_atomic_t ckpt_failed; /* advances when checkpoint fails */
int num_requests; /* current # of requests */
int max_requests; /* allocated array size */
BgWriterRequest requests[1]; /* VARIABLE LENGTH ARRAY */
int num_requests; /* current # of requests */
int max_requests; /* allocated array size */
BgWriterRequest requests[1]; /* VARIABLE LENGTH ARRAY */
} BgWriterShmemStruct;
static BgWriterShmemStruct *BgWriterShmem;
@@ -132,11 +132,11 @@ static volatile sig_atomic_t shutdown_requested = false;
/*
* Private state
*/
static bool am_bg_writer = false;
static bool am_bg_writer = false;
static bool ckpt_active = false;
static bool ckpt_active = false;
static time_t last_checkpoint_time;
static time_t last_checkpoint_time;
static void bg_quickdie(SIGNAL_ARGS);
@@ -164,20 +164,20 @@ BackgroundWriterMain(void)
* Properly accept or ignore signals the postmaster might send us
*
* Note: we deliberately ignore SIGTERM, because during a standard Unix
* system shutdown cycle, init will SIGTERM all processes at once. We
* want to wait for the backends to exit, whereupon the postmaster will
* tell us it's okay to shut down (via SIGUSR2).
* system shutdown cycle, init will SIGTERM all processes at once. We
* want to wait for the backends to exit, whereupon the postmaster
* will tell us it's okay to shut down (via SIGUSR2).
*
* SIGUSR1 is presently unused; keep it spare in case someday we want
* this process to participate in sinval messaging.
*/
pqsignal(SIGHUP, BgSigHupHandler); /* set flag to read config file */
pqsignal(SIGINT, ReqCheckpointHandler); /* request checkpoint */
pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */
pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */
pqsignal(SIGQUIT, bg_quickdie); /* hard crash time */
pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, SIG_IGN); /* reserve for sinval */
pqsignal(SIGUSR1, SIG_IGN); /* reserve for sinval */
pqsignal(SIGUSR2, ReqShutdownHandler); /* request shutdown */
/*
@@ -197,8 +197,8 @@ BackgroundWriterMain(void)
#endif
/*
* Initialize so that first time-driven checkpoint happens
* at the correct time.
* Initialize so that first time-driven checkpoint happens at the
* correct time.
*/
last_checkpoint_time = time(NULL);
@@ -220,8 +220,8 @@ BackgroundWriterMain(void)
/*
* These operations are really just a minimal subset of
* AbortTransaction(). We don't have very many resources
* to worry about in bgwriter, but we do have LWLocks and buffers.
* AbortTransaction(). We don't have very many resources to worry
* about in bgwriter, but we do have LWLocks and buffers.
*/
LWLockReleaseAll();
AbortBufferIO();
@@ -266,7 +266,7 @@ BackgroundWriterMain(void)
PG_SETMASK(&UnBlockSig);
/*
* Loop forever
* Loop forever
*/
for (;;)
{
@@ -309,8 +309,8 @@ BackgroundWriterMain(void)
}
/*
* Do an unforced checkpoint if too much time has elapsed
* since the last one.
* Do an unforced checkpoint if too much time has elapsed since
* the last one.
*/
now = time(NULL);
elapsed_secs = now - last_checkpoint_time;
@@ -328,8 +328,8 @@ BackgroundWriterMain(void)
/*
* Ideally we should only warn if this checkpoint was
* requested due to running out of segment files, and not
* if it was manually requested. However we can't tell the
* difference with the current signalling mechanism.
* if it was manually requested. However we can't tell
* the difference with the current signalling mechanism.
*/
if (elapsed_secs < CheckPointWarning)
ereport(LOG,
@@ -354,16 +354,17 @@ BackgroundWriterMain(void)
/*
* Note we record the checkpoint start time not end time as
* last_checkpoint_time. This is so that time-driven checkpoints
* happen at a predictable spacing.
* last_checkpoint_time. This is so that time-driven
* checkpoints happen at a predictable spacing.
*/
last_checkpoint_time = now;
/*
* After any checkpoint, close all smgr files. This is so we
* won't hang onto smgr references to deleted files indefinitely.
* (It is safe to do this because this process does not have a
* relcache, and so no dangling references could remain.)
* After any checkpoint, close all smgr files. This is so we
* won't hang onto smgr references to deleted files
* indefinitely. (It is safe to do this because this process
* does not have a relcache, and so no dangling references
* could remain.)
*/
smgrcloseall();
@@ -371,17 +372,15 @@ BackgroundWriterMain(void)
n = 1;
}
else
{
n = BufferSync(BgWriterPercent, BgWriterMaxPages);
}
/*
* Nap for the configured time or sleep for 10 seconds if
* there was nothing to do at all.
* Nap for the configured time or sleep for 10 seconds if there
* was nothing to do at all.
*
* On some platforms, signals won't interrupt the sleep. To ensure
* we respond reasonably promptly when someone signals us,
* break down the sleep into 1-second increments, and check for
* we respond reasonably promptly when someone signals us, break
* down the sleep into 1-second increments, and check for
* interrupts after each nap.
*
* We absorb pending requests after each short sleep.
@@ -469,7 +468,7 @@ BgWriterShmemSize(void)
* equal to NBuffers. This may prove too large or small ...
*/
return MAXALIGN(sizeof(BgWriterShmemStruct) +
(NBuffers - 1) * sizeof(BgWriterRequest));
(NBuffers - 1) *sizeof(BgWriterRequest));
}
/*
@@ -479,7 +478,7 @@ BgWriterShmemSize(void)
void
BgWriterShmemInit(void)
{
bool found;
bool found;
BgWriterShmem = (BgWriterShmemStruct *)
ShmemInitStruct("Background Writer Data",
@@ -509,12 +508,12 @@ RequestCheckpoint(bool waitforit)
{
/* use volatile pointer to prevent code rearrangement */
volatile BgWriterShmemStruct *bgs = BgWriterShmem;
sig_atomic_t old_failed = bgs->ckpt_failed;
sig_atomic_t old_started = bgs->ckpt_started;
sig_atomic_t old_failed = bgs->ckpt_failed;
sig_atomic_t old_started = bgs->ckpt_started;
/*
* Send signal to request checkpoint. When waitforit is false,
* we consider failure to send the signal to be nonfatal.
* Send signal to request checkpoint. When waitforit is false, we
* consider failure to send the signal to be nonfatal.
*/
if (BgWriterShmem->bgwriter_pid == 0)
elog(waitforit ? ERROR : LOG,
@@ -535,15 +534,16 @@ RequestCheckpoint(bool waitforit)
pg_usleep(100000L);
}
old_started = bgs->ckpt_started;
/*
* We are waiting for ckpt_done >= old_started, in a modulo
* sense. This is a little tricky since we don't know the
* width or signedness of sig_atomic_t. We make the lowest
* common denominator assumption that it is only as wide
* as "char". This means that this algorithm will cope
* correctly as long as we don't sleep for more than 127
* completed checkpoints. (If we do, we will get another
* chance to exit after 128 more checkpoints...)
* We are waiting for ckpt_done >= old_started, in a modulo sense.
* This is a little tricky since we don't know the width or
* signedness of sig_atomic_t. We make the lowest common
* denominator assumption that it is only as wide as "char". This
* means that this algorithm will cope correctly as long as we
* don't sleep for more than 127 completed checkpoints. (If we
* do, we will get another chance to exit after 128 more
* checkpoints...)
*/
while (((signed char) (bgs->ckpt_done - old_started)) < 0)
{
@@ -634,9 +634,7 @@ AbsorbFsyncRequests(void)
LWLockRelease(BgWriterCommLock);
for (request = requests; n > 0; request++, n--)
{
RememberFsyncRequest(request->rnode, request->segno);
}
if (requests)
pfree(requests);
}

View File

@@ -4,22 +4,22 @@
*
* PostgreSQL WAL archiver
*
* All functions relating to archiver are included here
* All functions relating to archiver are included here
*
* - All functions executed by archiver process
* - All functions executed by archiver process
*
* - archiver is forked from postmaster, and the two
* processes then communicate using signals. All functions
* executed by postmaster are included in this file.
* - archiver is forked from postmaster, and the two
* processes then communicate using signals. All functions
* executed by postmaster are included in this file.
*
* Initial author: Simon Riggs simon@2ndquadrant.com
* Initial author: Simon Riggs simon@2ndquadrant.com
*
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.8 2004/08/29 04:12:46 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.9 2004/08/29 05:06:46 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -65,7 +65,7 @@
*/
#define MIN_XFN_CHARS 16
#define MAX_XFN_CHARS 40
#define VALID_XFN_CHARS "0123456789ABCDEF.history.backup"
#define VALID_XFN_CHARS "0123456789ABCDEF.history.backup"
#define NUM_ARCHIVE_RETRIES 3
@@ -129,16 +129,16 @@ pgarch_start(void)
return 0;
/*
* Do nothing if too soon since last archiver start. This is a
* safety valve to protect against continuous respawn attempts if the
* archiver is dying immediately at launch. Note that since we will
* be re-called from the postmaster main loop, we will get another
* chance later.
* Do nothing if too soon since last archiver start. This is a safety
* valve to protect against continuous respawn attempts if the
* archiver is dying immediately at launch. Note that since we will be
* re-called from the postmaster main loop, we will get another chance
* later.
*/
curtime = time(NULL);
if ((unsigned int) (curtime - last_pgarch_start_time) <
(unsigned int) PGARCH_RESTART_INTERVAL)
return 0;
return 0;
last_pgarch_start_time = curtime;
fflush(stdout);
@@ -205,8 +205,8 @@ pgarch_start(void)
static pid_t
pgarch_forkexec(void)
{
char *av[10];
int ac = 0;
char *av[10];
int ac = 0;
av[ac++] = "postgres";
@@ -219,8 +219,7 @@ pgarch_forkexec(void)
return postmaster_forkexec(ac, av);
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
/*
@@ -232,44 +231,44 @@ pgarch_forkexec(void)
NON_EXEC_STATIC void
PgArchiverMain(int argc, char *argv[])
{
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
MyProcPid = getpid(); /* reset MyProcPid */
MyProcPid = getpid(); /* reset MyProcPid */
/* Lose the postmaster's on-exit routines */
on_exit_reset();
/*
* Ignore all signals usually bound to some action in the postmaster,
/*
* Ignore all signals usually bound to some action in the postmaster,
* except for SIGHUP, SIGUSR1 and SIGQUIT.
*/
pqsignal(SIGHUP, ArchSigHupHandler);
pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGTERM, SIG_IGN);
pqsignal(SIGQUIT, pgarch_exit);
pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, pgarch_waken);
pqsignal(SIGUSR2, SIG_IGN);
pqsignal(SIGCHLD, SIG_DFL);
pqsignal(SIGTTIN, SIG_DFL);
pqsignal(SIGTTOU, SIG_DFL);
pqsignal(SIGCONT, SIG_DFL);
pqsignal(SIGWINCH, SIG_DFL);
PG_SETMASK(&UnBlockSig);
*/
pqsignal(SIGHUP, ArchSigHupHandler);
pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGTERM, SIG_IGN);
pqsignal(SIGQUIT, pgarch_exit);
pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, pgarch_waken);
pqsignal(SIGUSR2, SIG_IGN);
pqsignal(SIGCHLD, SIG_DFL);
pqsignal(SIGTTIN, SIG_DFL);
pqsignal(SIGTTOU, SIG_DFL);
pqsignal(SIGCONT, SIG_DFL);
pqsignal(SIGWINCH, SIG_DFL);
PG_SETMASK(&UnBlockSig);
/*
* Identify myself via ps
*/
init_ps_display("archiver process", "", "");
set_ps_display("");
/*
* Identify myself via ps
*/
init_ps_display("archiver process", "", "");
set_ps_display("");
/* Init XLOG file paths --- needed in EXEC_BACKEND case */
/* Init XLOG file paths --- needed in EXEC_BACKEND case */
XLOGPathInit();
pgarch_MainLoop();
pgarch_MainLoop();
exit(0);
exit(0);
}
/* SIGQUIT signal handler for archiver process */
@@ -278,10 +277,10 @@ pgarch_exit(SIGNAL_ARGS)
{
/*
* For now, we just nail the doors shut and get out of town. It might
* seem cleaner to finish up any pending archive copies, but there's
* a nontrivial risk that init will kill us partway through.
* seem cleaner to finish up any pending archive copies, but there's a
* nontrivial risk that init will kill us partway through.
*/
exit(0);
exit(0);
}
/* SIGHUP: set flag to re-read config file at next convenient time */
@@ -306,8 +305,8 @@ pgarch_waken(SIGNAL_ARGS)
static void
pgarch_MainLoop(void)
{
time_t last_copy_time = 0;
time_t curtime;
time_t last_copy_time = 0;
time_t curtime;
/*
* We run the copy loop immediately upon entry, in case there are
@@ -317,7 +316,8 @@ pgarch_MainLoop(void)
*/
wakened = true;
do {
do
{
/* Check for config update */
if (got_SIGHUP)
@@ -337,12 +337,12 @@ pgarch_MainLoop(void)
}
/*
* There shouldn't be anything for the archiver to do except
* to wait for a signal, so we could use pause(3) here...
* ...however, the archiver exists to protect our data, so
* she wakes up occasionally to allow herself to be proactive.
* In particular this avoids getting stuck if a signal arrives
* just before we enter sleep().
* There shouldn't be anything for the archiver to do except to
* wait for a signal, so we could use pause(3) here... ...however,
* the archiver exists to protect our data, so she wakes up
* occasionally to allow herself to be proactive. In particular
* this avoids getting stuck if a signal arrives just before we
* enter sleep().
*/
if (!wakened)
{
@@ -353,7 +353,7 @@ pgarch_MainLoop(void)
(unsigned int) PGARCH_AUTOWAKE_INTERVAL)
wakened = true;
}
} while (PostmasterIsAlive(true));
} while (PostmasterIsAlive(true));
}
/*
@@ -364,18 +364,17 @@ pgarch_MainLoop(void)
static void
pgarch_ArchiverCopyLoop(void)
{
char xlog[MAX_XFN_CHARS + 1];
char xlog[MAX_XFN_CHARS + 1];
/*
* loop through all xlogs with archive_status of .ready
* and archive them...mostly we expect this to be a single
* file, though it is possible some backend will add
* files onto the list of those that need archiving while we
* are still copying earlier archives
*/
while (pgarch_readyXlog(xlog))
/*
* loop through all xlogs with archive_status of .ready and archive
* them...mostly we expect this to be a single file, though it is
* possible some backend will add files onto the list of those that
* need archiving while we are still copying earlier archives
*/
while (pgarch_readyXlog(xlog))
{
int failures = 0;
int failures = 0;
for (;;)
{
@@ -410,14 +409,14 @@ pgarch_ArchiverCopyLoop(void)
static bool
pgarch_archiveXlog(char *xlog)
{
char xlogarchcmd[MAXPGPATH];
char pathname[MAXPGPATH];
char *dp;
char *endp;
char xlogarchcmd[MAXPGPATH];
char pathname[MAXPGPATH];
char *dp;
char *endp;
const char *sp;
int rc;
int rc;
snprintf(pathname, MAXPGPATH, "%s/%s", XLogDir, xlog);
snprintf(pathname, MAXPGPATH, "%s/%s", XLogDir, xlog);
/*
* construct the command to be executed
@@ -435,14 +434,14 @@ pgarch_archiveXlog(char *xlog)
case 'p':
/* %p: full path of source file */
sp++;
StrNCpy(dp, pathname, endp-dp);
StrNCpy(dp, pathname, endp - dp);
make_native_path(dp);
dp += strlen(dp);
break;
case 'f':
/* %f: filename of source file */
sp++;
StrNCpy(dp, xlog, endp-dp);
StrNCpy(dp, xlog, endp - dp);
dp += strlen(dp);
break;
case '%':
@@ -467,19 +466,20 @@ pgarch_archiveXlog(char *xlog)
*dp = '\0';
ereport(DEBUG3,
(errmsg_internal("executing archive command \"%s\"",
(errmsg_internal("executing archive command \"%s\"",
xlogarchcmd)));
rc = system(xlogarchcmd);
if (rc != 0) {
ereport(LOG,
rc = system(xlogarchcmd);
if (rc != 0)
{
ereport(LOG,
(errmsg("archive command \"%s\" failed: return code %d",
xlogarchcmd, rc)));
return false;
}
return false;
}
ereport(LOG,
(errmsg("archived transaction log file \"%s\"", xlog)));
(errmsg("archived transaction log file \"%s\"", xlog)));
return true;
return true;
}
/*
@@ -507,57 +507,63 @@ static bool
pgarch_readyXlog(char *xlog)
{
/*
* open xlog status directory and read through list of
* xlogs that have the .ready suffix, looking for earliest file.
* It is possible to optimise this code, though only a single
* file is expected on the vast majority of calls, so....
* open xlog status directory and read through list of xlogs that have
* the .ready suffix, looking for earliest file. It is possible to
* optimise this code, though only a single file is expected on the
* vast majority of calls, so....
*/
char XLogArchiveStatusDir[MAXPGPATH];
char newxlog[MAX_XFN_CHARS + 6 + 1];
DIR *rldir;
struct dirent *rlde;
bool found = false;
char newxlog[MAX_XFN_CHARS + 6 + 1];
DIR *rldir;
struct dirent *rlde;
bool found = false;
snprintf(XLogArchiveStatusDir, MAXPGPATH, "%s/archive_status", XLogDir);
snprintf(XLogArchiveStatusDir, MAXPGPATH, "%s/archive_status", XLogDir);
rldir = AllocateDir(XLogArchiveStatusDir);
if (rldir == NULL)
ereport(ERROR,
(errcode_for_file_access(),
(errcode_for_file_access(),
errmsg("could not open archive status directory \"%s\": %m",
XLogArchiveStatusDir)));
errno = 0;
while ((rlde = readdir(rldir)) != NULL)
{
int basenamelen = (int) strlen(rlde->d_name) - 6;
int basenamelen = (int) strlen(rlde->d_name) - 6;
if (basenamelen >= MIN_XFN_CHARS &&
basenamelen <= MAX_XFN_CHARS &&
strspn(rlde->d_name, VALID_XFN_CHARS) >= basenamelen &&
strcmp(rlde->d_name + basenamelen, ".ready") == 0)
{
if (!found) {
strcpy(newxlog, rlde->d_name);
found = true;
} else {
if (strcmp(rlde->d_name, newxlog) < 0)
strcpy(newxlog, rlde->d_name);
}
if (!found)
{
strcpy(newxlog, rlde->d_name);
found = true;
}
else
{
if (strcmp(rlde->d_name, newxlog) < 0)
strcpy(newxlog, rlde->d_name);
}
}
errno = 0;
}
#ifdef WIN32
/* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
not in released version */
/*
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but
* not in released version
*/
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
if (errno)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not read archive status directory \"%s\": %m",
XLogArchiveStatusDir)));
errmsg("could not read archive status directory \"%s\": %m",
XLogArchiveStatusDir)));
FreeDir(rldir);
if (found)
@@ -580,13 +586,13 @@ pgarch_readyXlog(char *xlog)
static void
pgarch_archiveDone(char *xlog)
{
char rlogready[MAXPGPATH];
char rlogdone[MAXPGPATH];
char rlogready[MAXPGPATH];
char rlogdone[MAXPGPATH];
StatusFilePath(rlogready, xlog, ".ready");
StatusFilePath(rlogdone, xlog, ".done");
if (rename(rlogready, rlogdone) < 0)
ereport(WARNING,
if (rename(rlogready, rlogdone) < 0)
ereport(WARNING,
(errcode_for_file_access(),
errmsg("could not rename file \"%s\" to \"%s\": %m",
rlogready, rlogdone)));

View File

@@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2004, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.79 2004/08/29 04:12:46 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.80 2004/08/29 05:06:46 momjian Exp $
* ----------
*/
#include "postgres.h"
@@ -70,8 +70,8 @@
#define PGSTAT_DESTROY_DELAY 10000 /* How long to keep destroyed
* objects known, to give delayed
* UDP packets time to arrive;
* in milliseconds. */
* UDP packets time to arrive; in
* milliseconds. */
#define PGSTAT_DESTROY_COUNT (PGSTAT_DESTROY_DELAY / PGSTAT_STAT_INTERVAL)
@@ -108,7 +108,7 @@ bool pgstat_collect_blocklevel = false;
* Local data
* ----------
*/
NON_EXEC_STATIC int pgStatSock = -1;
NON_EXEC_STATIC int pgStatSock = -1;
static int pgStatPipe[2];
static struct sockaddr_storage pgStatAddr;
@@ -147,11 +147,10 @@ typedef enum STATS_PROCESS_TYPE
{
STAT_PROC_BUFFER,
STAT_PROC_COLLECTOR
} STATS_PROCESS_TYPE;
} STATS_PROCESS_TYPE;
static pid_t pgstat_forkexec(STATS_PROCESS_TYPE procType);
static void pgstat_parseArgs(int argc, char *argv[]);
#endif
NON_EXEC_STATIC void PgstatBufferMain(int argc, char *argv[]);
@@ -203,10 +202,10 @@ pgstat_init(void)
*addr,
hints;
int ret;
fd_set rset;
fd_set rset;
struct timeval tv;
char test_byte;
int sel_res;
char test_byte;
int sel_res;
#define TESTBYTEVAL ((char) 199)
@@ -219,10 +218,11 @@ pgstat_init(void)
pgstat_collect_startcollector = true;
/*
* Initialize the filename for the status reports. (In the EXEC_BACKEND
* case, this only sets the value in the postmaster. The collector
* subprocess will recompute the value for itself, and individual
* backends must do so also if they want to access the file.)
* Initialize the filename for the status reports. (In the
* EXEC_BACKEND case, this only sets the value in the postmaster. The
* collector subprocess will recompute the value for itself, and
* individual backends must do so also if they want to access the
* file.)
*/
snprintf(pgStat_fname, MAXPGPATH, PGSTAT_STAT_FILENAME, DataDir);
@@ -261,11 +261,11 @@ pgstat_init(void)
/*
* On some platforms, getaddrinfo_all() may return multiple addresses
* only one of which will actually work (eg, both IPv6 and IPv4 addresses
* when kernel will reject IPv6). Worse, the failure may occur at the
* bind() or perhaps even connect() stage. So we must loop through the
* results till we find a working combination. We will generate LOG
* messages, but no error, for bogus combinations.
* only one of which will actually work (eg, both IPv6 and IPv4
* addresses when kernel will reject IPv6). Worse, the failure may
* occur at the bind() or perhaps even connect() stage. So we must
* loop through the results till we find a working combination. We
* will generate LOG messages, but no error, for bogus combinations.
*/
for (addr = addrs; addr; addr = addr->ai_next)
{
@@ -274,6 +274,7 @@ pgstat_init(void)
if (addr->ai_family == AF_UNIX)
continue;
#endif
/*
* Create the socket.
*/
@@ -286,8 +287,8 @@ pgstat_init(void)
}
/*
* Bind it to a kernel assigned port on localhost and get the assigned
* port via getsockname().
* Bind it to a kernel assigned port on localhost and get the
* assigned port via getsockname().
*/
if (bind(pgStatSock, addr->ai_addr, addr->ai_addrlen) < 0)
{
@@ -300,7 +301,7 @@ pgstat_init(void)
}
alen = sizeof(pgStatAddr);
if (getsockname(pgStatSock, (struct sockaddr *) &pgStatAddr, &alen) < 0)
if (getsockname(pgStatSock, (struct sockaddr *) & pgStatAddr, &alen) < 0)
{
ereport(LOG,
(errcode_for_socket_access(),
@@ -311,12 +312,12 @@ pgstat_init(void)
}
/*
* Connect the socket to its own address. This saves a few cycles by
* not having to respecify the target address on every send. This also
* provides a kernel-level check that only packets from this same
* address will be received.
* Connect the socket to its own address. This saves a few cycles
* by not having to respecify the target address on every send.
* This also provides a kernel-level check that only packets from
* this same address will be received.
*/
if (connect(pgStatSock, (struct sockaddr *) &pgStatAddr, alen) < 0)
if (connect(pgStatSock, (struct sockaddr *) & pgStatAddr, alen) < 0)
{
ereport(LOG,
(errcode_for_socket_access(),
@@ -329,8 +330,8 @@ pgstat_init(void)
/*
* Try to send and receive a one-byte test message on the socket.
* This is to catch situations where the socket can be created but
* will not actually pass data (for instance, because kernel packet
* filtering rules prevent it).
* will not actually pass data (for instance, because kernel
* packet filtering rules prevent it).
*/
test_byte = TESTBYTEVAL;
if (send(pgStatSock, &test_byte, 1, 0) != 1)
@@ -344,9 +345,9 @@ pgstat_init(void)
}
/*
* There could possibly be a little delay before the message can be
* received. We arbitrarily allow up to half a second before deciding
* it's broken.
* There could possibly be a little delay before the message can
* be received. We arbitrarily allow up to half a second before
* deciding it's broken.
*/
for (;;) /* need a loop to handle EINTR */
{
@@ -354,7 +355,7 @@ pgstat_init(void)
FD_SET(pgStatSock, &rset);
tv.tv_sec = 0;
tv.tv_usec = 500000;
sel_res = select(pgStatSock+1, &rset, NULL, NULL, &tv);
sel_res = select(pgStatSock + 1, &rset, NULL, NULL, &tv);
if (sel_res >= 0 || errno != EINTR)
break;
}
@@ -362,7 +363,7 @@ pgstat_init(void)
{
ereport(LOG,
(errcode_for_socket_access(),
errmsg("select() failed in statistics collector: %m")));
errmsg("select() failed in statistics collector: %m")));
closesocket(pgStatSock);
pgStatSock = -1;
continue;
@@ -370,8 +371,8 @@ pgstat_init(void)
if (sel_res == 0 || !FD_ISSET(pgStatSock, &rset))
{
/*
* This is the case we actually think is likely, so take pains to
* give a specific message for it.
* This is the case we actually think is likely, so take pains
* to give a specific message for it.
*
* errno will not be set meaningfully here, so don't use it.
*/
@@ -395,7 +396,7 @@ pgstat_init(void)
continue;
}
if (test_byte != TESTBYTEVAL) /* strictly paranoia ... */
if (test_byte != TESTBYTEVAL) /* strictly paranoia ... */
{
ereport(LOG,
(ERRCODE_INTERNAL_ERROR,
@@ -428,7 +429,7 @@ pgstat_init(void)
{
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not set statistics collector socket to nonblocking mode: %m")));
errmsg("could not set statistics collector socket to nonblocking mode: %m")));
goto startup_failed;
}
@@ -463,9 +464,11 @@ startup_failed:
static pid_t
pgstat_forkexec(STATS_PROCESS_TYPE procType)
{
char *av[10];
int ac = 0, bufc = 0, i;
char pgstatBuf[2][32];
char *av[10];
int ac = 0,
bufc = 0,
i;
char pgstatBuf[2][32];
av[ac++] = "postgres";
@@ -489,8 +492,8 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
av[ac++] = postgres_exec_path;
/* Pipe file ids (those not passed by write_backend_variables) */
snprintf(pgstatBuf[bufc++],32,"%d",pgStatPipe[0]);
snprintf(pgstatBuf[bufc++],32,"%d",pgStatPipe[1]);
snprintf(pgstatBuf[bufc++], 32, "%d", pgStatPipe[0]);
snprintf(pgstatBuf[bufc++], 32, "%d", pgStatPipe[1]);
/* Add to the arg list */
Assert(bufc <= lengthof(pgstatBuf));
@@ -516,12 +519,11 @@ pgstat_parseArgs(int argc, char *argv[])
Assert(argc == 6);
argc = 3;
StrNCpy(postgres_exec_path, argv[argc++], MAXPGPATH);
pgStatPipe[0] = atoi(argv[argc++]);
pgStatPipe[1] = atoi(argv[argc++]);
StrNCpy(postgres_exec_path, argv[argc++], MAXPGPATH);
pgStatPipe[0] = atoi(argv[argc++]);
pgStatPipe[1] = atoi(argv[argc++]);
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
/* ----------
@@ -1072,7 +1074,7 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
{
tsmsg = pgStatTabstatMessages[mb];
for (i = tsmsg->m_nentries; --i >= 0; )
for (i = tsmsg->m_nentries; --i >= 0;)
{
if (tsmsg->m_entry[i].t_id == rel_id)
{
@@ -1387,7 +1389,7 @@ PgstatBufferMain(int argc, char *argv[])
/* unblock will happen in pgstat_recvbuffer */
#ifdef EXEC_BACKEND
pgstat_parseArgs(argc,argv);
pgstat_parseArgs(argc, argv);
#endif
/*
@@ -1464,9 +1466,9 @@ PgstatCollectorMain(int argc, char *argv[])
/*
* Reset signal handling. With the exception of restoring default
* SIGCHLD and SIGQUIT handling, this is a no-op in the non-EXEC_BACKEND
* case because we'll have inherited these settings from the buffer
* process; but it's not a no-op for EXEC_BACKEND.
* SIGCHLD and SIGQUIT handling, this is a no-op in the
* non-EXEC_BACKEND case because we'll have inherited these settings
* from the buffer process; but it's not a no-op for EXEC_BACKEND.
*/
pqsignal(SIGHUP, SIG_IGN);
pqsignal(SIGINT, SIG_IGN);
@@ -1484,7 +1486,7 @@ PgstatCollectorMain(int argc, char *argv[])
PG_SETMASK(&UnBlockSig);
#ifdef EXEC_BACKEND
pgstat_parseArgs(argc,argv);
pgstat_parseArgs(argc, argv);
#endif
/* Close unwanted files */
@@ -1532,7 +1534,7 @@ PgstatCollectorMain(int argc, char *argv[])
/* assume the problem is out-of-memory */
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory in statistics collector --- abort")));
errmsg("out of memory in statistics collector --- abort")));
exit(1);
}
@@ -1545,7 +1547,7 @@ PgstatCollectorMain(int argc, char *argv[])
{
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory in statistics collector --- abort")));
errmsg("out of memory in statistics collector --- abort")));
exit(1);
}
memset(pgStatBeTable, 0, sizeof(PgStat_StatBeEntry) * MaxBackends);
@@ -1597,7 +1599,7 @@ PgstatCollectorMain(int argc, char *argv[])
/*
* Now wait for something to do.
*/
nready = select(readPipe+1, &rfds, NULL, NULL,
nready = select(readPipe + 1, &rfds, NULL, NULL,
(need_statwrite) ? &timeout : NULL);
if (nready < 0)
{
@@ -1605,7 +1607,7 @@ PgstatCollectorMain(int argc, char *argv[])
continue;
ereport(LOG,
(errcode_for_socket_access(),
errmsg("select() failed in statistics collector: %m")));
errmsg("select() failed in statistics collector: %m")));
exit(1);
}
@@ -1640,7 +1642,7 @@ PgstatCollectorMain(int argc, char *argv[])
while (nread < targetlen)
{
len = piperead(readPipe, ((char *) &msg) + nread,
targetlen - nread);
targetlen - nread);
if (len < 0)
{
if (errno == EINTR)
@@ -1816,7 +1818,7 @@ pgstat_recvbuffer(void)
{
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not set statistics collector pipe to nonblocking mode: %m")));
errmsg("could not set statistics collector pipe to nonblocking mode: %m")));
exit(1);
}
@@ -1986,8 +1988,8 @@ pgstat_recvbuffer(void)
continue;
/*
* If the postmaster has terminated, we die too. (This is no longer
* the normal exit path, however.)
* If the postmaster has terminated, we die too. (This is no
* longer the normal exit path, however.)
*/
if (!PostmasterIsAlive(true))
exit(0);
@@ -2000,8 +2002,8 @@ pgstat_exit(SIGNAL_ARGS)
{
/*
* For now, we just nail the doors shut and get out of town. It might
* be cleaner to allow any pending messages to be sent, but that creates
* a tradeoff against speed of exit.
* be cleaner to allow any pending messages to be sent, but that
* creates a tradeoff against speed of exit.
*/
exit(0);
}
@@ -2034,7 +2036,7 @@ pgstat_add_backend(PgStat_MsgHdr *msg)
if (msg->m_backendid < 1 || msg->m_backendid > MaxBackends)
{
ereport(LOG,
(errmsg("invalid server process ID %d", msg->m_backendid)));
(errmsg("invalid server process ID %d", msg->m_backendid)));
return -1;
}
@@ -2229,8 +2231,8 @@ pgstat_write_statsfile(void)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not open temporary statistics file \"%s\": %m",
pgStat_tmpfname)));
errmsg("could not open temporary statistics file \"%s\": %m",
pgStat_tmpfname)));
return;
}
@@ -2342,8 +2344,8 @@ pgstat_write_statsfile(void)
{
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not close temporary statistics file \"%s\": %m",
pgStat_tmpfname)));
errmsg("could not close temporary statistics file \"%s\": %m",
pgStat_tmpfname)));
}
else
{
@@ -2373,8 +2375,8 @@ pgstat_write_statsfile(void)
HASH_REMOVE, NULL) == NULL)
{
ereport(LOG,
(errmsg("dead-server-process hash table corrupted "
"during cleanup --- abort")));
(errmsg("dead-server-process hash table corrupted "
"during cleanup --- abort")));
exit(1);
}
}
@@ -2743,7 +2745,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
static void
backend_read_statsfile(void)
{
TransactionId topXid = GetTopTransactionId();
TransactionId topXid = GetTopTransactionId();
if (!TransactionIdEquals(pgStatDBHashXact, topXid))
{

View File

@@ -7,7 +7,7 @@
* message to setup a backend process.
*
* The postmaster also manages system-wide operations such as
* startup and shutdown. The postmaster itself doesn't do those
* startup and shutdown. The postmaster itself doesn't do those
* operations, mind you --- it just forks off a subprocess to do them
* at the right times. It also takes care of resetting the system
* if a backend crashes.
@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.423 2004/08/29 04:12:46 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.424 2004/08/29 05:06:46 momjian Exp $
*
* NOTES
*
@@ -58,7 +58,7 @@
* Error Reporting:
* Use write_stderr() only for reporting "interactive" errors
* (essentially, bogus arguments on the command line). Once the
* postmaster is launched, use ereport(). In particular, don't use
* postmaster is launched, use ereport(). In particular, don't use
* write_stderr() for anything that occurs after pmdaemonize.
*
*-------------------------------------------------------------------------
@@ -238,9 +238,10 @@ extern int optreset;
*/
static void checkDataDir(const char *checkdir);
static bool onlyConfigSpecified(const char *checkdir);
#ifdef USE_RENDEZVOUS
static void reg_reply(DNSServiceRegistrationReplyErrorType errorCode,
void *context);
void *context);
#endif
static void pmdaemonize(void);
static Port *ConnCreate(int serverFd);
@@ -285,7 +286,7 @@ static pid_t *win32_childPIDArray;
static HANDLE *win32_childHNDArray;
static unsigned long win32_numChildren = 0;
HANDLE PostmasterHandle;
HANDLE PostmasterHandle;
#endif
static pid_t backend_forkexec(Port *port);
@@ -296,8 +297,7 @@ static bool write_backend_variables(char *filename, Port *port);
static void ShmemBackendArrayAdd(Backend *bn);
static void ShmemBackendArrayRemove(pid_t pid);
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
#define StartupDataBase() StartChildProcess(BS_XLOG_STARTUP)
#define StartBackgroundWriter() StartChildProcess(BS_XLOG_BGWRITER)
@@ -376,7 +376,7 @@ PostmasterMain(int argc, char *argv[])
InitializeGUCOptions();
userPGDATA = getenv("PGDATA"); /* default value */
opterr = 1;
while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1)
@@ -453,7 +453,8 @@ PostmasterMain(int argc, char *argv[])
case 'o':
/*
* Other options to pass to the backend on the command line
* Other options to pass to the backend on the command
* line
*/
snprintf(ExtraOptions + strlen(ExtraOptions),
sizeof(ExtraOptions) - strlen(ExtraOptions),
@@ -538,16 +539,16 @@ PostmasterMain(int argc, char *argv[])
if (onlyConfigSpecified(userPGDATA))
{
/*
* It is either a file name or a directory with no
* global/pg_control file, and hence not a data directory.
* It is either a file name or a directory with no
* global/pg_control file, and hence not a data directory.
*/
user_pgconfig = userPGDATA;
ProcessConfigFile(PGC_POSTMASTER);
if (!guc_pgdata) /* Got a pgdata from the config file? */
if (!guc_pgdata) /* Got a pgdata from the config file? */
{
write_stderr("%s does not know where to find the database system data.\n"
"This should be specified as \"pgdata\" in %s%s.\n",
"This should be specified as \"pgdata\" in %s%s.\n",
progname, userPGDATA,
user_pgconfig_is_dir ? "/postgresql.conf" : "");
ExitPostmaster(2);
@@ -557,7 +558,10 @@ PostmasterMain(int argc, char *argv[])
}
else
{
/* Now we can set the data directory, and then read postgresql.conf. */
/*
* Now we can set the data directory, and then read
* postgresql.conf.
*/
checkDataDir(userPGDATA);
SetDataDir(userPGDATA);
ProcessConfigFile(PGC_POSTMASTER);
@@ -565,7 +569,7 @@ PostmasterMain(int argc, char *argv[])
if (external_pidfile)
{
FILE *fpidfile = fopen(external_pidfile, "w");
FILE *fpidfile = fopen(external_pidfile, "w");
if (fpidfile)
{
@@ -575,8 +579,8 @@ PostmasterMain(int argc, char *argv[])
}
else
fprintf(stderr,
gettext("%s could not write to external pid file %s\n"),
progname, external_pidfile);
gettext("%s could not write to external pid file %s\n"),
progname, external_pidfile);
}
/* If timezone is not set, determine what the OS uses */
@@ -645,8 +649,8 @@ PostmasterMain(int argc, char *argv[])
if (find_other_exec(argv[0], "postgres", PG_VERSIONSTR,
postgres_exec_path) < 0)
ereport(FATAL,
(errmsg("%s: could not locate matching postgres executable",
progname)));
(errmsg("%s: could not locate matching postgres executable",
progname)));
#endif
/*
@@ -679,8 +683,8 @@ PostmasterMain(int argc, char *argv[])
* We want to do this before we try to grab the input sockets, because
* the data directory interlock is more reliable than the socket-file
* interlock (thanks to whoever decided to put socket files in /tmp
* :-(). For the same reason, it's best to grab the TCP socket(s) before
* the Unix socket.
* :-(). For the same reason, it's best to grab the TCP socket(s)
* before the Unix socket.
*/
CreateDataDirLockFile(DataDir, true);
@@ -699,25 +703,25 @@ PostmasterMain(int argc, char *argv[])
if (ListenAddresses)
{
char *rawstring;
List *elemlist;
ListCell *l;
char *rawstring;
List *elemlist;
ListCell *l;
/* Need a modifiable copy of ListenAddresses */
rawstring = pstrdup(ListenAddresses);
/* Parse string into list of identifiers */
if (!SplitIdentifierString(rawstring, ',', &elemlist))
if (!SplitIdentifierString(rawstring, ',', &elemlist))
{
/* syntax error in list */
ereport(FATAL,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid list syntax for \"listen_addresses\"")));
errmsg("invalid list syntax for \"listen_addresses\"")));
}
foreach(l, elemlist)
{
char *curhost = (char *) lfirst(l);
char *curhost = (char *) lfirst(l);
if (strcmp(curhost, "*") == 0)
status = StreamServerPort(AF_UNSPEC, NULL,
@@ -790,6 +794,7 @@ PostmasterMain(int argc, char *argv[])
BackendList = DLNewList();
#ifdef WIN32
/*
* Initialize the child pid/HANDLE arrays for signal handling.
*/
@@ -814,8 +819,8 @@ PostmasterMain(int argc, char *argv[])
TRUE,
DUPLICATE_SAME_ACCESS) == 0)
ereport(FATAL,
(errmsg_internal("could not duplicate postmaster handle: %d",
(int) GetLastError())));
(errmsg_internal("could not duplicate postmaster handle: %d",
(int) GetLastError())));
#endif
/*
@@ -862,9 +867,9 @@ PostmasterMain(int argc, char *argv[])
/*
* Reset whereToSendOutput from Debug (its starting state) to None.
* This stops ereport from sending log messages to stderr unless
* Log_destination permits. We don't do this until the postmaster
* is fully launched, since startup failures may as well be
* reported to stderr.
* Log_destination permits. We don't do this until the postmaster is
* fully launched, since startup failures may as well be reported to
* stderr.
*/
whereToSendOutput = None;
@@ -906,18 +911,20 @@ PostmasterMain(int argc, char *argv[])
static bool
onlyConfigSpecified(const char *checkdir)
{
char path[MAXPGPATH];
char path[MAXPGPATH];
struct stat stat_buf;
if (checkdir == NULL) /* checkDataDir handles this */
if (checkdir == NULL) /* checkDataDir handles this */
return FALSE;
if (stat(checkdir, &stat_buf) == -1) /* ditto */
if (stat(checkdir, &stat_buf) == -1) /* ditto */
return FALSE;
if (S_ISREG(stat_buf.st_mode)) /* It's a regular file, so assume it's explict */
if (S_ISREG(stat_buf.st_mode)) /* It's a regular file, so assume
* it's explict */
return TRUE;
else if (S_ISDIR(stat_buf.st_mode)) /* It's a directory, is it a config or system dir? */
else if (S_ISDIR(stat_buf.st_mode)) /* It's a directory, is it a
* config or system dir? */
{
snprintf(path, MAXPGPATH, "%s/global/pg_control", checkdir);
/* If this is not found, it is a config-only directory */
@@ -1006,8 +1013,7 @@ reg_reply(DNSServiceRegistrationReplyErrorType errorCode, void *context)
{
}
#endif /* USE_RENDEZVOUS */
#endif /* USE_RENDEZVOUS */
/*
@@ -1046,7 +1052,7 @@ pmdaemonize(void)
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
MyProcPid = PostmasterPid = getpid(); /* reset PID vars to child */
MyProcPid = PostmasterPid = getpid(); /* reset PID vars to child */
/* GH: If there's no setsid(), we hopefully don't need silent mode.
* Until there's a better solution.
@@ -1064,10 +1070,10 @@ pmdaemonize(void)
dup2(i, 1);
dup2(i, 2);
close(i);
#else /* WIN32 */
#else /* WIN32 */
/* not supported */
elog(FATAL, "SilentMode not supported under WIN32");
#endif /* WIN32 */
#endif /* WIN32 */
}
@@ -1143,7 +1149,8 @@ ServerLoop(void)
* Wait for something to happen.
*
* We wait at most one minute, to ensure that the other background
* tasks handled below get done even when no requests are arriving.
* tasks handled below get done even when no requests are
* arriving.
*/
memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
@@ -1178,7 +1185,8 @@ ServerLoop(void)
if (selres > 0)
{
/*
* Select a random seed at the time of first receiving a request.
* Select a random seed at the time of first receiving a
* request.
*/
while (random_seed == 0)
{
@@ -1186,8 +1194,9 @@ ServerLoop(void)
/*
* We are not sure how much precision is in tv_usec, so we
* swap the nibbles of 'later' and XOR them with 'earlier'. On
* the off chance that the result is 0, we loop until it isn't.
* swap the nibbles of 'later' and XOR them with
* 'earlier'. On the off chance that the result is 0, we
* loop until it isn't.
*/
random_seed = earlier.tv_usec ^
((later.tv_usec << 16) |
@@ -1206,8 +1215,8 @@ ServerLoop(void)
BackendStartup(port);
/*
* We no longer need the open socket or port structure
* in this process
* We no longer need the open socket or port
* structure in this process
*/
StreamClose(port->sock);
ConnFree(port);
@@ -1221,8 +1230,8 @@ ServerLoop(void)
SysLoggerPID = SysLogger_Start();
/*
* If no background writer process is running, and we are not in
* a state that prevents it, start one. It doesn't matter if this
* If no background writer process is running, and we are not in a
* state that prevents it, start one. It doesn't matter if this
* fails, we'll just try again later.
*/
if (BgWriterPID == 0 && StartupPID == 0 && !FatalError)
@@ -1234,18 +1243,19 @@ ServerLoop(void)
}
/* If we have lost the archiver, try to start a new one */
if (XLogArchivingActive() && PgArchPID == 0 &&
StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
if (XLogArchivingActive() && PgArchPID == 0 &&
StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
PgArchPID = pgarch_start();
/* If we have lost the stats collector, try to start a new one */
if (PgStatPID == 0 &&
StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
PgStatPID = pgstat_start();
/*
* Touch the socket and lock file at least every ten minutes, to ensure
* that they are not removed by overzealous /tmp-cleaning tasks.
* Touch the socket and lock file at least every ten minutes, to
* ensure that they are not removed by overzealous /tmp-cleaning
* tasks.
*/
now = time(NULL);
if (now - last_touch_time >= 10 * 60)
@@ -1591,8 +1601,10 @@ processCancelRequest(Port *port, void *pkt)
int backendPID;
long cancelAuthCode;
Backend *bp;
#ifndef EXEC_BACKEND
Dlelem *curr;
#else
int i;
#endif
@@ -1835,6 +1847,7 @@ pmdie(SIGNAL_ARGS)
switch (postgres_signal_arg)
{
case SIGTERM:
/*
* Smart Shutdown:
*
@@ -1869,6 +1882,7 @@ pmdie(SIGNAL_ARGS)
break;
case SIGINT:
/*
* Fast Shutdown:
*
@@ -1896,8 +1910,8 @@ pmdie(SIGNAL_ARGS)
/*
* No children left. Begin shutdown of data base system.
*
* Note: if we previously got SIGTERM then we may send SIGUSR2
* to the bgwriter a second time here. This should be harmless.
* Note: if we previously got SIGTERM then we may send SIGUSR2 to
* the bgwriter a second time here. This should be harmless.
*/
if (StartupPID != 0 || FatalError)
break; /* let reaper() handle this */
@@ -1916,6 +1930,7 @@ pmdie(SIGNAL_ARGS)
break;
case SIGQUIT:
/*
* Immediate Shutdown:
*
@@ -1979,14 +1994,14 @@ reaper(SIGNAL_ARGS)
while ((pid = win32_waitpid(&exitstatus)) > 0)
{
/*
* We need to do this here, and not in CleanupBackend, since this is
* to be called on all children when we are done with them. Could
* move to LogChildExit, but that seems like asking for future
* trouble...
* We need to do this here, and not in CleanupBackend, since this
* is to be called on all children when we are done with them.
* Could move to LogChildExit, but that seems like asking for
* future trouble...
*/
win32_RemoveChild(pid);
#endif /* WIN32 */
#endif /* HAVE_WAITPID */
#endif /* WIN32 */
#endif /* HAVE_WAITPID */
/*
* Check if this child was a startup process.
@@ -2004,12 +2019,13 @@ reaper(SIGNAL_ARGS)
}
/*
* Startup succeeded - we are done with system startup or recovery.
* Startup succeeded - we are done with system startup or
* recovery.
*/
FatalError = false;
/*
* Crank up the background writer. It doesn't matter if this
* Crank up the background writer. It doesn't matter if this
* fails, we'll just try again later.
*/
Assert(BgWriterPID == 0);
@@ -2017,16 +2033,18 @@ reaper(SIGNAL_ARGS)
/*
* Go to shutdown mode if a shutdown request was pending.
* Otherwise, try to start the archiver and stats collector too.
* Otherwise, try to start the archiver and stats collector
* too.
*/
if (Shutdown > NoShutdown && BgWriterPID != 0)
kill(BgWriterPID, SIGUSR2);
else if (Shutdown == NoShutdown) {
if (XLogArchivingActive() && PgArchPID == 0)
PgArchPID = pgarch_start();
if (PgStatPID == 0)
PgStatPID = pgstat_start();
}
else if (Shutdown == NoShutdown)
{
if (XLogArchivingActive() && PgArchPID == 0)
PgArchPID = pgarch_start();
if (PgStatPID == 0)
PgStatPID = pgstat_start();
}
continue;
}
@@ -2041,19 +2059,20 @@ reaper(SIGNAL_ARGS)
!FatalError && !DLGetHead(BackendList))
{
/*
* Normal postmaster exit is here: we've seen normal
* exit of the bgwriter after it's been told to shut down.
* We expect that it wrote a shutdown checkpoint. (If
* for some reason it didn't, recovery will occur on next
* Normal postmaster exit is here: we've seen normal exit
* of the bgwriter after it's been told to shut down. We
* expect that it wrote a shutdown checkpoint. (If for
* some reason it didn't, recovery will occur on next
* postmaster start.)
*
* Note: we do not wait around for exit of the archiver or
* stats processes. They've been sent SIGQUIT by this
* point, and in any case contain logic to commit hara-kiri
* if they notice the postmaster is gone.
* point, and in any case contain logic to commit
* hara-kiri if they notice the postmaster is gone.
*/
ExitPostmaster(0);
}
/*
* Any unexpected exit of the bgwriter is treated as a crash.
*/
@@ -2063,9 +2082,9 @@ reaper(SIGNAL_ARGS)
}
/*
* Was it the archiver? If so, just try to start a new
* one; no need to force reset of the rest of the system. (If fail,
* we'll try again in future cycles of the main loop.)
* Was it the archiver? If so, just try to start a new one; no
* need to force reset of the rest of the system. (If fail, we'll
* try again in future cycles of the main loop.)
*/
if (PgArchPID != 0 && pid == PgArchPID)
{
@@ -2080,9 +2099,9 @@ reaper(SIGNAL_ARGS)
}
/*
* Was it the statistics collector? If so, just try to start a new
* one; no need to force reset of the rest of the system. (If fail,
* we'll try again in future cycles of the main loop.)
* Was it the statistics collector? If so, just try to start a
* new one; no need to force reset of the rest of the system. (If
* fail, we'll try again in future cycles of the main loop.)
*/
if (PgStatPID != 0 && pid == PgStatPID)
{
@@ -2117,8 +2136,8 @@ reaper(SIGNAL_ARGS)
{
/*
* Wait for all important children to exit, then reset shmem and
* StartupDataBase. (We can ignore the archiver and stats processes
* here since they are not connected to shmem.)
* StartupDataBase. (We can ignore the archiver and stats
* processes here since they are not connected to shmem.)
*/
if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0)
goto reaper_done;
@@ -2165,7 +2184,7 @@ reaper_done:
*/
static void
CleanupBackend(int pid,
int exitstatus) /* child's exit status. */
int exitstatus) /* child's exit status. */
{
Dlelem *curr;
@@ -2217,13 +2236,14 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
/*
* Make log entry unless there was a previous crash (if so, nonzero
* exit status is to be expected in SIGQUIT response; don't clutter log)
* exit status is to be expected in SIGQUIT response; don't clutter
* log)
*/
if (!FatalError)
{
LogChildExit(LOG, procname, pid, exitstatus);
ereport(LOG,
(errmsg("terminating any other active server processes")));
(errmsg("terminating any other active server processes")));
}
/* Process regular backends */
@@ -2414,7 +2434,7 @@ BackendStartup(Port *port)
pid = backend_forkexec(port);
#else /* !EXEC_BACKEND */
#else /* !EXEC_BACKEND */
#ifdef LINUX_PROFILE
@@ -2449,8 +2469,7 @@ BackendStartup(Port *port)
proc_exit(BackendRun(port));
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
if (pid < 0)
{
@@ -2669,7 +2688,7 @@ BackendRun(Port *port)
* Build the PostmasterContext (which didn't exist before, in this
* process) to contain the data.
*
* FIXME: [fork/exec] Ugh. Is there a way around this overhead?
* FIXME: [fork/exec] Ugh. Is there a way around this overhead?
*/
#ifdef EXEC_BACKEND
Assert(PostmasterContext == NULL);
@@ -2910,7 +2929,8 @@ internal_forkexec(int argc, char *argv[], Port *port)
}
#endif
return pid; /* Parent returns pid, or -1 on fork failure */
return pid; /* Parent returns pid, or -1 on fork
* failure */
}
/*
@@ -2998,8 +3018,8 @@ SubPostmasterMain(int argc, char *argv[])
if (strcmp(argv[1], "-forkcol") == 0)
{
/*
* Do NOT close postmaster sockets here, because we are forking from
* pgstat buffer process, which already did it.
* Do NOT close postmaster sockets here, because we are forking
* from pgstat buffer process, which already did it.
*/
/* Do not want to attach to shared memory */
@@ -3020,8 +3040,7 @@ SubPostmasterMain(int argc, char *argv[])
return 1; /* shouldn't get here */
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
/*
@@ -3082,9 +3101,9 @@ sigusr1_handler(SIGNAL_ARGS)
* Send SIGUSR1 to archiver process, to wake it up and begin
* archiving next transaction log file.
*/
kill(PgArchPID, SIGUSR1);
kill(PgArchPID, SIGUSR1);
}
}
}
PG_SETMASK(&UnBlockSig);
@@ -3186,9 +3205,7 @@ CountChildren(void)
int cnt = 0;
for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
{
cnt++;
}
return cnt;
}
@@ -3196,7 +3213,7 @@ CountChildren(void)
/*
* StartChildProcess -- start a non-backend child process for the postmaster
*
* xlog determines what kind of child will be started. All child types
* xlog determines what kind of child will be started. All child types
* initially go to BootstrapMain, which will handle common setup.
*
* Return value of StartChildProcess is subprocess' PID, or 0 if failed
@@ -3209,6 +3226,7 @@ StartChildProcess(int xlop)
char *av[10];
int ac = 0;
char xlbuf[32];
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
@@ -3242,7 +3260,7 @@ StartChildProcess(int xlop)
pid = postmaster_forkexec(ac, av);
#else /* !EXEC_BACKEND */
#else /* !EXEC_BACKEND */
#ifdef LINUX_PROFILE
/* see comments in BackendStartup */
@@ -3267,7 +3285,8 @@ StartChildProcess(int xlop)
beos_backend_startup();
#endif
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
IsUnderPostmaster = true; /* we are a postmaster subprocess
* now */
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);
@@ -3283,8 +3302,7 @@ StartChildProcess(int xlop)
BootstrapMain(ac, av);
ExitPostmaster(0);
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
if (pid < 0)
{
@@ -3304,7 +3322,7 @@ StartChildProcess(int xlop)
break;
case BS_XLOG_BGWRITER:
ereport(LOG,
(errmsg("could not fork background writer process: %m")));
(errmsg("could not fork background writer process: %m")));
break;
default:
ereport(LOG,
@@ -3313,8 +3331,8 @@ StartChildProcess(int xlop)
}
/*
* fork failure is fatal during startup, but there's no need
* to choke immediately if starting other child types fails.
* fork failure is fatal during startup, but there's no need to
* choke immediately if starting other child types fails.
*/
if (xlop == BS_XLOG_STARTUP)
ExitPostmaster(1);
@@ -3380,7 +3398,7 @@ 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 write_array_var(var,fp) fwrite((void*)(var),sizeof(var),1,fp)
#define read_array_var(var,fp) fread((void*)(var),sizeof(var),1,fp)
#define read_array_var(var,fp) fread((void*)(var),sizeof(var),1,fp)
static bool
write_backend_variables(char *filename, Port *port)
@@ -3492,8 +3510,8 @@ read_backend_variables(char *filename, Port *port)
if (!fp)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read from backend variables file \"%s\": %m",
filename)));
errmsg("could not read from backend variables file \"%s\": %m",
filename)));
/* Read vars */
read_var(port->sock, fp);
@@ -3606,8 +3624,7 @@ ShmemBackendArrayRemove(pid_t pid)
(errmsg_internal("could not find backend entry with pid %d",
(int) pid)));
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
#ifdef WIN32
@@ -3624,16 +3641,16 @@ win32_forkexec(const char *path, char *argv[])
HANDLE waiterThread;
/* Format the cmd line */
cmdLine[sizeof(cmdLine)-1] = '\0';
cmdLine[sizeof(cmdLine)-2] = '\0';
snprintf(cmdLine, sizeof(cmdLine)-1, "\"%s\"", path);
cmdLine[sizeof(cmdLine) - 1] = '\0';
cmdLine[sizeof(cmdLine) - 2] = '\0';
snprintf(cmdLine, sizeof(cmdLine) - 1, "\"%s\"", path);
i = 0;
while (argv[++i] != NULL)
{
j = strlen(cmdLine);
snprintf(cmdLine+j, sizeof(cmdLine)-1-j, " \"%s\"", argv[i]);
snprintf(cmdLine + j, sizeof(cmdLine) - 1 - j, " \"%s\"", argv[i]);
}
if (cmdLine[sizeof(cmdLine)-2] != '\0')
if (cmdLine[sizeof(cmdLine) - 2] != '\0')
{
elog(LOG, "subprocess command line too long");
return -1;
@@ -3669,8 +3686,8 @@ win32_forkexec(const char *path, char *argv[])
(LPVOID) childHandleCopy, 0, NULL);
if (!waiterThread)
ereport(FATAL,
(errmsg_internal("could not create sigchld waiter thread: %d",
(int) GetLastError())));
(errmsg_internal("could not create sigchld waiter thread: %d",
(int) GetLastError())));
CloseHandle(waiterThread);
if (IsUnderPostmaster)
@@ -3736,13 +3753,13 @@ win32_RemoveChild(pid_t pid)
static pid_t
win32_waitpid(int *exitstatus)
{
/*
* Note: Do NOT use WaitForMultipleObjectsEx, as we don't want to
* run queued APCs here.
*/
int index;
DWORD exitCode;
DWORD ret;
/*
* Note: Do NOT use WaitForMultipleObjectsEx, as we don't want to run
* queued APCs here.
*/
int index;
DWORD exitCode;
DWORD ret;
unsigned long offset;
Assert(win32_childPIDArray && win32_childHNDArray);
@@ -3751,13 +3768,14 @@ win32_waitpid(int *exitstatus)
for (offset = 0; offset < win32_numChildren; offset += MAXIMUM_WAIT_OBJECTS)
{
unsigned long num = min(MAXIMUM_WAIT_OBJECTS, win32_numChildren - offset);
ret = WaitForMultipleObjects(num, &win32_childHNDArray[offset], FALSE, 0);
switch (ret)
{
case WAIT_FAILED:
ereport(LOG,
(errmsg_internal("failed to wait on %lu of %lu children: %d",
num, win32_numChildren, (int) GetLastError())));
num, win32_numChildren, (int) GetLastError())));
return -1;
case WAIT_TIMEOUT:
@@ -3765,6 +3783,7 @@ win32_waitpid(int *exitstatus)
break;
default:
/*
* Get the exit code, and return the PID of, the
* respective process
@@ -3806,9 +3825,9 @@ win32_sigchld_waiter(LPVOID param)
pg_queue_signal(SIGCHLD);
else
write_stderr("ERROR: failed to wait on child process handle: %d\n",
(int) GetLastError());
(int) GetLastError());
CloseHandle(procHandle);
return 0;
}
#endif /* WIN32 */
#endif /* WIN32 */

View File

@@ -18,7 +18,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.6 2004/08/29 00:38:03 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.7 2004/08/29 05:06:46 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,40 +55,41 @@
/*
* GUC parameters. Redirect_stderr cannot be changed after postmaster
* GUC parameters. Redirect_stderr cannot be changed after postmaster
* start, but the rest can change at SIGHUP.
*/
bool Redirect_stderr = false;
int Log_RotationAge = 24*60;
int Log_RotationSize = 10*1024;
char * Log_directory = "pg_log";
char * Log_filename_prefix = "postgresql-";
int Log_RotationAge = 24 * 60;
int Log_RotationSize = 10 * 1024;
char *Log_directory = "pg_log";
char *Log_filename_prefix = "postgresql-";
/*
* Globally visible state (used by elog.c)
*/
bool am_syslogger = false;
bool am_syslogger = false;
/*
* Private state
*/
static pg_time_t last_rotation_time = 0;
static pg_time_t last_rotation_time = 0;
static bool redirection_done = false;
static bool redirection_done = false;
static bool pipe_eof_seen = false;
static bool pipe_eof_seen = false;
static FILE *syslogFile = NULL;
/* These must be exported for EXEC_BACKEND case ... annoying */
#ifndef WIN32
int syslogPipe[2] = {-1, -1};
int syslogPipe[2] = {-1, -1};
#else
HANDLE syslogPipe[2] = {0, 0};
HANDLE syslogPipe[2] = {0, 0};
#endif
#ifdef WIN32
static HANDLE threadHandle=0;
static HANDLE threadHandle = 0;
static CRITICAL_SECTION sysfileSection;
#endif
@@ -104,11 +105,12 @@ static pid_t syslogger_forkexec(void);
static void syslogger_parseArgs(int argc, char *argv[]);
#endif
static void write_syslogger_file_binary(const char *buffer, int count);
#ifdef WIN32
static unsigned int __stdcall pipeThread(void *arg);
#endif
static void logfile_rotate(void);
static char* logfile_getname(pg_time_t timestamp);
static char *logfile_getname(pg_time_t timestamp);
static void sigHupHandler(SIGNAL_ARGS);
@@ -119,7 +121,7 @@ static void sigHupHandler(SIGNAL_ARGS);
NON_EXEC_STATIC void
SysLoggerMain(int argc, char *argv[])
{
char currentLogDir[MAXPGPATH];
char currentLogDir[MAXPGPATH];
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
@@ -130,7 +132,7 @@ SysLoggerMain(int argc, char *argv[])
#ifdef EXEC_BACKEND
syslogger_parseArgs(argc, argv);
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
am_syslogger = true;
@@ -139,20 +141,21 @@ SysLoggerMain(int argc, char *argv[])
/*
* If we restarted, our stderr is already redirected into our own
* input pipe. This is of course pretty useless, not to mention that
* input pipe. This is of course pretty useless, not to mention that
* it interferes with detecting pipe EOF. Point stderr to /dev/null.
* This assumes that all interesting messages generated in the syslogger
* will come through elog.c and will be sent to write_syslogger_file.
* This assumes that all interesting messages generated in the
* syslogger will come through elog.c and will be sent to
* write_syslogger_file.
*/
if (redirection_done)
{
int fd = open(NULL_DEV, O_WRONLY);
int fd = open(NULL_DEV, O_WRONLY);
/*
* The closes might look redundant, but they are not: we want to be
* darn sure the pipe gets closed even if the open failed. We can
* survive running with stderr pointing nowhere, but we can't afford
* to have extra pipe input descriptors hanging around.
* The closes might look redundant, but they are not: we want to
* be darn sure the pipe gets closed even if the open failed. We
* can survive running with stderr pointing nowhere, but we can't
* afford to have extra pipe input descriptors hanging around.
*/
close(fileno(stdout));
close(fileno(stderr));
@@ -163,7 +166,7 @@ SysLoggerMain(int argc, char *argv[])
/*
* Also close our copy of the write end of the pipe. This is needed
* to ensure we can detect pipe EOF correctly. (But note that in the
* to ensure we can detect pipe EOF correctly. (But note that in the
* restart case, the postmaster already did this.)
*/
#ifndef WIN32
@@ -185,7 +188,7 @@ SysLoggerMain(int argc, char *argv[])
*/
pqsignal(SIGHUP, sigHupHandler); /* set flag to read config file */
pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGTERM, SIG_IGN);
pqsignal(SIGQUIT, SIG_IGN);
pqsignal(SIGALRM, SIG_IGN);
@@ -211,9 +214,9 @@ SysLoggerMain(int argc, char *argv[])
{
unsigned int tid;
threadHandle = (HANDLE)_beginthreadex(0, 0, pipeThread, 0, 0, &tid);
threadHandle = (HANDLE) _beginthreadex(0, 0, pipeThread, 0, 0, &tid);
}
#endif /* WIN32 */
#endif /* WIN32 */
/* remember age of initial logfile */
last_rotation_time = time(NULL);
@@ -223,11 +226,12 @@ SysLoggerMain(int argc, char *argv[])
/* main worker loop */
for (;;)
{
bool rotation_requested = false;
bool rotation_requested = false;
#ifndef WIN32
char logbuffer[1024];
int bytesRead;
int rc;
char logbuffer[1024];
int bytesRead;
int rc;
fd_set rfds;
struct timeval timeout;
#endif
@@ -238,9 +242,9 @@ SysLoggerMain(int argc, char *argv[])
ProcessConfigFile(PGC_SIGHUP);
/*
* Check if the log directory changed in postgresql.conf. If so,
* force rotation to make sure we're writing the logfiles in the
* right place.
* Check if the log directory changed in postgresql.conf. If
* so, force rotation to make sure we're writing the logfiles
* in the right place.
*
* XXX is it worth responding similarly to a change of
* Log_filename_prefix?
@@ -257,11 +261,11 @@ SysLoggerMain(int argc, char *argv[])
Log_RotationAge > 0)
{
/*
* Do a logfile rotation if too much time has elapsed
* since the last one.
* Do a logfile rotation if too much time has elapsed since
* the last one.
*/
pg_time_t now = time(NULL);
int elapsed_secs = now - last_rotation_time;
pg_time_t now = time(NULL);
int elapsed_secs = now - last_rotation_time;
if (elapsed_secs >= Log_RotationAge * 60)
rotation_requested = true;
@@ -280,26 +284,27 @@ SysLoggerMain(int argc, char *argv[])
logfile_rotate();
#ifndef WIN32
/*
* Wait for some data, timing out after 1 second
*/
FD_ZERO(&rfds);
FD_SET(syslogPipe[0], &rfds);
timeout.tv_sec=1;
timeout.tv_usec=0;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
rc = select(syslogPipe[0]+1, &rfds, NULL, NULL, &timeout);
rc = select(syslogPipe[0] + 1, &rfds, NULL, NULL, &timeout);
if (rc < 0)
{
if (errno != EINTR)
ereport(LOG,
(errcode_for_socket_access(),
errmsg("select() failed in logger process: %m")));
errmsg("select() failed in logger process: %m")));
}
else if (rc > 0 && FD_ISSET(syslogPipe[0], &rfds))
{
bytesRead = piperead(syslogPipe[0],
bytesRead = piperead(syslogPipe[0],
logbuffer, sizeof(logbuffer));
if (bytesRead < 0)
@@ -307,7 +312,7 @@ SysLoggerMain(int argc, char *argv[])
if (errno != EINTR)
ereport(LOG,
(errcode_for_socket_access(),
errmsg("could not read from logger pipe: %m")));
errmsg("could not read from logger pipe: %m")));
}
else if (bytesRead > 0)
{
@@ -318,33 +323,35 @@ SysLoggerMain(int argc, char *argv[])
{
/*
* Zero bytes read when select() is saying read-ready
* means EOF on the pipe: that is, there are no longer
* any processes with the pipe write end open. Therefore,
* the postmaster and all backends are shut down, and we
* are done.
* means EOF on the pipe: that is, there are no longer any
* processes with the pipe write end open. Therefore, the
* postmaster and all backends are shut down, and we are
* done.
*/
pipe_eof_seen = true;
}
}
#else /* WIN32 */
#else /* WIN32 */
/*
* On Windows we leave it to a separate thread to transfer data and
* detect pipe EOF. The main thread just wakes up once a second to
* check for SIGHUP and rotation conditions.
* On Windows we leave it to a separate thread to transfer data
* and detect pipe EOF. The main thread just wakes up once a
* second to check for SIGHUP and rotation conditions.
*/
pgwin32_backend_usleep(1000000);
#endif /* WIN32 */
#endif /* WIN32 */
if (pipe_eof_seen)
{
ereport(LOG,
(errmsg("logger shutting down")));
/*
* Normal exit from the syslogger is here. Note that we
* deliberately do not close syslogFile before exiting;
* this is to allow for the possibility of elog messages
* being generated inside proc_exit. Regular exit() will
* take care of flushing and closing stdio channels.
* Normal exit from the syslogger is here. Note that we
* deliberately do not close syslogFile before exiting; this
* is to allow for the possibility of elog messages being
* generated inside proc_exit. Regular exit() will take care
* of flushing and closing stdio channels.
*/
proc_exit(0);
}
@@ -357,34 +364,35 @@ SysLoggerMain(int argc, char *argv[])
int
SysLogger_Start(void)
{
pid_t sysloggerPid;
pg_time_t now;
char *filename;
pid_t sysloggerPid;
pg_time_t now;
char *filename;
if (!Redirect_stderr)
return 0;
return 0;
/*
* If first time through, create the pipe which will receive stderr output.
* If first time through, create the pipe which will receive stderr
* output.
*
* If the syslogger crashes and needs to be restarted, we continue to use
* the same pipe (indeed must do so, since extant backends will be writing
* into that pipe).
* the same pipe (indeed must do so, since extant backends will be
* writing into that pipe).
*
* This means the postmaster must continue to hold the read end of the
* pipe open, so we can pass it down to the reincarnated syslogger.
* This is a bit klugy but we have little choice.
*/
#ifndef WIN32
if (syslogPipe[0] < 0)
if (syslogPipe[0] < 0)
{
if (pgpipe(syslogPipe) < 0)
ereport(FATAL,
if (pgpipe(syslogPipe) < 0)
ereport(FATAL,
(errcode_for_socket_access(),
(errmsg("could not create pipe for syslogging: %m"))));
(errmsg("could not create pipe for syslogging: %m"))));
}
#else
if (!syslogPipe[0])
if (!syslogPipe[0])
{
SECURITY_ATTRIBUTES sa;
@@ -393,9 +401,9 @@ SysLogger_Start(void)
sa.bInheritHandle = TRUE;
if (!CreatePipe(&syslogPipe[0], &syslogPipe[1], &sa, 32768))
ereport(FATAL,
ereport(FATAL,
(errcode_for_file_access(),
(errmsg("could not create pipe for syslogging: %m"))));
(errmsg("could not create pipe for syslogging: %m"))));
}
#endif
@@ -413,8 +421,8 @@ SysLogger_Start(void)
}
/*
* The initial logfile is created right in the postmaster,
* to verify that the Log_directory is writable.
* The initial logfile is created right in the postmaster, to verify
* that the Log_directory is writable.
*/
now = time(NULL);
filename = logfile_getname(now);
@@ -422,7 +430,7 @@ SysLogger_Start(void)
syslogFile = fopen(filename, "a");
if (!syslogFile)
ereport(FATAL,
ereport(FATAL,
(errcode_for_file_access(),
(errmsg("could not create logfile \"%s\": %m",
filename))));
@@ -496,7 +504,7 @@ SysLogger_Start(void)
close(syslogPipe[1]);
syslogPipe[1] = -1;
#else
int fd;
int fd;
fflush(stderr);
fd = _open_osfhandle((long) syslogPipe[1],
@@ -534,9 +542,11 @@ SysLogger_Start(void)
static pid_t
syslogger_forkexec(void)
{
char *av[10];
int ac = 0, bufc = 0, i;
char numbuf[2][32];
char *av[10];
int ac = 0,
bufc = 0,
i;
char numbuf[2][32];
av[ac++] = "postgres";
av[ac++] = "-forklog";
@@ -545,18 +555,18 @@ syslogger_forkexec(void)
/* static variables (those not passed by write_backend_variables) */
#ifndef WIN32
if (syslogFile != NULL)
snprintf(numbuf[bufc++], 32, "%d", fileno(syslogFile));
else
strcpy(numbuf[bufc++], "-1");
snprintf(numbuf[bufc++], 32, "%d", fileno(syslogFile));
else
strcpy(numbuf[bufc++], "-1");
snprintf(numbuf[bufc++], 32, "%d", (int) redirection_done);
#else /* WIN32 */
#else /* WIN32 */
if (syslogFile != NULL)
snprintf(numbuf[bufc++], 32, "%ld",
snprintf(numbuf[bufc++], 32, "%ld",
_get_osfhandle(_fileno(syslogFile)));
else
strcpy(numbuf[bufc++], "0");
else
strcpy(numbuf[bufc++], "0");
snprintf(numbuf[bufc++], 32, "%d", (int) redirection_done);
#endif /* WIN32 */
#endif /* WIN32 */
/* Add to the arg list */
Assert(bufc <= lengthof(numbuf));
@@ -577,7 +587,7 @@ syslogger_forkexec(void)
static void
syslogger_parseArgs(int argc, char *argv[])
{
int fd;
int fd;
Assert(argc == 5);
argv += 3;
@@ -586,11 +596,11 @@ syslogger_parseArgs(int argc, char *argv[])
fd = atoi(*argv++);
if (fd != -1)
{
syslogFile = fdopen(fd, "a");
syslogFile = fdopen(fd, "a");
setvbuf(syslogFile, NULL, LBF_MODE, 0);
}
redirection_done = (bool) atoi(*argv++);
#else /* WIN32 */
#else /* WIN32 */
fd = atoi(*argv++);
if (fd != 0)
{
@@ -602,10 +612,9 @@ syslogger_parseArgs(int argc, char *argv[])
}
}
redirection_done = (bool) atoi(*argv++);
#endif /* WIN32 */
#endif /* WIN32 */
}
#endif /* EXEC_BACKEND */
#endif /* EXEC_BACKEND */
/* --------------------------------
@@ -624,23 +633,24 @@ void
write_syslogger_file(const char *buffer, int count)
{
#ifdef WIN32
/*
* On Windows we need to do our own newline-to-CRLF translation.
*/
char convbuf[256];
char *p;
int n;
char convbuf[256];
char *p;
int n;
p = convbuf;
n = 0;
while (count-- > 0)
{
if (*buffer == '\n')
{
*p++ = '\r';
if (*buffer == '\n')
{
*p++ = '\r';
n++;
}
*p++ = *buffer++;
}
*p++ = *buffer++;
n++;
if (n >= sizeof(convbuf) - 1)
{
@@ -648,10 +658,10 @@ write_syslogger_file(const char *buffer, int count)
p = convbuf;
n = 0;
}
}
}
if (n > 0)
write_syslogger_file_binary(convbuf, n);
#else /* !WIN32 */
#else /* !WIN32 */
write_syslogger_file_binary(buffer, count);
#endif
}
@@ -665,18 +675,18 @@ write_syslogger_file(const char *buffer, int count)
static void
write_syslogger_file_binary(const char *buffer, int count)
{
int rc;
int rc;
#ifndef WIN32
rc = fwrite(buffer, 1, count, syslogFile);
rc = fwrite(buffer, 1, count, syslogFile);
#else
EnterCriticalSection(&sysfileSection);
rc = fwrite(buffer, 1, count, syslogFile);
LeaveCriticalSection(&sysfileSection);
EnterCriticalSection(&sysfileSection);
rc = fwrite(buffer, 1, count, syslogFile);
LeaveCriticalSection(&sysfileSection);
#endif
if (rc != count)
ereport(LOG,
if (rc != count)
ereport(LOG,
(errcode_for_file_access(),
errmsg("could not write to logfile: %m")));
}
@@ -693,15 +703,15 @@ write_syslogger_file_binary(const char *buffer, int count)
static unsigned int __stdcall
pipeThread(void *arg)
{
DWORD bytesRead;
char logbuffer[1024];
DWORD bytesRead;
char logbuffer[1024];
for (;;)
{
if (!ReadFile(syslogPipe[0], logbuffer, sizeof(logbuffer),
for (;;)
{
if (!ReadFile(syslogPipe[0], logbuffer, sizeof(logbuffer),
&bytesRead, 0))
{
DWORD error = GetLastError();
DWORD error = GetLastError();
if (error == ERROR_HANDLE_EOF ||
error == ERROR_BROKEN_PIPE)
@@ -711,17 +721,16 @@ pipeThread(void *arg)
(errcode_for_file_access(),
errmsg("could not read from logger pipe: %m")));
}
else if (bytesRead > 0)
write_syslogger_file_binary(logbuffer, bytesRead);
}
else if (bytesRead > 0)
write_syslogger_file_binary(logbuffer, bytesRead);
}
/* We exit the above loop only upon detecting pipe EOF */
pipe_eof_seen = true;
_endthread();
return 0;
_endthread();
return 0;
}
#endif /* WIN32 */
#endif /* WIN32 */
/*
* perform logfile rotation
@@ -729,9 +738,9 @@ pipeThread(void *arg)
static void
logfile_rotate(void)
{
char *filename;
pg_time_t now;
FILE *fh;
char *filename;
pg_time_t now;
FILE *fh;
now = time(NULL);
filename = logfile_getname(now);
@@ -739,7 +748,7 @@ logfile_rotate(void)
fh = fopen(filename, "a");
if (!fh)
{
int saveerrno = errno;
int saveerrno = errno;
ereport(LOG,
(errcode_for_file_access(),
@@ -747,15 +756,15 @@ logfile_rotate(void)
filename)));
/*
* ENFILE/EMFILE are not too surprising on a busy system; just keep
* using the old file till we manage to get a new one. Otherwise,
* assume something's wrong with Log_directory and stop trying to
* create files.
* ENFILE/EMFILE are not too surprising on a busy system; just
* keep using the old file till we manage to get a new one.
* Otherwise, assume something's wrong with Log_directory and stop
* trying to create files.
*/
if (saveerrno != ENFILE && saveerrno != EMFILE)
{
ereport(LOG,
(errmsg("disabling auto rotation (use SIGHUP to reenable)")));
(errmsg("disabling auto rotation (use SIGHUP to reenable)")));
Log_RotationAge = 0;
Log_RotationSize = 0;
}
@@ -786,11 +795,11 @@ logfile_rotate(void)
*
* Result is palloc'd.
*/
static char*
static char *
logfile_getname(pg_time_t timestamp)
{
char *filename;
char stamptext[128];
char *filename;
char stamptext[128];
pg_strftime(stamptext, sizeof(stamptext), "%Y-%m-%d_%H%M%S",
pg_localtime(&timestamp));
@@ -818,5 +827,5 @@ logfile_getname(pg_time_t timestamp)
static void
sigHupHandler(SIGNAL_ARGS)
{
got_SIGHUP = true;
got_SIGHUP = true;
}