aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/misc/guc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/misc/guc.c')
-rw-r--r--src/backend/utils/misc/guc.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0ec3ff0fd6b..6497393c032 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -84,6 +84,7 @@
#include "utils/float.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
+#include "utils/pg_lsn.h"
#include "utils/plancache.h"
#include "utils/portal.h"
#include "utils/ps_status.h"
@@ -195,6 +196,19 @@ static bool check_cluster_name(char **newval, void **extra, GucSource source);
static const char *show_unix_socket_permissions(void);
static const char *show_log_file_mode(void);
static const char *show_data_directory_mode(void);
+static bool check_recovery_target_timeline(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_timeline(const char *newval, void *extra);
+static bool check_recovery_target(char **newval, void **extra, GucSource source);
+static void assign_recovery_target(const char *newval, void *extra);
+static bool check_recovery_target_xid(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_xid(const char *newval, void *extra);
+static bool check_recovery_target_time(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_time(const char *newval, void *extra);
+static bool check_recovery_target_name(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_name(const char *newval, void *extra);
+static bool check_recovery_target_lsn(char **newval, void **extra, GucSource source);
+static void assign_recovery_target_lsn(const char *newval, void *extra);
+static bool check_primary_slot_name(char **newval, void **extra, GucSource source);
/* Private functions in guc-file.l that need to be called from guc.c */
static ConfigVariable *ProcessConfigFileInternal(GucContext context,
@@ -442,6 +456,7 @@ const struct config_enum_entry ssl_protocol_versions_info[] = {
*/
extern const struct config_enum_entry wal_level_options[];
extern const struct config_enum_entry archive_mode_options[];
+extern const struct config_enum_entry recovery_target_action_options[];
extern const struct config_enum_entry sync_method_options[];
extern const struct config_enum_entry dynamic_shared_memory_options[];
@@ -533,6 +548,13 @@ static int wal_block_size;
static bool data_checksums;
static bool integer_datetimes;
static bool assert_enabled;
+static char *recovery_target_timeline_string;
+static char *recovery_target_string;
+static char *recovery_target_xid_string;
+static char *recovery_target_time_string;
+static char *recovery_target_name_string;
+static char *recovery_target_lsn_string;
+
/* should be static, but commands/variable.c needs to get at this */
char *role_string;
@@ -616,6 +638,10 @@ const char *const config_group_names[] =
gettext_noop("Write-Ahead Log / Checkpoints"),
/* WAL_ARCHIVING */
gettext_noop("Write-Ahead Log / Archiving"),
+ /* WAL_ARCHIVE_RECOVERY */
+ gettext_noop("Write-Ahead Log / Archive Recovery"),
+ /* WAL_RECOVERY_TARGET */
+ gettext_noop("Write-Ahead Log / Recovery Target"),
/* REPLICATION */
gettext_noop("Replication"),
/* REPLICATION_SENDING */
@@ -1638,6 +1664,16 @@ static struct config_bool ConfigureNamesBool[] =
},
{
+ {"recovery_target_inclusive", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets whether to include or exclude transaction with recovery target."),
+ NULL
+ },
+ &recoveryTargetInclusive,
+ true,
+ NULL, NULL, NULL
+ },
+
+ {
{"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
gettext_noop("Allows connections and queries during recovery."),
NULL
@@ -1974,6 +2010,17 @@ static struct config_int ConfigureNamesInt[] =
},
{
+ {"recovery_min_apply_delay", PGC_POSTMASTER, REPLICATION_STANDBY,
+ gettext_noop("Sets the minimum delay for applying changes during recovery."),
+ NULL,
+ GUC_UNIT_MS
+ },
+ &recovery_min_apply_delay,
+ 0, 0, INT_MAX,
+ NULL, NULL, NULL
+ },
+
+ {
{"wal_receiver_status_interval", PGC_SIGHUP, REPLICATION_STANDBY,
gettext_noop("Sets the maximum interval between WAL receiver status reports to the sending server."),
NULL,
@@ -3292,6 +3339,123 @@ static struct config_string ConfigureNamesString[] =
},
{
+ {"restore_command", PGC_POSTMASTER, WAL_ARCHIVE_RECOVERY,
+ gettext_noop("Sets the shell command that will retrieve an archived WAL file."),
+ NULL
+ },
+ &recoveryRestoreCommand,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"archive_cleanup_command", PGC_POSTMASTER, WAL_ARCHIVE_RECOVERY,
+ gettext_noop("Sets the shell command that will be executed at every restart point."),
+ NULL
+ },
+ &archiveCleanupCommand,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"recovery_end_command", PGC_POSTMASTER, WAL_ARCHIVE_RECOVERY,
+ gettext_noop("Sets the shell command that will be executed once at the end of recovery."),
+ NULL
+ },
+ &recoveryEndCommand,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"recovery_target_timeline", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Specifies the timeline to recovery into."),
+ NULL
+ },
+ &recovery_target_timeline_string,
+ "",
+ check_recovery_target_timeline, assign_recovery_target_timeline, NULL
+ },
+
+ {
+ {"recovery_target", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Set to 'immediate' to end recovery as soon as a consistent state is reached."),
+ NULL
+ },
+ &recovery_target_string,
+ "",
+ check_recovery_target, assign_recovery_target, NULL
+ },
+ {
+ {"recovery_target_xid", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the transaction ID up to which recovery will proceed."),
+ NULL
+ },
+ &recovery_target_xid_string,
+ "",
+ check_recovery_target_xid, assign_recovery_target_xid, NULL
+ },
+ {
+ {"recovery_target_time", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the time stamp up to which recovery will proceed."),
+ NULL
+ },
+ &recovery_target_time_string,
+ "",
+ check_recovery_target_time, assign_recovery_target_time, NULL
+ },
+ {
+ {"recovery_target_name", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the named restore point up to which recovery will proceed."),
+ NULL
+ },
+ &recovery_target_name_string,
+ "",
+ check_recovery_target_name, assign_recovery_target_name, NULL
+ },
+ {
+ {"recovery_target_lsn", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the LSN of the write-ahead log location up to which recovery will proceed."),
+ NULL
+ },
+ &recovery_target_lsn_string,
+ "",
+ check_recovery_target_lsn, assign_recovery_target_lsn, NULL
+ },
+
+ {
+ {"promote_trigger_file", PGC_POSTMASTER, REPLICATION_STANDBY,
+ gettext_noop("Specifies a file name whose presence ends recovery in the standby."),
+ NULL
+ },
+ &PromoteTriggerFile,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"primary_conninfo", PGC_POSTMASTER, REPLICATION_STANDBY,
+ gettext_noop("Sets the connection string to be used to connect to the sending server."),
+ NULL,
+ GUC_SUPERUSER_ONLY
+ },
+ &PrimaryConnInfo,
+ "",
+ NULL, NULL, NULL
+ },
+
+ {
+ {"primary_slot_name", PGC_POSTMASTER, REPLICATION_STANDBY,
+ gettext_noop("Sets the name of the replication slot to use on the sending server."),
+ NULL
+ },
+ &PrimarySlotName,
+ "",
+ check_primary_slot_name, NULL, NULL
+ },
+
+ {
{"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
gettext_noop("Sets the client's character set encoding."),
NULL,
@@ -4072,6 +4236,16 @@ static struct config_enum ConfigureNamesEnum[] =
},
{
+ {"recovery_target_action", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
+ gettext_noop("Sets the action to perform upon reaching the recovery target."),
+ NULL
+ },
+ &recoveryTargetAction,
+ RECOVERY_TARGET_ACTION_PAUSE, recovery_target_action_options,
+ NULL, NULL, NULL
+ },
+
+ {
{"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
gettext_noop("Enables logging of recovery-related debugging information."),
gettext_noop("Each level includes all the levels that follow it. The later"
@@ -10838,4 +11012,251 @@ show_data_directory_mode(void)
return buf;
}
+static bool
+check_recovery_target_timeline(char **newval, void **extra, GucSource source)
+{
+ RecoveryTargetTimeLineGoal rttg = RECOVERY_TARGET_TIMELINE_CONTROLFILE;
+ RecoveryTargetTimeLineGoal *myextra;
+
+ if (strcmp(*newval, "") == 0)
+ rttg = RECOVERY_TARGET_TIMELINE_CONTROLFILE;
+ else if (strcmp(*newval, "latest") == 0)
+ rttg = RECOVERY_TARGET_TIMELINE_LATEST;
+ else
+ {
+ errno = 0;
+ strtoul(*newval, NULL, 0);
+ if (errno == EINVAL || errno == ERANGE)
+ {
+ GUC_check_errdetail("recovery_target_timeline is not a valid number");
+ return false;
+ }
+ rttg = RECOVERY_TARGET_TIMELINE_NUMERIC;
+ }
+
+ myextra = (RecoveryTargetTimeLineGoal *) guc_malloc(ERROR, sizeof(RecoveryTargetTimeLineGoal));
+ *myextra = rttg;
+ *extra = (void *) myextra;
+
+ return true;
+}
+
+static void
+assign_recovery_target_timeline(const char *newval, void *extra)
+{
+ recoveryTargetTimeLineGoal = *((RecoveryTargetTimeLineGoal *) extra);
+ if (recoveryTargetTimeLineGoal == RECOVERY_TARGET_TIMELINE_NUMERIC)
+ recoveryTargetTLIRequested = (TimeLineID) strtoul(newval, NULL, 0);
+ else
+ recoveryTargetTLIRequested = 0;
+}
+
+static bool
+check_recovery_target(char **newval, void **extra, GucSource source)
+{
+ if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
+ {
+ GUC_check_errdetail("The only allowed value is \"immediate\".");
+ return false;
+ }
+ return true;
+}
+
+static void
+assign_recovery_target(const char *newval, void *extra)
+{
+ if (newval && strcmp(newval, "") != 0)
+ recoveryTarget = RECOVERY_TARGET_IMMEDIATE;
+ else
+ /*
+ * Reset recoveryTarget to RECOVERY_TARGET_UNSET to proper handle user
+ * setting multiple recovery_target with blank value on last.
+ */
+ recoveryTarget = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_xid(char **newval, void **extra, GucSource source)
+{
+ if (strcmp(*newval, "") != 0)
+ {
+ TransactionId xid;
+ TransactionId *myextra;
+
+ errno = 0;
+ xid = (TransactionId) strtoul(*newval, NULL, 0);
+ if (errno == EINVAL || errno == ERANGE)
+ return false;
+
+ myextra = (TransactionId *) guc_malloc(ERROR, sizeof(TransactionId));
+ *myextra = xid;
+ *extra = (void *) myextra;
+ }
+ return true;
+}
+
+static void
+assign_recovery_target_xid(const char *newval, void *extra)
+{
+ if (newval && strcmp(newval, "") != 0)
+ {
+ recoveryTarget = RECOVERY_TARGET_XID;
+ recoveryTargetXid = *((TransactionId *) extra);
+ }
+ else
+ recoveryTarget = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_time(char **newval, void **extra, GucSource source)
+{
+ if (strcmp(*newval, "") != 0)
+ {
+ TimestampTz time;
+ TimestampTz *myextra;
+ MemoryContext oldcontext = CurrentMemoryContext;
+
+ /* reject some special values */
+ if (strcmp(*newval, "epoch") == 0 ||
+ strcmp(*newval, "infinity") == 0 ||
+ strcmp(*newval, "-infinity") == 0 ||
+ strcmp(*newval, "now") == 0 ||
+ strcmp(*newval, "today") == 0 ||
+ strcmp(*newval, "tomorrow") == 0 ||
+ strcmp(*newval, "yesterday") == 0)
+ {
+ return false;
+ }
+
+ PG_TRY();
+ {
+ time = DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
+ CStringGetDatum(*newval),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1)));
+ }
+ PG_CATCH();
+ {
+ ErrorData *edata;
+
+ /* Save error info */
+ MemoryContextSwitchTo(oldcontext);
+ edata = CopyErrorData();
+ FlushErrorState();
+
+ /* Pass the error message */
+ GUC_check_errdetail("%s", edata->message);
+ FreeErrorData(edata);
+ return false;
+ }
+ PG_END_TRY();
+
+ myextra = (TimestampTz *) guc_malloc(ERROR, sizeof(TimestampTz));
+ *myextra = time;
+ *extra = (void *) myextra;
+ }
+ return true;
+}
+
+static void
+assign_recovery_target_time(const char *newval, void *extra)
+{
+ if (newval && strcmp(newval, "") != 0)
+ {
+ recoveryTarget = RECOVERY_TARGET_TIME;
+ recoveryTargetTime = *((TimestampTz *) extra);
+ }
+ else
+ recoveryTarget = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_name(char **newval, void **extra, GucSource source)
+{
+ /* Use the value of newval directly */
+ if (strlen(*newval) >= MAXFNAMELEN)
+ {
+ GUC_check_errdetail("recovery_target_name is too long (maximum %d characters)",
+ MAXFNAMELEN - 1);
+ return false;
+ }
+ return true;
+}
+
+static void
+assign_recovery_target_name(const char *newval, void *extra)
+{
+ if (newval && strcmp(newval, "") != 0)
+ {
+ recoveryTarget = RECOVERY_TARGET_NAME;
+ recoveryTargetName = (char *) newval;
+ }
+ else
+ recoveryTarget = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_recovery_target_lsn(char **newval, void **extra, GucSource source)
+{
+ if (strcmp(*newval, "") != 0)
+ {
+ XLogRecPtr lsn;
+ XLogRecPtr *myextra;
+ MemoryContext oldcontext = CurrentMemoryContext;
+
+ /*
+ * Convert the LSN string given by the user to XLogRecPtr form.
+ */
+ PG_TRY();
+ {
+ lsn = DatumGetLSN(DirectFunctionCall3(pg_lsn_in,
+ CStringGetDatum(*newval),
+ ObjectIdGetDatum(InvalidOid),
+ Int32GetDatum(-1)));
+ }
+ PG_CATCH();
+ {
+ ErrorData *edata;
+
+ /* Save error info */
+ MemoryContextSwitchTo(oldcontext);
+ edata = CopyErrorData();
+ FlushErrorState();
+
+ /* Pass the error message */
+ GUC_check_errdetail("%s", edata->message);
+ FreeErrorData(edata);
+ return false;
+ }
+ PG_END_TRY();
+
+ myextra = (XLogRecPtr *) guc_malloc(ERROR, sizeof(XLogRecPtr));
+ *myextra = lsn;
+ *extra = (void *) myextra;
+ }
+ return true;
+}
+
+static void
+assign_recovery_target_lsn(const char *newval, void *extra)
+{
+ if (newval && strcmp(newval, "") != 0)
+ {
+ recoveryTarget = RECOVERY_TARGET_LSN;
+ recoveryTargetLSN = *((XLogRecPtr *) extra);
+ }
+ else
+ recoveryTarget = RECOVERY_TARGET_UNSET;
+}
+
+static bool
+check_primary_slot_name(char **newval, void **extra, GucSource source)
+{
+ if (*newval && strcmp(*newval, "") != 0 &&
+ !ReplicationSlotValidateName(*newval, WARNING))
+ return false;
+
+ return true;
+}
+
#include "guc-file.c"