Use setitimer() for stats file write, rather than do a gettimeofday()
call for every stats packet read to adjust select() timeout. Other stylistic improvements.
This commit is contained in:
parent
fd924b2988
commit
447450df71
@ -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;
|
|||||||
|
|
||||||
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;
|
|||||||
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[]);
|
|||||||
|
|
||||||
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,12 +1550,10 @@ 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[])
|
|||||||
/* 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[])
|
|||||||
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[])
|
|||||||
*/
|
*/
|
||||||
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[])
|
|||||||
/*
|
/*
|
||||||
* 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[])
|
|||||||
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[])
|
|||||||
*/
|
*/
|
||||||
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[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
force_statwrite(SIGNAL_ARGS)
|
||||||
|
{
|
||||||
|
need_statwrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* pgstat_recvbuffer() -
|
* pgstat_recvbuffer() -
|
||||||
*
|
*
|
||||||
@ -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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user