1010 *
1111 *
1212 * IDENTIFICATION
13- * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.49 2007/06/08 21:21:28 alvherre Exp $
13+ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.50 2007/06/13 21:24:55 alvherre Exp $
1414 *
1515 *-------------------------------------------------------------------------
1616 */
1717#include "postgres.h"
1818
1919#include <signal.h>
2020#include <sys/types.h>
21+ #include <sys/time.h>
2122#include <time.h>
2223#include <unistd.h>
2324
@@ -73,6 +74,10 @@ intautovacuum_vac_cost_limit;
7374
7475int Log_autovacuum = -1 ;
7576
77+
78+ /* maximum sleep duration in the launcher, in seconds */
79+ #define AV_SLEEP_QUANTUM 10
80+
7681/* Flags to tell if we are in an autovacuum process */
7782static bool am_autovacuum_launcher = false;
7883static bool am_autovacuum_worker = false;
@@ -197,7 +202,8 @@ NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]);
197202NON_EXEC_STATIC void AutoVacLauncherMain (int argc ,char * argv []);
198203
199204static Oid do_start_worker (void );
200- static uint64 launcher_determine_sleep (bool canlaunch ,bool recursing );
205+ static void launcher_determine_sleep (bool canlaunch ,bool recursing ,
206+ struct timeval * nap );
201207static void launch_worker (TimestampTz now );
202208static List * get_database_list (void );
203209static void rebuild_database_list (Oid newdb );
@@ -487,7 +493,7 @@ AutoVacLauncherMain(int argc, char *argv[])
487493
488494for (;;)
489495{
490- uint64 micros ;
496+ struct timeval nap ;
491497bool can_launch ;
492498TimestampTz current_time = 0 ;
493499
@@ -498,11 +504,39 @@ AutoVacLauncherMain(int argc, char *argv[])
498504if (!PostmasterIsAlive (true))
499505exit (1 );
500506
501- micros = launcher_determine_sleep (AutoVacuumShmem -> av_freeWorkers !=
502- INVALID_OFFSET , false);
507+ launcher_determine_sleep (AutoVacuumShmem -> av_freeWorkers !=
508+ INVALID_OFFSET , false,& nap );
509+
510+ /*
511+ * Sleep for a while according to schedule. We only sleep in
512+ * AV_SLEEP_QUANTUM second intervals, in order to promptly notice
513+ * postmaster death.
514+ */
515+ while (nap .tv_sec > 0 || nap .tv_usec > 0 )
516+ {
517+ uint32 sleeptime ;
518+
519+ sleeptime = nap .tv_usec ;
520+ nap .tv_usec = 0 ;
503521
504- /* Sleep for a while according to schedule */
505- pg_usleep (micros );
522+ if (nap .tv_sec > 0 )
523+ {
524+ sleeptime += Min (nap .tv_sec ,AV_SLEEP_QUANTUM )* 1000000 ;
525+ nap .tv_sec -= Min (nap .tv_sec ,AV_SLEEP_QUANTUM );
526+ }
527+
528+ pg_usleep (sleeptime );
529+
530+ /*
531+ * Emergency bailout if postmaster has died. This is to avoid the
532+ * necessity for manual cleanup of all postmaster children.
533+ */
534+ if (!PostmasterIsAlive (true))
535+ exit (1 );
536+
537+ if (avlauncher_shutdown_request || got_SIGHUP || got_SIGUSR1 )
538+ break ;
539+ }
506540
507541/* the normal shutdown case */
508542if (avlauncher_shutdown_request )
@@ -647,16 +681,15 @@ AutoVacLauncherMain(int argc, char *argv[])
647681}
648682
649683/*
650- * Determine the time to sleep,in microseconds, based on the database list.
684+ * Determine the time to sleep, based on the database list.
651685 *
652686 * The "canlaunch" parameter indicates whether we can start a worker right now,
653- * for example due to the workers being all busy.
687+ * for example due to the workers being all busy. If this is false, we will
688+ * cause a long sleep, which will be interrupted when a worker exits.
654689 */
655- static uint64
656- launcher_determine_sleep (bool canlaunch ,bool recursing )
690+ static void
691+ launcher_determine_sleep (bool canlaunch ,bool recursing , struct timeval * nap )
657692{
658- long secs ;
659- int usecs ;
660693Dlelem * elem ;
661694
662695/*
@@ -667,23 +700,28 @@ launcher_determine_sleep(bool canlaunch, bool recursing)
667700 */
668701if (!canlaunch )
669702{
670- secs = autovacuum_naptime ;
671- usecs = 0 ;
703+ nap -> tv_sec = autovacuum_naptime ;
704+ nap -> tv_usec = 0 ;
672705}
673706else if ((elem = DLGetTail (DatabaseList ))!= NULL )
674707{
675708avl_dbase * avdb = DLE_VAL (elem );
676709TimestampTz current_time = GetCurrentTimestamp ();
677710TimestampTz next_wakeup ;
711+ long secs ;
712+ int usecs ;
678713
679714next_wakeup = avdb -> adl_next_worker ;
680715TimestampDifference (current_time ,next_wakeup ,& secs ,& usecs );
716+
717+ nap -> tv_sec = secs ;
718+ nap -> tv_usec = usecs ;
681719}
682720else
683721{
684722/* list is empty, sleep for whole autovacuum_naptime seconds */
685- secs = autovacuum_naptime ;
686- usecs = 0 ;
723+ nap -> tv_sec = autovacuum_naptime ;
724+ nap -> tv_usec = 0 ;
687725}
688726
689727/*
@@ -696,20 +734,19 @@ launcher_determine_sleep(bool canlaunch, bool recursing)
696734 * We only recurse once. rebuild_database_list should always return times
697735 * in the future, but it seems best not to trust too much on that.
698736 */
699- if (secs == 0L && usecs == 0 && !recursing )
737+ if (nap -> tv_sec == 0L && nap -> tv_usec == 0 && !recursing )
700738{
701739rebuild_database_list (InvalidOid );
702- return launcher_determine_sleep (canlaunch , true);
740+ launcher_determine_sleep (canlaunch , true,nap );
741+ return ;
703742}
704743
705744/* 100ms is the smallest time we'll allow the launcher to sleep */
706- if (secs <=0L && usecs <=100000 )
745+ if (nap -> tv_sec <=0L && nap -> tv_usec <=100000 )
707746{
708- secs = 0L ;
709- usecs = 100000 ;/* 100 ms */
747+ nap -> tv_sec = 0L ;
748+ nap -> tv_usec = 100000 ;/* 100 ms */
710749}
711-
712- return secs * 1000000 + usecs ;
713750}
714751
715752/*