Index: src/backend/postmaster/pgstat.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v
retrieving revision 1.116
diff -c -c -r1.116 pgstat.c
*** src/backend/postmaster/pgstat.c	2 Jan 2006 00:58:00 -0000	1.116
--- src/backend/postmaster/pgstat.c	3 Jan 2006 16:26:04 -0000
***************
*** 117,123 ****
  
  static long pgStatNumMessages = 0;
  
! static bool pgStatRunningInCollector = FALSE;
  
  /*
   * Place where backends store per-table info to be sent to the collector.
--- 117,123 ----
  
  static long pgStatNumMessages = 0;
  
! static bool pgStatRunningInCollector = false;
  
  /*
   * Place where backends store per-table info to be sent to the collector.
***************
*** 145,150 ****
--- 145,151 ----
  static PgStat_StatBeEntry *pgStatBeTable = NULL;
  static int	pgStatNumBackends = 0;
  
+ static volatile bool	need_statwrite;
  
  /* ----------
   * Local function forward declarations
***************
*** 164,169 ****
--- 165,171 ----
  
  NON_EXEC_STATIC void PgstatBufferMain(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_exit(SIGNAL_ARGS);
  static void pgstat_die(SIGNAL_ARGS);
***************
*** 1548,1560 ****
  	PgStat_Msg	msg;
  	fd_set		rfds;
  	int			readPipe;
- 	int			nready;
  	int			len = 0;
! 	struct timeval timeout;
! 	struct timeval next_statwrite;
! 	bool		need_statwrite;
  	HASHCTL		hash_ctl;
! 
  	MyProcPid = getpid();		/* reset MyProcPid */
  
  	/*
--- 1550,1560 ----
  	PgStat_Msg	msg;
  	fd_set		rfds;
  	int			readPipe;
  	int			len = 0;
! 	struct itimerval timeval;
  	HASHCTL		hash_ctl;
! 	bool		need_timer = false;
! 	
  	MyProcPid = getpid();		/* reset MyProcPid */
  
  	/*
***************
*** 1572,1578 ****
  	/* kluge to allow buffer process to kill collector; FIXME */
  	pqsignal(SIGQUIT, pgstat_exit);
  #endif
! 	pqsignal(SIGALRM, SIG_IGN);
  	pqsignal(SIGPIPE, SIG_IGN);
  	pqsignal(SIGUSR1, SIG_IGN);
  	pqsignal(SIGUSR2, SIG_IGN);
--- 1572,1578 ----
  	/* kluge to allow buffer process to kill collector; FIXME */
  	pqsignal(SIGQUIT, pgstat_exit);
  #endif
! 	pqsignal(SIGALRM, force_statwrite);
  	pqsignal(SIGPIPE, SIG_IGN);
  	pqsignal(SIGUSR1, SIG_IGN);
  	pqsignal(SIGUSR2, SIG_IGN);
***************
*** 1597,1613 ****
  	init_ps_display("stats collector process", "", "");
  	set_ps_display("");
  
! 	/*
! 	 * Arrange to write the initial status file right away
! 	 */
! 	gettimeofday(&next_statwrite, NULL);
! 	need_statwrite = TRUE;
  
  	/*
  	 * Read in an existing statistics stats file or initialize the stats to
  	 * zero.
  	 */
! 	pgStatRunningInCollector = TRUE;
  	pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL);
  
  	/*
--- 1597,1613 ----
  	init_ps_display("stats collector process", "", "");
  	set_ps_display("");
  
! 	need_statwrite = true;
! 
! 	MemSet(&timeval, 0, sizeof(struct itimerval));
! 	timeval.it_value.tv_sec = PGSTAT_STAT_INTERVAL / 1000;
! 	timeval.it_value.tv_usec = PGSTAT_STAT_INTERVAL % 1000;
  
  	/*
  	 * Read in an existing statistics stats file or initialize the stats to
  	 * zero.
  	 */
! 	pgStatRunningInCollector = true;
  	pgstat_read_statsfile(&pgStatDBHash, InvalidOid, NULL, NULL);
  
  	/*
***************
*** 1634,1667 ****
  	 */
  	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)
  		{
! 			struct timeval now;
! 
! 			gettimeofday(&now, NULL);
! 			/* 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;
! 				}
! 			}
  		}
  
  		/*
--- 1634,1644 ----
  	 */
  	for (;;)
  	{
  		if (need_statwrite)
  		{
! 			pgstat_write_statsfile();
! 			need_statwrite = false;
! 			need_timer = true;
  		}
  
  		/*
***************
*** 1673,1681 ****
  		/*
  		 * Now wait for something to do.
  		 */
! 		nready = select(readPipe + 1, &rfds, NULL, NULL,
! 						(need_statwrite) ? &timeout : NULL);
! 		if (nready < 0)
  		{
  			if (errno == EINTR)
  				continue;
--- 1650,1656 ----
  		/*
  		 * Now wait for something to do.
  		 */
! 		if (select(readPipe + 1, &rfds, NULL, NULL, NULL) < 0)
  		{
  			if (errno == EINTR)
  				continue;
***************
*** 1685,1702 ****
  		}
  
  		/*
- 		 * 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.
  		 */
  		if (FD_ISSET(readPipe, &rfds))
--- 1660,1665 ----
***************
*** 1813,1829 ****
  			 */
  			pgStatNumMessages++;
  
! 			/*
! 			 * 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);
! 				next_statwrite.tv_usec += ((PGSTAT_STAT_INTERVAL) * 1000);
! 				next_statwrite.tv_sec += (next_statwrite.tv_usec / 1000000);
! 				next_statwrite.tv_usec %= 1000000;
! 				need_statwrite = TRUE;
  			}
  		}
  
--- 1776,1787 ----
  			 */
  			pgStatNumMessages++;
  
! 			if (need_timer)
  			{
! 				if (setitimer(ITIMER_REAL, &timeval, NULL))
! 					ereport(ERROR,
! 						  (errmsg("unable to set statistics collector timer: %m")));
! 				need_timer = false;
  			}
  		}
  
***************
*** 1848,1853 ****
--- 1806,1818 ----
  }
  
  
+ static void
+ force_statwrite(SIGNAL_ARGS)
+ {
+ 	need_statwrite = true;
+ }
+ 
+ 
  /* ----------
   * pgstat_recvbuffer() -
   *
***************
*** 1865,1871 ****
  	struct timeval timeout;
  	int			writePipe = pgStatPipe[1];
  	int			maxfd;
- 	int			nready;
  	int			len;
  	int			xfr;
  	int			frm;
--- 1830,1835 ----
***************
*** 1907,1912 ****
--- 1871,1884 ----
  	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
  	 */
  	for (;;)
***************
*** 1946,1961 ****
  				maxfd = writePipe;
  		}
  
! 		/*
! 		 * 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)
  				continue;
--- 1918,1924 ----
  				maxfd = writePipe;
  		}
  
! 		if (select(maxfd + 1, &rfds, &wfds, NULL, &timeout) < 0)
  		{
  			if (errno == EINTR)
  				continue;
