diff options
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r-- | src/backend/postmaster/postmaster.c | 179 |
1 files changed, 149 insertions, 30 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index d08d02c2cf6..661451411f4 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.412 2004/07/19 02:47:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.413 2004/07/21 20:22:59 momjian Exp $ * * NOTES * @@ -55,12 +55,6 @@ * The Postmaster cleans up after backends if they have an emergency * exit and/or core dump. * - * Error Reporting: - * Use write_stderr() only for reporting "interactive" errors - * (essentially, bogus arguments on the command line). Once the - * postmaster is launched, use ereport(). In particular, don't use - * write_stderr() for anything that occurs after pmdaemonize. - * *------------------------------------------------------------------------- */ @@ -200,6 +194,7 @@ char *preload_libraries_string = NULL; static pid_t StartupPID = 0, BgWriterPID = 0, PgArchPID = 0, + AutoVacPID = 0, PgStatPID = 0; /* Startup/shutdown state */ @@ -269,6 +264,7 @@ static void SignalChildren(int signal); static int CountChildren(void); static bool CreateOptsFile(int argc, char *argv[], char *fullprogname); static pid_t StartChildProcess(int xlop); +static void postmaster_error(const char *fmt,...); #ifdef EXEC_BACKEND @@ -299,6 +295,7 @@ static void ShmemBackendArrayRemove(pid_t pid); #define StartupDataBase() StartChildProcess(BS_XLOG_STARTUP) #define StartBackgroundWriter() StartChildProcess(BS_XLOG_BGWRITER) +#define StartAutoVac() StartChildProcess(BS_XLOG_AUTOVAC) /* @@ -385,7 +382,7 @@ PostmasterMain(int argc, char *argv[]) #ifdef USE_ASSERT_CHECKING SetConfigOption("debug_assertions", optarg, PGC_POSTMASTER, PGC_S_ARGV); #else - write_stderr("%s: assert checking is not compiled in\n", progname); + postmaster_error("assert checking is not compiled in"); #endif break; case 'a': @@ -509,8 +506,9 @@ PostmasterMain(int argc, char *argv[]) } default: - write_stderr("Try \"%s --help\" for more information.\n", - progname); + fprintf(stderr, + gettext("Try \"%s --help\" for more information.\n"), + progname); ExitPostmaster(1); } } @@ -520,10 +518,10 @@ PostmasterMain(int argc, char *argv[]) */ if (optind < argc) { - write_stderr("%s: invalid argument: \"%s\"\n", - progname, argv[optind]); - write_stderr("Try \"%s --help\" for more information.\n", - progname); + postmaster_error("invalid argument: \"%s\"", argv[optind]); + fprintf(stderr, + gettext("Try \"%s --help\" for more information.\n"), + progname); ExitPostmaster(1); } @@ -594,13 +592,13 @@ PostmasterMain(int argc, char *argv[]) * for lack of buffers. The specific choices here are somewhat * arbitrary. */ - write_stderr("%s: the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16\n", progname); + postmaster_error("the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16"); ExitPostmaster(1); } if (ReservedBackends >= MaxBackends) { - write_stderr("%s: superuser_reserved_connections must be less than max_connections\n", progname); + postmaster_error("superuser_reserved_connections must be less than max_connections"); ExitPostmaster(1); } @@ -609,7 +607,7 @@ PostmasterMain(int argc, char *argv[]) */ if (!CheckDateTokenTables()) { - write_stderr("%s: invalid datetoken tables, please fix\n", progname); + postmaster_error("invalid datetoken tables, please fix"); ExitPostmaster(1); } @@ -829,7 +827,7 @@ PostmasterMain(int argc, char *argv[]) * CAUTION: when changing this list, check for side-effects on the signal * handling setup of child processes. See tcop/postgres.c, * bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/pgarch.c, - * and postmaster/pgstat.c. + * postmaster/pgstat.c, and postmaster/pg_autovacuum.c. */ pqinitmask(); PG_SETMASK(&BlockSig); @@ -978,10 +976,11 @@ checkDataDir(const char *checkdir) fp = AllocateFile(path, PG_BINARY_R); if (fp == NULL) { - write_stderr("%s: could not find the database system\n" - "Expected to find it in the directory \"%s\",\n" - "but could not open file \"%s\": %s\n", - progname, checkdir, path, strerror(errno)); + fprintf(stderr, + gettext("%s: could not find the database system\n" + "Expected to find it in the directory \"%s\",\n" + "but could not open file \"%s\": %s\n"), + progname, checkdir, path, strerror(errno)); ExitPostmaster(2); } FreeFile(fp); @@ -1024,8 +1023,8 @@ pmdaemonize(void) pid = fork(); if (pid == (pid_t) -1) { - write_stderr("%s: could not fork background process: %s\n", - progname, strerror(errno)); + postmaster_error("could not fork background process: %s", + strerror(errno)); ExitPostmaster(1); } else if (pid) @@ -1046,8 +1045,8 @@ pmdaemonize(void) #ifdef HAVE_SETSID if (setsid() < 0) { - write_stderr("%s: could not dissociate from controlling TTY: %s\n", - progname, strerror(errno)); + postmaster_error("could not dissociate from controlling TTY: %s", + strerror(errno)); ExitPostmaster(1); } #endif @@ -1114,9 +1113,9 @@ ServerLoop(void) int nSockets; time_t now, last_touch_time; - struct timeval earlier, + struct timeval earlier, later; - struct timezone tz; + struct timezone tz; gettimeofday(&earlier, &tz); last_touch_time = time(NULL); @@ -1220,6 +1219,35 @@ ServerLoop(void) kill(BgWriterPID, SIGUSR2); } + /* + * If no AutoVacuum process is running, and we are not in + * a state that prevents it, start one. It doesn't matter if this + * fails, we'll just try again later. + */ + if (autovacuum_start_daemon) + { + if (pgstat_collect_tuplelevel) + { + if (AutoVacPID == 0 && StartupPID == 0 && !FatalError) + { + AutoVacPID = StartAutoVac(); + if(pgstat_collect_resetonpmstart) + elog(WARNING,"pg_autovacuum: stats_reset_on_server_start should be disabled for optimal performance"); + + /* If shutdown is pending, set it going */ + if (Shutdown > NoShutdown && AutoVacPID != 0) + kill(AutoVacPID, SIGUSR2); + } + } + else + elog(WARNING, "pg_autovacuum: autovac is enabled, but requires stats_row_level which is not enabled"); + } + else if(AutoVacPID > 0) + kill(AutoVacPID, SIGUSR2); + + if (!autovacuum_start_daemon) + elog(DEBUG1, "pg_autovacuum: not enabled"); + /* If we have lost the archiver, try to start a new one */ if (XLogArchivingActive() && PgArchPID == 0 && StartupPID == 0 && !FatalError && Shutdown == NoShutdown) @@ -1587,6 +1615,21 @@ processCancelRequest(Port *port, void *pkt) backendPID = (int) ntohl(canc->backendPID); cancelAuthCode = (long) ntohl(canc->cancelAuthCode); + if (backendPID == BgWriterPID) + { + ereport(DEBUG2, + (errmsg_internal("ignoring cancel request for bgwriter process %d", + backendPID))); + return; + } + if (backendPID == AutoVacPID) + { + ereport(DEBUG2, + (errmsg_internal("ignoring cancel request for autovacuum process %d", + backendPID))); + return; + } + /* * See if we have a matching backend. In the EXEC_BACKEND case, we * can no longer access the postmaster's own backend list, and must @@ -1770,6 +1813,8 @@ SIGHUP_handler(SIGNAL_ARGS) kill(BgWriterPID, SIGHUP); if (PgArchPID != 0) kill(PgArchPID, SIGHUP); + if (AutoVacPID != 0) + kill(AutoVacPID, SIGHUP); /* PgStatPID does not currently need SIGHUP */ load_hba(); load_ident(); @@ -1831,6 +1876,10 @@ pmdie(SIGNAL_ARGS) /* Tell pgarch to shut down too; nothing left for it to do */ if (PgArchPID != 0) kill(PgArchPID, SIGQUIT); + /* I don't think we need to Start the autovac process if not running */ + /* And tell it to shut down */ + if (AutoVacPID != 0) + kill(AutoVacPID, SIGUSR2); /* Tell pgstat to shut down too; nothing left for it to do */ if (PgStatPID != 0) kill(PgStatPID, SIGQUIT); @@ -1878,6 +1927,9 @@ pmdie(SIGNAL_ARGS) /* Tell pgarch to shut down too; nothing left for it to do */ if (PgArchPID != 0) kill(PgArchPID, SIGQUIT); + /* And tell it to shut down */ + if (AutoVacPID != 0) + kill(AutoVacPID, SIGUSR2); /* Tell pgstat to shut down too; nothing left for it to do */ if (PgStatPID != 0) kill(PgStatPID, SIGQUIT); @@ -1898,6 +1950,8 @@ pmdie(SIGNAL_ARGS) kill(BgWriterPID, SIGQUIT); if (PgArchPID != 0) kill(PgArchPID, SIGQUIT); + if (AutoVacPID != 0) + kill(AutoVacPID, SIGQUIT); if (PgStatPID != 0) kill(PgStatPID, SIGQUIT); if (DLGetHead(BackendList)) @@ -2040,10 +2094,36 @@ reaper(SIGNAL_ARGS) if (XLogArchivingActive() && StartupPID == 0 && !FatalError && Shutdown == NoShutdown) PgArchPID = pgarch_start(); + /* + * Shutdown autovac if a shutdown request was pending. + */ + if (Shutdown > NoShutdown && AutoVacPID != 0) + kill(AutoVacPID, SIGUSR2); + continue; } /* + * Was it the autovac? + */ + if (AutoVacPID != 0 && pid == AutoVacPID) + { + AutoVacPID = 0; + if (exitstatus != 0) + { + /* + * Any unexpected exit of the autovacuum is treated as a crash. + * FIXME: This is useful for debugging autovac, but I think it should be + * ripped out before final patch, autovac shouldn't crash the postmaster + */ + LogChildExit(LOG, gettext("pg_autovacuum process"), + pid, exitstatus); + HandleChildCrash(pid, exitstatus); + continue; + } + } + + /* * Was it the statistics collector? If so, just try to start a new * one; no need to force reset of the rest of the system. (If fail, * we'll try again in future cycles of the main loop.) @@ -2072,7 +2152,7 @@ reaper(SIGNAL_ARGS) * StartupDataBase. (We can ignore the archiver and stats processes * here since they are not connected to shmem.) */ - if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0) + if (DLGetHead(BackendList) || StartupPID != 0 || BgWriterPID != 0 || AutoVacPID != 0) goto reaper_done; ereport(LOG, (errmsg("all server processes terminated; reinitializing"))); @@ -2095,6 +2175,9 @@ reaper(SIGNAL_ARGS) /* And tell it to shut down */ if (BgWriterPID != 0) kill(BgWriterPID, SIGUSR2); + /* Tell AutoVac to shut down */ + if (AutoVacPID != 0) + kill(AutoVacPID, SIGUSR2); } reaper_done: @@ -2254,6 +2337,20 @@ HandleChildCrash(int pid, } FatalError = true; + + /* Take care of the autovacuum too */ + if (pid == AutoVacPID) + AutoVacPID = 0; + else if (AutoVacPID != 0 && !FatalError) + { + ereport(DEBUG2, + (errmsg_internal("sending %s to process %d", + (SendStop ? "SIGSTOP" : "SIGQUIT"), + (int) AutoVacPID))); + kill(AutoVacPID, (SendStop ? SIGSTOP : SIGQUIT)); + } + + FatalError = true; } /* @@ -3240,6 +3337,10 @@ StartChildProcess(int xlop) ereport(LOG, (errmsg("could not fork background writer process: %m"))); break; + case BS_XLOG_AUTOVAC: + ereport(LOG, + (errmsg("could not fork auto vacuum process: %m"))); + break; default: ereport(LOG, (errmsg("could not fork process: %m"))); @@ -3294,6 +3395,24 @@ CreateOptsFile(int argc, char *argv[], char *fullprogname) return true; } +/* + * This should be used only for reporting "interactive" errors (essentially, + * bogus arguments on the command line). Once the postmaster is launched, + * use ereport. In particular, don't use this for anything that occurs + * after pmdaemonize. + */ +static void +postmaster_error(const char *fmt,...) +{ + va_list ap; + + fprintf(stderr, "%s: ", progname); + va_start(ap, fmt); + vfprintf(stderr, gettext(fmt), ap); + va_end(ap); + fprintf(stderr, "\n"); +} + #ifdef EXEC_BACKEND @@ -3733,7 +3852,7 @@ win32_sigchld_waiter(LPVOID param) if (r == WAIT_OBJECT_0) pg_queue_signal(SIGCHLD); else - write_stderr("ERROR: failed to wait on child process handle: %d\n", + fprintf(stderr, "ERROR: failed to wait on child process handle: %d\n", (int) GetLastError()); CloseHandle(procHandle); return 0; |