mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-30 19:00:29 +08:00
Avoid integer overflow issues in autovacuum.
This commit is contained in:
parent
e976fd43c6
commit
a0a26c47d4
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.49 2007/06/08 21:21:28 alvherre Exp $
|
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.50 2007/06/13 21:24:55 alvherre Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -73,6 +74,10 @@ int autovacuum_vac_cost_limit;
|
|||||||
|
|
||||||
int Log_autovacuum = -1;
|
int Log_autovacuum = -1;
|
||||||
|
|
||||||
|
|
||||||
|
/* maximum sleep duration in the launcher, in seconds */
|
||||||
|
#define AV_SLEEP_QUANTUM 10
|
||||||
|
|
||||||
/* Flags to tell if we are in an autovacuum process */
|
/* Flags to tell if we are in an autovacuum process */
|
||||||
static bool am_autovacuum_launcher = false;
|
static bool am_autovacuum_launcher = false;
|
||||||
static bool am_autovacuum_worker = false;
|
static bool am_autovacuum_worker = false;
|
||||||
@ -197,7 +202,8 @@ NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]);
|
|||||||
NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]);
|
NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]);
|
||||||
|
|
||||||
static Oid do_start_worker(void);
|
static Oid do_start_worker(void);
|
||||||
static uint64 launcher_determine_sleep(bool canlaunch, bool recursing);
|
static void launcher_determine_sleep(bool canlaunch, bool recursing,
|
||||||
|
struct timeval *nap);
|
||||||
static void launch_worker(TimestampTz now);
|
static void launch_worker(TimestampTz now);
|
||||||
static List *get_database_list(void);
|
static List *get_database_list(void);
|
||||||
static void rebuild_database_list(Oid newdb);
|
static void rebuild_database_list(Oid newdb);
|
||||||
@ -487,7 +493,7 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
uint64 micros;
|
struct timeval nap;
|
||||||
bool can_launch;
|
bool can_launch;
|
||||||
TimestampTz current_time = 0;
|
TimestampTz current_time = 0;
|
||||||
|
|
||||||
@ -498,11 +504,39 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
if (!PostmasterIsAlive(true))
|
if (!PostmasterIsAlive(true))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
micros = launcher_determine_sleep(AutoVacuumShmem->av_freeWorkers !=
|
launcher_determine_sleep(AutoVacuumShmem->av_freeWorkers !=
|
||||||
INVALID_OFFSET, false);
|
INVALID_OFFSET, false, &nap);
|
||||||
|
|
||||||
/* Sleep for a while according to schedule */
|
/*
|
||||||
pg_usleep(micros);
|
* Sleep for a while according to schedule. We only sleep in
|
||||||
|
* AV_SLEEP_QUANTUM second intervals, in order to promptly notice
|
||||||
|
* postmaster death.
|
||||||
|
*/
|
||||||
|
while (nap.tv_sec > 0 || nap.tv_usec > 0)
|
||||||
|
{
|
||||||
|
uint32 sleeptime;
|
||||||
|
|
||||||
|
sleeptime = nap.tv_usec;
|
||||||
|
nap.tv_usec = 0;
|
||||||
|
|
||||||
|
if (nap.tv_sec > 0)
|
||||||
|
{
|
||||||
|
sleeptime += Min(nap.tv_sec, AV_SLEEP_QUANTUM) * 1000000;
|
||||||
|
nap.tv_sec -= Min(nap.tv_sec, AV_SLEEP_QUANTUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
pg_usleep(sleeptime);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emergency bailout if postmaster has died. This is to avoid the
|
||||||
|
* necessity for manual cleanup of all postmaster children.
|
||||||
|
*/
|
||||||
|
if (!PostmasterIsAlive(true))
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
if (avlauncher_shutdown_request || got_SIGHUP || got_SIGUSR1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* the normal shutdown case */
|
/* the normal shutdown case */
|
||||||
if (avlauncher_shutdown_request)
|
if (avlauncher_shutdown_request)
|
||||||
@ -647,16 +681,15 @@ AutoVacLauncherMain(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine the time to sleep, in microseconds, based on the database list.
|
* Determine the time to sleep, based on the database list.
|
||||||
*
|
*
|
||||||
* The "canlaunch" parameter indicates whether we can start a worker right now,
|
* The "canlaunch" parameter indicates whether we can start a worker right now,
|
||||||
* for example due to the workers being all busy.
|
* for example due to the workers being all busy. If this is false, we will
|
||||||
|
* cause a long sleep, which will be interrupted when a worker exits.
|
||||||
*/
|
*/
|
||||||
static uint64
|
static void
|
||||||
launcher_determine_sleep(bool canlaunch, bool recursing)
|
launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval *nap)
|
||||||
{
|
{
|
||||||
long secs;
|
|
||||||
int usecs;
|
|
||||||
Dlelem *elem;
|
Dlelem *elem;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -667,23 +700,28 @@ launcher_determine_sleep(bool canlaunch, bool recursing)
|
|||||||
*/
|
*/
|
||||||
if (!canlaunch)
|
if (!canlaunch)
|
||||||
{
|
{
|
||||||
secs = autovacuum_naptime;
|
nap->tv_sec = autovacuum_naptime;
|
||||||
usecs = 0;
|
nap->tv_usec = 0;
|
||||||
}
|
}
|
||||||
else if ((elem = DLGetTail(DatabaseList)) != NULL)
|
else if ((elem = DLGetTail(DatabaseList)) != NULL)
|
||||||
{
|
{
|
||||||
avl_dbase *avdb = DLE_VAL(elem);
|
avl_dbase *avdb = DLE_VAL(elem);
|
||||||
TimestampTz current_time = GetCurrentTimestamp();
|
TimestampTz current_time = GetCurrentTimestamp();
|
||||||
TimestampTz next_wakeup;
|
TimestampTz next_wakeup;
|
||||||
|
long secs;
|
||||||
|
int usecs;
|
||||||
|
|
||||||
next_wakeup = avdb->adl_next_worker;
|
next_wakeup = avdb->adl_next_worker;
|
||||||
TimestampDifference(current_time, next_wakeup, &secs, &usecs);
|
TimestampDifference(current_time, next_wakeup, &secs, &usecs);
|
||||||
|
|
||||||
|
nap->tv_sec = secs;
|
||||||
|
nap->tv_usec = usecs;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* list is empty, sleep for whole autovacuum_naptime seconds */
|
/* list is empty, sleep for whole autovacuum_naptime seconds */
|
||||||
secs = autovacuum_naptime;
|
nap->tv_sec = autovacuum_naptime;
|
||||||
usecs = 0;
|
nap->tv_usec = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -696,20 +734,19 @@ launcher_determine_sleep(bool canlaunch, bool recursing)
|
|||||||
* We only recurse once. rebuild_database_list should always return times
|
* We only recurse once. rebuild_database_list should always return times
|
||||||
* in the future, but it seems best not to trust too much on that.
|
* in the future, but it seems best not to trust too much on that.
|
||||||
*/
|
*/
|
||||||
if (secs == 0L && usecs == 0 && !recursing)
|
if (nap->tv_sec == 0L && nap->tv_usec == 0 && !recursing)
|
||||||
{
|
{
|
||||||
rebuild_database_list(InvalidOid);
|
rebuild_database_list(InvalidOid);
|
||||||
return launcher_determine_sleep(canlaunch, true);
|
launcher_determine_sleep(canlaunch, true, nap);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 100ms is the smallest time we'll allow the launcher to sleep */
|
/* 100ms is the smallest time we'll allow the launcher to sleep */
|
||||||
if (secs <= 0L && usecs <= 100000)
|
if (nap->tv_sec <= 0L && nap->tv_usec <= 100000)
|
||||||
{
|
{
|
||||||
secs = 0L;
|
nap->tv_sec = 0L;
|
||||||
usecs = 100000; /* 100 ms */
|
nap->tv_usec = 100000; /* 100 ms */
|
||||||
}
|
}
|
||||||
|
|
||||||
return secs * 1000000 + usecs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
* Written by Peter Eisentraut <peter_e@gmx.net>.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.396 2007/06/08 18:23:52 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.397 2007/06/13 21:24:56 alvherre Exp $
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------
|
*--------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1645,7 +1645,7 @@ static struct config_int ConfigureNamesInt[] =
|
|||||||
GUC_UNIT_S
|
GUC_UNIT_S
|
||||||
},
|
},
|
||||||
&autovacuum_naptime,
|
&autovacuum_naptime,
|
||||||
60, 1, INT_MAX, NULL, NULL
|
60, 1, INT_MAX / 1000, NULL, NULL
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
|
{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
|
||||||
|
Loading…
Reference in New Issue
Block a user