Commit 447450df authored by Bruce Momjian's avatar Bruce Momjian

Use setitimer() for stats file write, rather than do a gettimeofday()

call for every stats packet read to adjust select() timeout.  Other
stylistic improvements.
parent fd924b29
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2005, PostgreSQL Global Development Group * Copyright (c) 2001-2005, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.116 2006/01/02 00:58:00 momjian Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.117 2006/01/03 16:42:17 momjian Exp $
* ---------- * ----------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -117,7 +117,7 @@ static time_t last_pgstat_start_time; ...@@ -117,7 +117,7 @@ static time_t last_pgstat_start_time;
static long pgStatNumMessages = 0; static long pgStatNumMessages = 0;
static bool pgStatRunningInCollector = FALSE; static bool pgStatRunningInCollector = false;
/* /*
* Place where backends store per-table info to be sent to the collector. * Place where backends store per-table info to be sent to the collector.
...@@ -145,6 +145,7 @@ static HTAB *pgStatBeDead = NULL; ...@@ -145,6 +145,7 @@ static HTAB *pgStatBeDead = NULL;
static PgStat_StatBeEntry *pgStatBeTable = NULL; static PgStat_StatBeEntry *pgStatBeTable = NULL;
static int pgStatNumBackends = 0; static int pgStatNumBackends = 0;
static volatile bool need_statwrite;
/* ---------- /* ----------
* Local function forward declarations * Local function forward declarations
...@@ -164,6 +165,7 @@ static void pgstat_parseArgs(int argc, char *argv[]); ...@@ -164,6 +165,7 @@ static void pgstat_parseArgs(int argc, char *argv[]);
NON_EXEC_STATIC void PgstatBufferMain(int argc, char *argv[]); NON_EXEC_STATIC void PgstatBufferMain(int argc, char *argv[]);
NON_EXEC_STATIC void PgstatCollectorMain(int argc, char *argv[]); NON_EXEC_STATIC void PgstatCollectorMain(int argc, char *argv[]);
static void force_statwrite(SIGNAL_ARGS);
static void pgstat_recvbuffer(void); static void pgstat_recvbuffer(void);
static void pgstat_exit(SIGNAL_ARGS); static void pgstat_exit(SIGNAL_ARGS);
static void pgstat_die(SIGNAL_ARGS); static void pgstat_die(SIGNAL_ARGS);
...@@ -1548,13 +1550,11 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1548,13 +1550,11 @@ PgstatCollectorMain(int argc, char *argv[])
PgStat_Msg msg; PgStat_Msg msg;
fd_set rfds; fd_set rfds;
int readPipe; int readPipe;
int nready;
int len = 0; int len = 0;
struct timeval timeout; struct itimerval timeval;
struct timeval next_statwrite;
bool need_statwrite;
HASHCTL hash_ctl; HASHCTL hash_ctl;
bool need_timer = false;
MyProcPid = getpid(); /* reset MyProcPid */ MyProcPid = getpid(); /* reset MyProcPid */
/* /*
...@@ -1572,7 +1572,7 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1572,7 +1572,7 @@ PgstatCollectorMain(int argc, char *argv[])
/* kluge to allow buffer process to kill collector; FIXME */ /* kluge to allow buffer process to kill collector; FIXME */
pqsignal(SIGQUIT, pgstat_exit); pqsignal(SIGQUIT, pgstat_exit);
#endif #endif
pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGALRM, force_statwrite);
pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, SIG_IGN); pqsignal(SIGUSR1, SIG_IGN);
pqsignal(SIGUSR2, SIG_IGN); pqsignal(SIGUSR2, SIG_IGN);
...@@ -1597,17 +1597,17 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1597,17 +1597,17 @@ PgstatCollectorMain(int argc, char *argv[])
init_ps_display("stats collector process", "", ""); init_ps_display("stats collector process", "", "");
set_ps_display(""); set_ps_display("");
/* need_statwrite = true;
* Arrange to write the initial status file right away
*/ MemSet(&timeval, 0, sizeof(struct itimerval));
gettimeofday(&next_statwrite, NULL); timeval.it_value.tv_sec = PGSTAT_STAT_INTERVAL / 1000;
need_statwrite = TRUE; timeval.it_value.tv_usec = PGSTAT_STAT_INTERVAL % 1000;
/* /*
* Read in an existing statistics stats file or initialize the stats to * Read in an existing statistics stats file or initialize the stats to
* zero. * zero.
*/ */
pgStatRunningInCollector = TRUE; pgStatRunningInCollector = true;
pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL); pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL);
/* /*
...@@ -1634,34 +1634,11 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1634,34 +1634,11 @@ PgstatCollectorMain(int argc, char *argv[])
*/ */
for (;;) for (;;)
{ {
/*
* If we need to write the status file again (there have been changes
* in the statistics since we wrote it last) calculate the timeout
* until we have to do so.
*/
if (need_statwrite) if (need_statwrite)
{ {
struct timeval now; pgstat_write_statsfile();
need_statwrite = false;
gettimeofday(&now, NULL); need_timer = true;
/* avoid assuming that tv_sec is signed */
if (now.tv_sec > next_statwrite.tv_sec ||
(now.tv_sec == next_statwrite.tv_sec &&
now.tv_usec >= next_statwrite.tv_usec))
{
timeout.tv_sec = 0;
timeout.tv_usec = 0;
}
else
{
timeout.tv_sec = next_statwrite.tv_sec - now.tv_sec;
timeout.tv_usec = next_statwrite.tv_usec - now.tv_usec;
if (timeout.tv_usec < 0)
{
timeout.tv_sec--;
timeout.tv_usec += 1000000;
}
}
} }
/* /*
...@@ -1673,9 +1650,7 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1673,9 +1650,7 @@ PgstatCollectorMain(int argc, char *argv[])
/* /*
* Now wait for something to do. * Now wait for something to do.
*/ */
nready = select(readPipe + 1, &rfds, NULL, NULL, if (select(readPipe + 1, &rfds, NULL, NULL, NULL) < 0)
(need_statwrite) ? &timeout : NULL);
if (nready < 0)
{ {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
...@@ -1684,18 +1659,6 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1684,18 +1659,6 @@ PgstatCollectorMain(int argc, char *argv[])
errmsg("select() failed in statistics collector: %m"))); errmsg("select() failed in statistics collector: %m")));
} }
/*
* If there are no descriptors ready, our timeout for writing the
* stats file happened.
*/
if (nready == 0)
{
pgstat_write_statsfile();
need_statwrite = FALSE;
continue;
}
/* /*
* Check if there is a new statistics message to collect. * Check if there is a new statistics message to collect.
*/ */
...@@ -1813,17 +1776,12 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1813,17 +1776,12 @@ PgstatCollectorMain(int argc, char *argv[])
*/ */
pgStatNumMessages++; pgStatNumMessages++;
/* if (need_timer)
* If this is the first message after we wrote the stats file the
* last time, setup the timeout that it'd be written.
*/
if (!need_statwrite)
{ {
gettimeofday(&next_statwrite, NULL); if (setitimer(ITIMER_REAL, &timeval, NULL))
next_statwrite.tv_usec += ((PGSTAT_STAT_INTERVAL) * 1000); ereport(ERROR,
next_statwrite.tv_sec += (next_statwrite.tv_usec / 1000000); (errmsg("unable to set statistics collector timer: %m")));
next_statwrite.tv_usec %= 1000000; need_timer = false;
need_statwrite = TRUE;
} }
} }
...@@ -1848,6 +1806,13 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1848,6 +1806,13 @@ PgstatCollectorMain(int argc, char *argv[])
} }
static void
force_statwrite(SIGNAL_ARGS)
{
need_statwrite = true;
}
/* ---------- /* ----------
* pgstat_recvbuffer() - * pgstat_recvbuffer() -
* *
...@@ -1865,7 +1830,6 @@ pgstat_recvbuffer(void) ...@@ -1865,7 +1830,6 @@ pgstat_recvbuffer(void)
struct timeval timeout; struct timeval timeout;
int writePipe = pgStatPipe[1]; int writePipe = pgStatPipe[1];
int maxfd; int maxfd;
int nready;
int len; int len;
int xfr; int xfr;
int frm; int frm;
...@@ -1906,6 +1870,14 @@ pgstat_recvbuffer(void) ...@@ -1906,6 +1870,14 @@ pgstat_recvbuffer(void)
*/ */
msgbuffer = (char *) palloc(PGSTAT_RECVBUFFERSZ); msgbuffer = (char *) palloc(PGSTAT_RECVBUFFERSZ);
/*
* Wait for some work to do; but not for more than 10 seconds. (This
* determines how quickly we will shut down after an ungraceful
* postmaster termination; so it needn't be very fast.)
*/
timeout.tv_sec = 10;
timeout.tv_usec = 0;
/* /*
* Loop forever * Loop forever
*/ */
...@@ -1946,16 +1918,7 @@ pgstat_recvbuffer(void) ...@@ -1946,16 +1918,7 @@ pgstat_recvbuffer(void)
maxfd = writePipe; maxfd = writePipe;
} }
/* if (select(maxfd + 1, &rfds, &wfds, NULL, &timeout) < 0)
* Wait for some work to do; but not for more than 10 seconds. (This
* determines how quickly we will shut down after an ungraceful
* postmaster termination; so it needn't be very fast.)
*/
timeout.tv_sec = 10;
timeout.tv_usec = 0;
nready = select(maxfd + 1, &rfds, &wfds, NULL, &timeout);
if (nready < 0)
{ {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment