static void do_reload(void) { pgpid_t pid; pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; write_stderr(_("%s: cannot reload server; " "single-user server is running (PID: %ld)\n"), progname, pid); write_stderr(_("Please terminate the single-user server and try again.\n")); exit(1); } if (kill((pid_t) pid, sig) != 0) { write_stderr(_("%s: could not send reload signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); exit(1); } print_msg(_("server signaled\n")); }
static void do_promote(void) { pgpid_t pid; pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not gtm */ { pid = -pid; write_stderr(_("%s: cannot promote server; " "single-user server is running (PID: %ld)\n"), progname, pid); exit(1); } if (kill((pid_t) pid, SIGUSR1) != 0) { write_stderr(_("%s: could not send promote signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); exit(1); } }
static void do_status(void) { pgpid_t pid; pid = get_pgpid(); if (pid != 0) /* 0 means no pid file */ { if (pid < 0) /* standalone backend */ { pid = -pid; if (postmaster_is_alive((pid_t) pid)) { printf(_("%s: single-user server is running (PID: %ld)\n"), progname, pid); return; } } else /* postmaster */ { if (postmaster_is_alive((pid_t) pid)) { char **optlines; printf(_("%s: server is running (PID: %ld)\n"), progname, pid); optlines = readfile(postopts_file); if (optlines != NULL) for (; *optlines != NULL; optlines++) fputs(*optlines, stdout); return; } } } printf(_("%s: no server running\n"), progname); exit(1); }
static void do_restart(void) { int cnt; pgpid_t pid; struct stat statbuf; pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); write_stderr(_("starting server anyway\n")); do_start(); return; } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; if (postmaster_is_alive((pid_t) pid)) { write_stderr(_("%s: cannot restart server; " "single-user server is running (PID: %ld)\n"), progname, pid); write_stderr(_("Please terminate the single-user server and try again.\n")); exit(1); } } if (postmaster_is_alive((pid_t) pid)) { if (kill((pid_t) pid, sig) != 0) { write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); exit(1); } /* * If backup_label exists, an online backup is running. Warn the * user that smart shutdown will wait for it to finish. However, if * recovery.conf is also present, we're recovering from an online * backup instead of performing one. */ if (shutdown_mode == SMART_MODE && stat(backup_file, &statbuf) == 0 && stat(recovery_file, &statbuf) != 0) { print_msg(_("WARNING: online backup mode is active\n" "Shutdown will not complete until pg_stop_backup() is called.\n\n")); } print_msg(_("waiting for server to shut down...")); /* always wait for restart */ for (cnt = 0; cnt < wait_seconds; cnt++) { if ((pid = get_pgpid()) != 0) { print_msg("."); pg_usleep(1000000); /* 1 sec */ } else break; } if (pid != 0) /* pid file still exists */ { print_msg(_(" failed\n")); write_stderr(_("%s: server does not shut down\n"), progname); exit(1); } print_msg(_(" done\n")); print_msg(_("server stopped\n")); } else { write_stderr(_("%s: old server process (PID: %ld) seems to be gone\n"), progname, pid); write_stderr(_("starting server anyway\n")); } do_start(); }
static void do_start(void) { pgpid_t pid; pgpid_t old_pid = 0; int exitcode; if (ctl_command != RESTART_COMMAND) { old_pid = get_pgpid(); if (old_pid != 0) write_stderr(_("%s: another server might be running; " "trying to start server anyway\n"), progname); } read_post_opts(); /* No -D or -D already added during server start */ if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL) pgdata_opt = ""; if (exec_path == NULL) exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR); #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) if (allow_core_files) unlimit_core_size(); #endif /* * If possible, tell the postmaster our parent shell's PID (see the * comments in CreateLockFile() for motivation). Windows hasn't got * getppid() unfortunately. */ #ifndef WIN32 { static char env_var[32]; snprintf(env_var, sizeof(env_var), "PG_GRANDPARENT_PID=%d", (int) getppid()); putenv(env_var); } #endif exitcode = start_postmaster(); if (exitcode != 0) { write_stderr(_("%s: could not start server: exit code was %d\n"), progname, exitcode); exit(1); } if (old_pid != 0) { pg_usleep(1000000); pid = get_pgpid(); if (pid == old_pid) { write_stderr(_("%s: could not start server\n" "Examine the log output.\n"), progname); exit(1); } } if (do_wait) { print_msg(_("waiting for server to start...")); if (test_postmaster_connection(false) == false) { write_stderr(_("%s: could not start server\n" "Examine the log output.\n"), progname); exit(1); } else { print_msg(_(" done\n")); print_msg(_("server started\n")); } } else print_msg(_("server starting\n")); }
static void do_restart(void) { int cnt; pgpid_t pid; pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); write_stderr(_("starting server anyway\n")); do_start(); return; } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; if (postmaster_is_alive((pid_t) pid)) { write_stderr(_("%s: cannot restart server; " "single-user server is running (PID: %ld)\n"), progname, pid); write_stderr(_("Please terminate the single-user server and try again.\n")); exit(1); } } if (postmaster_is_alive((pid_t) pid)) { if (kill((pid_t) pid, sig) != 0) { write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); exit(1); } print_msg(_("waiting for server to shut down...")); /* always wait for restart */ for (cnt = 0; cnt < wait_seconds; cnt++) { if ((pid = get_pgpid()) != 0) { print_msg("."); pg_usleep(1000000); /* 1 sec */ } else break; } if (pid != 0) /* pid file still exists */ { print_msg(_(" failed\n")); write_stderr(_("%s: server does not shut down\n"), progname); exit(1); } print_msg(_(" done\n")); printf(_("server stopped\n")); } else { write_stderr(_("%s: old server process (PID: %ld) seems to be gone\n"), progname, pid); write_stderr(_("starting server anyway\n")); } do_start(); }
static void do_stop(void) { int cnt; pgpid_t pid; pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not postmaster */ { pid = -pid; write_stderr(_("%s: cannot stop server; " "single-user server is running (PID: %ld)\n"), progname, pid); exit(1); } if (kill((pid_t) pid, sig) != 0) { write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); exit(1); } if (!do_wait) { print_msg(_("server shutting down\n")); return; } else { print_msg(_("waiting for server to shut down...")); for (cnt = 0; cnt < wait_seconds; cnt++) { if ((pid = get_pgpid()) != 0) { print_msg("."); pg_usleep(1000000); /* 1 sec */ } else break; } if (pid != 0) /* pid file still exists */ { print_msg(_(" failed\n")); write_stderr(_("%s: server does not shut down\n"), progname); exit(1); } print_msg(_(" done\n")); printf(_("server stopped\n")); } }
static void do_start(void) { pgpid_t pid; pgpid_t old_pid = 0; int exitcode; if (ctl_command != RESTART_COMMAND) { old_pid = get_pgpid(); if (old_pid != 0) write_stderr(_("%s: another server might be running; " "trying to start server anyway\n"), progname); } read_post_opts(); /* No -D or -D already added during server start */ if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL) pgdata_opt = ""; if (postgres_path == NULL) { char *postmaster_path; int ret; postmaster_path = pg_malloc(MAXPGPATH); if ((ret = find_other_exec(argv0, "postgres", PM_VERSIONSTR, postmaster_path)) < 0) { char full_path[MAXPGPATH]; if (find_my_exec(argv0, full_path) < 0) strlcpy(full_path, progname, sizeof(full_path)); if (ret == -1) write_stderr(_("The program \"postgres\" is needed by %s " "but was not found in the\n" "same directory as \"%s\".\n" "Check your installation.\n"), progname, full_path); else write_stderr(_("The program \"postgres\" was found by \"%s\"\n" "but was not the same version as %s.\n" "Check your installation.\n"), full_path, progname); exit(1); } postgres_path = postmaster_path; } #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE) if (allow_core_files) unlimit_core_size(); #endif exitcode = start_postmaster(); if (exitcode != 0) { write_stderr(_("%s: could not start server: exit code was %d\n"), progname, exitcode); exit(1); } if (old_pid != 0) { pg_usleep(1000000); pid = get_pgpid(); if (pid == old_pid) { write_stderr(_("%s: could not start server\n" "Examine the log output.\n"), progname); exit(1); } } if (do_wait) { print_msg(_("waiting for server to start...")); if (test_postmaster_connection(false) == false) { printf(_("could not start server\n")); exit(1); } else { print_msg(_(" done\n")); print_msg(_("server started\n")); } } else print_msg(_("server starting\n")); }
/* * Find the pgport and try a connection * Note that the checkpoint parameter enables a Windows service control * manager checkpoint, it's got nothing to do with database checkpoints!! */ static bool test_postmaster_connection(bool do_checkpoint __attribute__((unused))) { PGconn *conn; bool success = false; int i; char portstr[32]; char *p; char *q; char connstr[128]; /* Should be way more than enough! */ static const char *backend_options = "'-c gp_session_role=utility'"; *portstr = '\0'; /* * Look in post_opts for a -p switch. * * This parsing code is not amazingly bright; it could for instance get * fooled if ' -p' occurs within a quoted argument value. Given that few * people pass complicated settings in post_opts, it's probably good * enough. */ for (p = post_opts; *p;) { /* advance past whitespace */ while (isspace((unsigned char) *p)) p++; if (strncmp(p, "-p", 2) == 0) { p += 2; /* advance past any whitespace/quoting */ while (isspace((unsigned char) *p) || *p == '\'' || *p == '"') p++; /* find end of value (not including any ending quote!) */ q = p; while (*q && !(isspace((unsigned char) *q) || *q == '\'' || *q == '"')) q++; /* and save the argument value */ strlcpy(portstr, p, Min((q - p) + 1, sizeof(portstr))); /* keep looking, maybe there is another -p */ p = q; } /* Advance to next whitespace */ while (*p && !isspace((unsigned char) *p)) p++; } /* * Search config file for a 'port' option. * * This parsing code isn't amazingly bright either, but it should be okay * for valid port settings. */ if (!*portstr) { char **optlines; optlines = readfile(conf_file); if (optlines != NULL) { for (; *optlines != NULL; optlines++) { p = *optlines; while (isspace((unsigned char) *p)) p++; if (strncmp(p, "port", 4) != 0) continue; p += 4; while (isspace((unsigned char) *p)) p++; if (*p != '=') continue; p++; /* advance past any whitespace/quoting */ while (isspace((unsigned char) *p) || *p == '\'' || *p == '"') p++; /* find end of value (not including any ending quote/comment!) */ q = p; while (*q && !(isspace((unsigned char) *q) || *q == '\'' || *q == '"' || *q == '#')) q++; /* and save the argument value */ strlcpy(portstr, p, Min((q - p) + 1, sizeof(portstr))); /* keep looking, maybe there is another */ } } } /* Check environment */ if (!*portstr && getenv("PGPORT") != NULL) strlcpy(portstr, getenv("PGPORT"), sizeof(portstr)); /* Else use compiled-in default */ if (!*portstr) snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT); /* * We need to set a connect timeout otherwise on Windows the SCM will * probably timeout first */ snprintf(connstr, sizeof(connstr), "dbname=template1 port=%s connect_timeout=5 options=%s", portstr, backend_options); for (i = 0; i < wait_seconds; i++) { if ((conn = PQconnectdb(connstr)) != NULL && (PQstatus(conn) == CONNECTION_OK || PQconnectionNeedsPassword(conn))) { PQfinish(conn); success = true; break; } else { PQfinish(conn); #if defined(WIN32) if (do_checkpoint) { /* * Increment the wait hint by 6 secs (connection timeout + * sleep) We must do this to indicate to the SCM that our * startup time is changing, otherwise it'll usually send a * stop signal after 20 seconds, despite incrementing the * checkpoint counter. */ status.dwWaitHint += 6000; status.dwCheckPoint++; SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status); } else #endif print_msg("."); /* * The postmaster should create postmaster.pid very soon after being * started. If it's not there after we've waited 30 or more seconds, * assume startup failed and give up waiting. (Note this covers both * cases where the pidfile was never created, and where it was created * and then removed during postmaster exit.) */ if (i >= (wait_seconds / 2)) { pgpid_t pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); break; } if (! postmaster_is_alive((pid_t) pid)) { write_stderr(_("%s: postmaster pid %ld not running\n"), progname, pid); break; } } pg_usleep(1000000); /* 1 sec */ } } return success; }
static void do_status(void) { pgpid_t pid; char datpath[MAXPGPATH]; int mode; FILE *pidf; /* * Read a PID file to get GTM server status instead of attaching shared memory. */ pidf = fopen(pid_file, "r"); if (pidf == NULL) { write_stderr(_("%s: could not open PID file \"%s\": %s\n"), progname, pid_file, strerror(errno)); exit(1); } if (fscanf(pidf, "%ld", &pid) != 1) { write_stderr(_("%s: invalid data in PID file \"%s\"\n"), progname, pid_file); exit(1); } if (fscanf(pidf, "%s", datpath) != 1) { write_stderr(_("%s: invalid data in PID file \"%s\"\n"), progname, pid_file); exit(1); } if (strcmp(gtm_app, "gtm_proxy") != 0) { if (fscanf(pidf, "%d", &mode) != 1) { write_stderr(_("%s: invalid data in PID file \"%s\"\n"), progname, pid_file); exit(1); } } fclose(pidf); pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not gtm */ { pid = -pid; if (gtm_is_alive((pid_t) pid)) { write_stderr(_("%s: cannot get server status; " "single-user server is running (PID: %ld)\n"), progname, pid); write_stderr(_("Please terminate the single-user server and try again.\n")); exit(1); } } else { if (gtm_is_alive((pid_t) pid)) { char **optlines; printf(_("%s: server is running (PID: %ld)\n"), progname, pid); optlines = readfile(gtmopts_file); if (optlines != NULL) for (; *optlines != NULL; optlines++) fputs(*optlines, stdout); if (strcmp(gtm_app, "gtm_proxy") != 0) printf("%d %s\n", mode, mode == 1 ? "master" : "slave"); return; } } write_stderr(_("%s: no server running\n"), progname); exit(1); }
/* * At least we expect the following argument * * 1) -D datadir * 2) -o options: we expect that -t and -s options are specified here. * Check will be done in GTM-Proxy. If there's an error, it will be * logged. In this case, GTM-Proxy won't terminate. It will continue * to read/write with old GTM. * * Because they are not passed to gtm directly, they should appear in * gtm_ctl argument, not in -o options. They're specific to gtm_ctl * reconnect. */ static void do_reconnect(void) { pgpid_t pid; char *reconnect_point_file_nam; FILE *reconnect_point_file; #ifdef GTM_SBY_DEBUG write_stderr("Reconnecting to new GTM ... DEBUG MODE."); #endif /* * Target must be "gtm_proxy" */ if (strcmp(gtm_app, "gtm_proxy") != 0) { write_stderr(_("%s: only gtm_proxy can accept reconnect command\n"), progname); exit(1); } pid = get_pgpid(); if (pid == 0) /* no pid file */ { write_stderr(_("%s: PID file \"%s\" does not exist\n"), progname, pid_file); write_stderr(_("Is server running?\n")); exit(1); } else if (pid < 0) /* standalone backend, not gtm */ { pid = -pid; write_stderr(_("%s: cannot promote server; " "single-user server is running (PID: %ld)\n"), progname, pid); exit(1); } read_gtm_opts(); /* * Pass reconnect info to GTM-Proxy. * * Option arguments are written to new gtm file under -D directory. */ reconnect_point_file_nam = malloc(strlen(gtm_data) + 9); if (reconnect_point_file_nam == NULL) { write_stderr(_("%s: No memory available.\n"), progname); exit(1); } snprintf(reconnect_point_file_nam, strlen(gtm_data) + 8, "%s/newgtm", gtm_data); reconnect_point_file = fopen(reconnect_point_file_nam, "w"); if (reconnect_point_file == NULL) { write_stderr(_("%s: Cannot open reconnect point file %s\n"), progname, reconnect_point_file_nam); exit(1); } fprintf(reconnect_point_file, "%s\n", gtm_opts); fclose(reconnect_point_file); free(reconnect_point_file_nam); if (kill((pid_t) pid, SIGUSR1) != 0) { write_stderr(_("%s: could not send promote signal (PID: %ld): %s\n"), progname, pid, strerror(errno)); exit(1); } }
static void do_start(void) { pgpid_t pid; pgpid_t old_pid = 0; int exitcode; if (ctl_command != RESTART_COMMAND) { old_pid = get_pgpid(); if (old_pid != 0) write_stderr(_("%s: another server might be running; " "trying to start server anyway\n"), progname); } read_gtm_opts(); /* The binary for both gtm and gtm_standby is the same */ if (strcmp(gtm_app, "gtm_standby") == 0) gtm_app = "gtm"; if (gtm_path == NULL) { int ret; char *found_path; char version_str[MAXPGPATH]; found_path = pg_malloc(MAXPGPATH); sprintf(version_str, "%s (Postgres-XC) %s\n", gtm_app, PGXC_VERSION); if ((ret = find_other_exec(argv0, gtm_app, version_str, found_path)) < 0) { char full_path[MAXPGPATH]; if (find_my_exec(argv0, full_path) < 0) strlcpy(full_path, progname, sizeof(full_path)); if (ret == -1) write_stderr(_("The program \"%s\" is needed by gtm_ctl " "but was not found in the\n" "same directory as \"%s\".\n" "Check your installation.\n"), gtm_app, full_path); else write_stderr(_("The program \"%s\" was found by \"%s\"\n" "but was not the same version as gtm_ctl.\n" "Check your installation.\n"), gtm_app, full_path); exit(1); } *last_dir_separator(found_path) = '\0'; gtm_path = found_path; } exitcode = start_gtm(); if (exitcode != 0) { write_stderr(_("%s: could not start server: exit code was %d\n"), progname, exitcode); exit(1); } if (old_pid != 0) { sleep(1); pid = get_pgpid(); if (pid == old_pid) { write_stderr(_("%s: could not start server\n" "Examine the log output.\n"), progname); exit(1); } } if (do_wait) { print_msg(_("waiting for server to start...")); if (test_gtm_connection() == false) { printf(_("could not start server\n")); exit(1); } else { print_msg(_(" done\n")); print_msg(_("server started\n")); } } else print_msg(_("server starting\n")); }