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:
@@ -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);
|
||||
}
|
||||
|
@@ -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)));
|
||||
|
@@ -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))
|
||||
{
|
||||
|
@@ -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 */
|
||||
|
@@ -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(×tamp));
|
||||
@@ -818,5 +827,5 @@ logfile_getname(pg_time_t timestamp)
|
||||
static void
|
||||
sigHupHandler(SIGNAL_ARGS)
|
||||
{
|
||||
got_SIGHUP = true;
|
||||
got_SIGHUP = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user