1313 *
1414 *Copyright (c) 2001-2005, PostgreSQL Global Development Group
1515 *
16- *$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.116 2006/01/02 00:58:00 momjian Exp $
16+ *$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.117 2006/01/03 16:42:17 momjian Exp $
1717 * ----------
1818 */
1919#include "postgres.h"
@@ -117,7 +117,7 @@ static time_t last_pgstat_start_time;
117117
118118static long pgStatNumMessages = 0 ;
119119
120- static bool pgStatRunningInCollector = FALSE ;
120+ static bool pgStatRunningInCollector = false ;
121121
122122/*
123123 * Place where backends store per-table info to be sent to the collector.
@@ -145,6 +145,7 @@ static HTAB *pgStatBeDead = NULL;
145145static PgStat_StatBeEntry * pgStatBeTable = NULL ;
146146static int pgStatNumBackends = 0 ;
147147
148+ static volatile bool need_statwrite ;
148149
149150/* ----------
150151 * Local function forward declarations
@@ -164,6 +165,7 @@ static void pgstat_parseArgs(int argc, char *argv[]);
164165
165166NON_EXEC_STATIC void PgstatBufferMain (int argc ,char * argv []);
166167NON_EXEC_STATIC void PgstatCollectorMain (int argc ,char * argv []);
168+ static void force_statwrite (SIGNAL_ARGS );
167169static void pgstat_recvbuffer (void );
168170static void pgstat_exit (SIGNAL_ARGS );
169171static void pgstat_die (SIGNAL_ARGS );
@@ -1548,13 +1550,11 @@ PgstatCollectorMain(int argc, char *argv[])
15481550PgStat_Msg msg ;
15491551fd_set rfds ;
15501552int readPipe ;
1551- int nready ;
15521553int len = 0 ;
1553- struct timeval timeout ;
1554- struct timeval next_statwrite ;
1555- bool need_statwrite ;
1554+ struct itimerval timeval ;
15561555HASHCTL hash_ctl ;
1557-
1556+ bool need_timer = false;
1557+
15581558MyProcPid = getpid ();/* reset MyProcPid */
15591559
15601560/*
@@ -1572,7 +1572,7 @@ PgstatCollectorMain(int argc, char *argv[])
15721572/* kluge to allow buffer process to kill collector; FIXME */
15731573pqsignal (SIGQUIT ,pgstat_exit );
15741574#endif
1575- pqsignal (SIGALRM ,SIG_IGN );
1575+ pqsignal (SIGALRM ,force_statwrite );
15761576pqsignal (SIGPIPE ,SIG_IGN );
15771577pqsignal (SIGUSR1 ,SIG_IGN );
15781578pqsignal (SIGUSR2 ,SIG_IGN );
@@ -1597,17 +1597,17 @@ PgstatCollectorMain(int argc, char *argv[])
15971597init_ps_display ("stats collector process" ,"" ,"" );
15981598set_ps_display ("" );
15991599
1600- /*
1601- * Arrange to write the initial status file right away
1602- */
1603- gettimeofday ( & next_statwrite , NULL ) ;
1604- need_statwrite = TRUE ;
1600+ need_statwrite = true;
1601+
1602+ MemSet ( & timeval , 0 , sizeof ( struct itimerval ));
1603+ timeval . it_value . tv_sec = PGSTAT_STAT_INTERVAL / 1000 ;
1604+ timeval . it_value . tv_usec = PGSTAT_STAT_INTERVAL % 1000 ;
16051605
16061606/*
16071607 * Read in an existing statistics stats file or initialize the stats to
16081608 * zero.
16091609 */
1610- pgStatRunningInCollector = TRUE ;
1610+ pgStatRunningInCollector = true ;
16111611pgstat_read_statsfile (& pgStatDBHash ,InvalidOid ,NULL ,NULL );
16121612
16131613/*
@@ -1634,34 +1634,11 @@ PgstatCollectorMain(int argc, char *argv[])
16341634 */
16351635for (;;)
16361636{
1637- /*
1638- * If we need to write the status file again (there have been changes
1639- * in the statistics since we wrote it last) calculate the timeout
1640- * until we have to do so.
1641- */
16421637if (need_statwrite )
16431638{
1644- struct timeval now ;
1645-
1646- gettimeofday (& now ,NULL );
1647- /* avoid assuming that tv_sec is signed */
1648- if (now .tv_sec > next_statwrite .tv_sec ||
1649- (now .tv_sec == next_statwrite .tv_sec &&
1650- now .tv_usec >=next_statwrite .tv_usec ))
1651- {
1652- timeout .tv_sec = 0 ;
1653- timeout .tv_usec = 0 ;
1654- }
1655- else
1656- {
1657- timeout .tv_sec = next_statwrite .tv_sec - now .tv_sec ;
1658- timeout .tv_usec = next_statwrite .tv_usec - now .tv_usec ;
1659- if (timeout .tv_usec < 0 )
1660- {
1661- timeout .tv_sec -- ;
1662- timeout .tv_usec += 1000000 ;
1663- }
1664- }
1639+ pgstat_write_statsfile ();
1640+ need_statwrite = false;
1641+ need_timer = true;
16651642}
16661643
16671644/*
@@ -1673,9 +1650,7 @@ PgstatCollectorMain(int argc, char *argv[])
16731650/*
16741651 * Now wait for something to do.
16751652 */
1676- nready = select (readPipe + 1 ,& rfds ,NULL ,NULL ,
1677- (need_statwrite ) ?& timeout :NULL );
1678- if (nready < 0 )
1653+ if (select (readPipe + 1 ,& rfds ,NULL ,NULL ,NULL )< 0 )
16791654{
16801655if (errno == EINTR )
16811656continue ;
@@ -1684,18 +1659,6 @@ PgstatCollectorMain(int argc, char *argv[])
16841659errmsg ("select() failed in statistics collector: %m" )));
16851660}
16861661
1687- /*
1688- * If there are no descriptors ready, our timeout for writing the
1689- * stats file happened.
1690- */
1691- if (nready == 0 )
1692- {
1693- pgstat_write_statsfile ();
1694- need_statwrite = FALSE;
1695-
1696- continue ;
1697- }
1698-
16991662/*
17001663 * Check if there is a new statistics message to collect.
17011664 */
@@ -1813,17 +1776,12 @@ PgstatCollectorMain(int argc, char *argv[])
18131776 */
18141777pgStatNumMessages ++ ;
18151778
1816- /*
1817- * If this is the first message after we wrote the stats file the
1818- * last time, setup the timeout that it'd be written.
1819- */
1820- if (!need_statwrite )
1779+ if (need_timer )
18211780{
1822- gettimeofday (& next_statwrite ,NULL );
1823- next_statwrite .tv_usec += ((PGSTAT_STAT_INTERVAL )* 1000 );
1824- next_statwrite .tv_sec += (next_statwrite .tv_usec /1000000 );
1825- next_statwrite .tv_usec %=1000000 ;
1826- need_statwrite = TRUE;
1781+ if (setitimer (ITIMER_REAL ,& timeval ,NULL ))
1782+ ereport (ERROR ,
1783+ (errmsg ("unable to set statistics collector timer: %m" )));
1784+ need_timer = false;
18271785}
18281786}
18291787
@@ -1848,6 +1806,13 @@ PgstatCollectorMain(int argc, char *argv[])
18481806}
18491807
18501808
1809+ static void
1810+ force_statwrite (SIGNAL_ARGS )
1811+ {
1812+ need_statwrite = true;
1813+ }
1814+
1815+
18511816/* ----------
18521817 * pgstat_recvbuffer() -
18531818 *
@@ -1865,7 +1830,6 @@ pgstat_recvbuffer(void)
18651830struct timeval timeout ;
18661831int writePipe = pgStatPipe [1 ];
18671832int maxfd ;
1868- int nready ;
18691833int len ;
18701834int xfr ;
18711835int frm ;
@@ -1906,6 +1870,14 @@ pgstat_recvbuffer(void)
19061870 */
19071871msgbuffer = (char * )palloc (PGSTAT_RECVBUFFERSZ );
19081872
1873+ /*
1874+ * Wait for some work to do; but not for more than 10 seconds. (This
1875+ * determines how quickly we will shut down after an ungraceful
1876+ * postmaster termination; so it needn't be very fast.)
1877+ */
1878+ timeout .tv_sec = 10 ;
1879+ timeout .tv_usec = 0 ;
1880+
19091881/*
19101882 * Loop forever
19111883 */
@@ -1946,16 +1918,7 @@ pgstat_recvbuffer(void)
19461918maxfd = writePipe ;
19471919}
19481920
1949- /*
1950- * Wait for some work to do; but not for more than 10 seconds. (This
1951- * determines how quickly we will shut down after an ungraceful
1952- * postmaster termination; so it needn't be very fast.)
1953- */
1954- timeout .tv_sec = 10 ;
1955- timeout .tv_usec = 0 ;
1956-
1957- nready = select (maxfd + 1 ,& rfds ,& wfds ,NULL ,& timeout );
1958- if (nready < 0 )
1921+ if (select (maxfd + 1 ,& rfds ,& wfds ,NULL ,& timeout )< 0 )
19591922{
19601923if (errno == EINTR )
19611924continue ;