]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/misc/guc.c
Add option to pg_ctl to choose event source for logging
[postgresql] / src / backend / utils / misc / guc.c
index 5c910dd11240c701cbee61cbf29b9a73ba6090b5..6c52db859032af33eccb1eb53a890506f4e7b181 100644 (file)
@@ -6,7 +6,7 @@
  * See src/backend/utils/misc/README for more information.
  *
  *
- * Copyright (c) 2000-2012, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2014, PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
@@ -39,6 +39,7 @@
 #include "funcapi.h"
 #include "libpq/auth.h"
 #include "libpq/be-fsstubs.h"
+#include "libpq/libpq.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "optimizer/cost.h"
 #include "parser/scansup.h"
 #include "pgstat.h"
 #include "postmaster/autovacuum.h"
+#include "postmaster/bgworker.h"
 #include "postmaster/bgwriter.h"
 #include "postmaster/postmaster.h"
 #include "postmaster/syslogger.h"
 #include "postmaster/walwriter.h"
+#include "replication/slot.h"
 #include "replication/syncrep.h"
 #include "replication/walreceiver.h"
 #include "replication/walsender.h"
 #include "storage/bufmgr.h"
+#include "storage/dsm_impl.h"
 #include "storage/standby.h"
 #include "storage/fd.h"
+#include "storage/pg_shmem.h"
+#include "storage/proc.h"
 #include "storage/predicate.h"
 #include "tcop/tcopprot.h"
 #include "tsearch/ts_cache.h"
@@ -79,9 +85,6 @@
 #ifndef PG_KRB_SRVTAB
 #define PG_KRB_SRVTAB ""
 #endif
-#ifndef PG_KRB_SRVNAM
-#define PG_KRB_SRVNAM ""
-#endif
 
 #define CONFIG_FILENAME "postgresql.conf"
 #define HBA_FILENAME   "pg_hba.conf"
 #define MAX_KILOBYTES  (INT_MAX / 1024)
 #endif
 
-/*
- * Note: MAX_BACKENDS is limited to 2^23-1 because inval.c stores the
- * backend ID as a 3-byte signed integer.  Even if that limitation were
- * removed, we still could not exceed INT_MAX/4 because some places compute
- * 4*MaxBackends without any overflow check.  This is rechecked in
- * check_maxconnections, since MaxBackends is computed as MaxConnections
- * plus autovacuum_max_workers plus one (for the autovacuum launcher).
- */
-#define MAX_BACKENDS   0x7fffff
-
 #define KB_PER_MB (1024)
 #define KB_PER_GB (1024*1024)
+#define KB_PER_TB (1024*1024*1024)
 
 #define MS_PER_S 1000
 #define S_PER_MIN 60
@@ -129,10 +123,11 @@ extern int        CommitDelay;
 extern int     CommitSiblings;
 extern char *default_tablespace;
 extern char *temp_tablespaces;
+extern bool ignore_checksum_failure;
 extern bool synchronize_seqscans;
-extern bool fullPageWrites;
-extern int     ssl_renegotiation_limit;
 extern char *SSLCipherSuites;
+extern char *SSLECDHCurve;
+extern bool SSLPreferServerCiphers;
 
 #ifdef TRACE_SORT
 extern bool trace_sort;
@@ -179,7 +174,6 @@ static void assign_syslog_ident(const char *newval, void *extra);
 static void assign_session_replication_role(int newval, void *extra);
 static bool check_temp_buffers(int *newval, void **extra, GucSource source);
 static bool check_phony_autocommit(bool *newval, void **extra, GucSource source);
-static bool check_debug_assertions(bool *newval, void **extra, GucSource source);
 static bool check_bonjour(bool *newval, void **extra, GucSource source);
 static bool check_ssl(bool *newval, void **extra, GucSource source);
 static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
@@ -196,14 +190,15 @@ static const char *show_tcp_keepalives_idle(void);
 static const char *show_tcp_keepalives_interval(void);
 static const char *show_tcp_keepalives_count(void);
 static bool check_maxconnections(int *newval, void **extra, GucSource source);
-static void assign_maxconnections(int newval, void *extra);
+static bool check_max_worker_processes(int *newval, void **extra, GucSource source);
 static bool check_autovacuum_max_workers(int *newval, void **extra, GucSource source);
-static void assign_autovacuum_max_workers(int newval, void *extra);
+static bool check_autovacuum_work_mem(int *newval, void **extra, GucSource source);
 static bool check_effective_io_concurrency(int *newval, void **extra, GucSource source);
 static void assign_effective_io_concurrency(int newval, void *extra);
 static void assign_pgstat_temp_directory(const char *newval, void *extra);
 static bool check_application_name(char **newval, void **extra, GucSource source);
 static void assign_application_name(const char *newval, void *extra);
+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);
 
@@ -211,6 +206,10 @@ static char *config_enum_get_options(struct config_enum * record,
                                                const char *prefix, const char *suffix,
                                                const char *separator);
 
+static bool validate_conf_option(struct config_generic * record,
+                                        const char *name, const char *value, GucSource source,
+                                        int elevel, bool freemem, void *newval, void **newextra);
+
 
 /*
  * Options for enum values defined in this module.
@@ -370,11 +369,12 @@ static const struct config_enum_entry constraint_exclusion_options[] = {
 };
 
 /*
- * Although only "on", "off", and "local" are documented, we
+ * Although only "on", "off", "remote_write", and "local" are documented, we
  * accept all the likely variants of "on" and "off".
  */
 static const struct config_enum_entry synchronous_commit_options[] = {
        {"local", SYNCHRONOUS_COMMIT_LOCAL_FLUSH, false},
+       {"remote_write", SYNCHRONOUS_COMMIT_REMOTE_WRITE, false},
        {"on", SYNCHRONOUS_COMMIT_ON, false},
        {"off", SYNCHRONOUS_COMMIT_OFF, false},
        {"true", SYNCHRONOUS_COMMIT_ON, true},
@@ -386,20 +386,33 @@ static const struct config_enum_entry synchronous_commit_options[] = {
        {NULL, 0, false}
 };
 
+/*
+ * Although only "on", "off", "try" are documented, we accept all the likely
+ * variants of "on" and "off".
+ */
+static const struct config_enum_entry huge_pages_options[] = {
+       {"off", HUGE_PAGES_OFF, false},
+       {"on", HUGE_PAGES_ON, false},
+       {"try", HUGE_PAGES_TRY, false},
+       {"true", HUGE_PAGES_ON, true},
+       {"false", HUGE_PAGES_OFF, true},
+       {"yes", HUGE_PAGES_ON, true},
+       {"no", HUGE_PAGES_OFF, true},
+       {"1", HUGE_PAGES_ON, true},
+       {"0", HUGE_PAGES_OFF, true},
+       {NULL, 0, false}
+};
+
 /*
  * Options for enum values stored in other modules
  */
 extern const struct config_enum_entry wal_level_options[];
 extern const struct config_enum_entry sync_method_options[];
+extern const struct config_enum_entry dynamic_shared_memory_options[];
 
 /*
  * GUC option variables that are exported from this module
  */
-#ifdef USE_ASSERT_CHECKING
-bool           assert_enabled = true;
-#else
-bool           assert_enabled = false;
-#endif
 bool           log_duration = false;
 bool           Debug_print_plan = false;
 bool           Debug_print_parse = false;
@@ -431,6 +444,7 @@ int                 temp_file_limit = -1;
 
 int                    num_temp_buffers = 1024;
 
+char      *cluster_name = "";
 char      *data_directory;
 char      *ConfigFileName;
 char      *HbaFileName;
@@ -445,13 +459,17 @@ int                       tcp_keepalives_idle;
 int                    tcp_keepalives_interval;
 int                    tcp_keepalives_count;
 
+/*
+ * This really belongs in pg_shmem.c, but is defined here so that it doesn't
+ * need to be duplicated in all the different implementations of pg_shmem.c.
+ */
+int                    huge_pages;
+
 /*
  * These variables are all dummies that don't do anything, except in some
  * cases provide the value for SHOW to display.  The real state is elsewhere
  * and is kept in sync by assign_hooks.
  */
-static char *log_destination_string;
-
 static char *syslog_ident_str;
 static bool phony_autocommit;
 static bool session_auth_is_superuser;
@@ -474,9 +492,11 @@ static int max_identifier_length;
 static int     block_size;
 static int     segment_size;
 static int     wal_block_size;
+static bool data_checksums;
 static int     wal_segment_size;
 static bool integer_datetimes;
 static int     effective_io_concurrency;
+static bool    assert_enabled;
 
 /* should be static, but commands/variable.c needs to get at this */
 char      *role_string;
@@ -509,6 +529,7 @@ const char *const GucSource_Names[] =
         /* PGC_S_ENV_VAR */ "environment variable",
         /* PGC_S_FILE */ "configuration file",
         /* PGC_S_ARGV */ "command line",
+        /* PGC_S_GLOBAL */ "global",
         /* PGC_S_DATABASE */ "database",
         /* PGC_S_USER */ "user",
         /* PGC_S_DATABASE_USER */ "database user",
@@ -596,6 +617,8 @@ const char *const config_group_names[] =
        gettext_noop("Client Connection Defaults / Statement Behavior"),
        /* CLIENT_CONN_LOCALE */
        gettext_noop("Client Connection Defaults / Locale and Formatting"),
+       /* CLIENT_CONN_PRELOAD */
+       gettext_noop("Client Connection Defaults / Shared Library Preloading"),
        /* CLIENT_CONN_OTHER */
        gettext_noop("Client Connection Defaults / Other Defaults"),
        /* LOCK_MANAGEMENT */
@@ -803,6 +826,15 @@ static struct config_bool ConfigureNamesBool[] =
                false,
                check_ssl, NULL, NULL
        },
+       {
+               {"ssl_prefer_server_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+                       gettext_noop("Give priority to server ciphersuite order."),
+                       NULL
+               },
+               &SSLPreferServerCiphers,
+               true,
+               NULL, NULL, NULL
+       },
        {
                {"fsync", PGC_SIGHUP, WAL_SETTINGS,
                        gettext_noop("Forces synchronization of updates to disk."),
@@ -815,6 +847,21 @@ static struct config_bool ConfigureNamesBool[] =
                true,
                NULL, NULL, NULL
        },
+       {
+               {"ignore_checksum_failure", PGC_SUSET, DEVELOPER_OPTIONS,
+                       gettext_noop("Continues processing after a checksum failure."),
+                       gettext_noop("Detection of a checksum failure normally causes PostgreSQL to "
+                               "report an error, aborting the current transaction. Setting "
+                                                "ignore_checksum_failure to true causes the system to ignore the failure "
+                          "(but still report a warning), and continue processing. This "
+                         "behavior could cause crashes or other serious problems. Only "
+                                                "has an effect if checksums are enabled."),
+                       GUC_NOT_IN_SAMPLE
+               },
+               &ignore_checksum_failure,
+               false,
+               NULL, NULL, NULL
+       },
        {
                {"zero_damaged_pages", PGC_SUSET, DEVELOPER_OPTIONS,
                        gettext_noop("Continues processing past damaged page headers."),
@@ -842,6 +889,17 @@ static struct config_bool ConfigureNamesBool[] =
                true,
                NULL, NULL, NULL
        },
+
+       {
+               {"wal_log_hints", PGC_POSTMASTER, WAL_SETTINGS,
+                       gettext_noop("Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modifications"),
+                       NULL
+               },
+               &wal_log_hints,
+               false,
+               NULL, NULL, NULL
+       },
+
        {
                {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
                        gettext_noop("Logs each checkpoint."),
@@ -870,10 +928,10 @@ static struct config_bool ConfigureNamesBool[] =
                NULL, NULL, NULL
        },
        {
-               {"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
-                       gettext_noop("Turns on various assertion checks."),
-                       gettext_noop("This is a debugging aid."),
-                       GUC_NOT_IN_SAMPLE
+               {"debug_assertions", PGC_INTERNAL, PRESET_OPTIONS,
+                       gettext_noop("Shows whether the running server has assertion checks enabled."),
+                       NULL,
+                       GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
                },
                &assert_enabled,
 #ifdef USE_ASSERT_CHECKING
@@ -881,7 +939,7 @@ static struct config_bool ConfigureNamesBool[] =
 #else
                false,
 #endif
-               check_debug_assertions, NULL, NULL
+               NULL, NULL, NULL
        },
 
        {
@@ -987,7 +1045,7 @@ static struct config_bool ConfigureNamesBool[] =
 #ifdef BTREE_BUILD_STATS
        {
                {"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
+                       gettext_noop("Logs system resource usage statistics (memory and CPU) on various B-tree operations."),
                        NULL,
                        GUC_NOT_IN_SAMPLE
                },
@@ -1017,6 +1075,15 @@ static struct config_bool ConfigureNamesBool[] =
                true,
                NULL, NULL, NULL
        },
+       {
+               {"track_io_timing", PGC_SUSET, STATS_COLLECTOR,
+                       gettext_noop("Collects timing statistics for database I/O activity."),
+                       NULL
+               },
+               &track_io_timing,
+               false,
+               NULL, NULL, NULL
+       },
 
        {
                {"update_process_title", PGC_SUSET, STATS_COLLECTOR,
@@ -1052,7 +1119,7 @@ static struct config_bool ConfigureNamesBool[] =
 #ifdef LOCK_DEBUG
        {
                {"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
+                       gettext_noop("Emits information about lock usage."),
                        NULL,
                        GUC_NOT_IN_SAMPLE
                },
@@ -1062,7 +1129,7 @@ static struct config_bool ConfigureNamesBool[] =
        },
        {
                {"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
+                       gettext_noop("Emits information about user lock usage."),
                        NULL,
                        GUC_NOT_IN_SAMPLE
                },
@@ -1072,7 +1139,7 @@ static struct config_bool ConfigureNamesBool[] =
        },
        {
                {"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
+                       gettext_noop("Emits information about lightweight lock usage."),
                        NULL,
                        GUC_NOT_IN_SAMPLE
                },
@@ -1082,7 +1149,7 @@ static struct config_bool ConfigureNamesBool[] =
        },
        {
                {"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
+                       gettext_noop("Dumps information about all current locks when a deadlock timeout occurs."),
                        NULL,
                        GUC_NOT_IN_SAMPLE
                },
@@ -1438,6 +1505,17 @@ static struct config_bool ConfigureNamesBool[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"data_checksums", PGC_INTERNAL, PRESET_OPTIONS,
+                       gettext_noop("Shows whether data checksums are turned on for this cluster."),
+                       NULL,
+                       GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
+               },
+               &data_checksums,
+               false,
+               NULL, NULL, NULL
+       },
+
        /* End-of-list marker */
        {
                {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
@@ -1455,7 +1533,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_S
                },
                &XLogArchiveTimeout,
-               0, 0, INT_MAX,
+               0, 0, INT_MAX / 2,
                NULL, NULL, NULL
        },
        {
@@ -1465,7 +1543,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_NOT_IN_SAMPLE | GUC_UNIT_S
                },
                &PostAuthDelay,
-               0, 0, INT_MAX,
+               0, 0, INT_MAX / 1000000,
                NULL, NULL, NULL
        },
        {
@@ -1584,6 +1662,17 @@ static struct config_int ConfigureNamesInt[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY,
+                       gettext_noop("Sets the maximum wait time to receive data from the primary."),
+                       NULL,
+                       GUC_UNIT_MS
+               },
+               &wal_receiver_timeout,
+               60 * 1000, 0, INT_MAX,
+               NULL, NULL, NULL
+       },
+
        {
                {"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
                        gettext_noop("Sets the maximum number of concurrent connections."),
@@ -1591,7 +1680,7 @@ static struct config_int ConfigureNamesInt[] =
                },
                &MaxConnections,
                100, 1, MAX_BACKENDS,
-               check_maxconnections, assign_maxconnections, NULL
+               check_maxconnections, NULL, NULL
        },
 
        {
@@ -1678,7 +1767,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_KB
                },
                &work_mem,
-               1024, 64, MAX_KILOBYTES,
+               4096, 64, MAX_KILOBYTES,
                NULL, NULL, NULL
        },
 
@@ -1689,7 +1778,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_KB
                },
                &maintenance_work_mem,
-               16384, 1024, MAX_KILOBYTES,
+               65536, 1024, MAX_KILOBYTES,
                NULL, NULL, NULL
        },
 
@@ -1711,7 +1800,7 @@ static struct config_int ConfigureNamesInt[] =
 
        {
                {"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
-                       gettext_noop("Limits the total size of all temp files used by each session."),
+                       gettext_noop("Limits the total size of all temporary files used by each session."),
                        gettext_noop("-1 means no limit."),
                        GUC_UNIT_KB
                },
@@ -1818,8 +1907,8 @@ static struct config_int ConfigureNamesInt[] =
 #ifdef LOCK_DEBUG
        {
                {"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
-                       NULL,
+                       gettext_noop("Sets the minimum OID of tables for tracking locks."),
+                       gettext_noop("Is used to avoid output on system tables."),
                        GUC_NOT_IN_SAMPLE
                },
                &Trace_lock_oidmin,
@@ -1828,7 +1917,7 @@ static struct config_int ConfigureNamesInt[] =
        },
        {
                {"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
-                       gettext_noop("No description available."),
+                       gettext_noop("Sets the OID of the table with unconditionally lock tracing."),
                        NULL,
                        GUC_NOT_IN_SAMPLE
                },
@@ -1849,6 +1938,17 @@ static struct config_int ConfigureNamesInt[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
+                       gettext_noop("Sets the maximum allowed duration of any wait for a lock."),
+                       gettext_noop("A value of 0 turns off the timeout."),
+                       GUC_UNIT_MS
+               },
+               &LockTimeout,
+               0, 0, INT_MAX,
+               NULL, NULL, NULL
+       },
+
        {
                {"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
                        gettext_noop("Minimum age at which VACUUM should freeze a table row."),
@@ -1869,6 +1969,26 @@ static struct config_int ConfigureNamesInt[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"vacuum_multixact_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
+                       gettext_noop("Minimum age at which VACUUM should freeze a MultiXactId in a table row."),
+                       NULL
+               },
+               &vacuum_multixact_freeze_min_age,
+               5000000, 0, 1000000000,
+               NULL, NULL, NULL
+       },
+
+       {
+               {"vacuum_multixact_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
+                       gettext_noop("Multixact age at which VACUUM should scan whole table to freeze tuples."),
+                       NULL
+               },
+               &vacuum_multixact_freeze_table_age,
+               150000000, 0, 2000000000,
+               NULL, NULL, NULL
+       },
+
        {
                {"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_MASTER,
                        gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
@@ -1996,6 +2116,17 @@ static struct config_int ConfigureNamesInt[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"xloginsert_locks", PGC_POSTMASTER, WAL_SETTINGS,
+                       gettext_noop("Sets the number of locks used for concurrent xlog insertions."),
+                       NULL,
+                       GUC_NOT_IN_SAMPLE
+               },
+               &num_xloginsert_locks,
+               8, 1, 1000,
+               NULL, NULL, NULL
+       },
+
        {
                /* see max_connections */
                {"max_wal_senders", PGC_POSTMASTER, REPLICATION_SENDING,
@@ -2008,21 +2139,33 @@ static struct config_int ConfigureNamesInt[] =
        },
 
        {
-               {"replication_timeout", PGC_SIGHUP, REPLICATION_SENDING,
+               /* see max_connections */
+               {"max_replication_slots", PGC_POSTMASTER, REPLICATION_SENDING,
+                       gettext_noop("Sets the maximum number of simultaneously defined replication slots."),
+                       NULL
+               },
+               &max_replication_slots,
+               0, 0, MAX_BACKENDS /* XXX? */ ,
+               NULL, NULL, NULL
+       },
+
+       {
+               {"wal_sender_timeout", PGC_SIGHUP, REPLICATION_SENDING,
                        gettext_noop("Sets the maximum time to wait for WAL replication."),
                        NULL,
                        GUC_UNIT_MS
                },
-               &replication_timeout,
+               &wal_sender_timeout,
                60 * 1000, 0, INT_MAX,
                NULL, NULL, NULL
        },
 
        {
-               {"commit_delay", PGC_USERSET, WAL_SETTINGS,
+               {"commit_delay", PGC_SUSET, WAL_SETTINGS,
                        gettext_noop("Sets the delay in microseconds between transaction commit and "
                                                 "flushing WAL to disk."),
                        NULL
+                       /* we have no microseconds designation, so can't supply units here */
                },
                &CommitDelay,
                0, 0, 100000,
@@ -2117,6 +2260,18 @@ static struct config_int ConfigureNamesInt[] =
                check_effective_io_concurrency, assign_effective_io_concurrency, NULL
        },
 
+       {
+               {"max_worker_processes",
+                       PGC_POSTMASTER,
+                       RESOURCES_ASYNCHRONOUS,
+                       gettext_noop("Maximum number of concurrent worker processes."),
+                       NULL,
+               },
+               &max_worker_processes,
+               8, 1, MAX_BACKENDS,
+               check_max_worker_processes, NULL, NULL
+       },
+
        {
                {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
                        gettext_noop("Automatic log file rotation will occur after N minutes."),
@@ -2124,7 +2279,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_MIN
                },
                &Log_RotationAge,
-               HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR,
+               HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / SECS_PER_MINUTE,
                NULL, NULL, NULL
        },
 
@@ -2239,7 +2394,7 @@ static struct config_int ConfigureNamesInt[] =
        },
        {
                {"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
-                       gettext_noop("Minimum number of tuple inserts, updates or deletes prior to analyze."),
+                       gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."),
                        NULL
                },
                &autovacuum_anl_thresh,
@@ -2257,6 +2412,16 @@ static struct config_int ConfigureNamesInt[] =
                200000000, 100000000, 2000000000,
                NULL, NULL, NULL
        },
+       {
+               /* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
+               {"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
+                       gettext_noop("Multixact age at which to autovacuum a table to prevent multixact wraparound."),
+                       NULL
+               },
+               &autovacuum_multixact_freeze_max_age,
+               400000000, 10000000, 2000000000,
+               NULL, NULL, NULL
+       },
        {
                /* see max_connections */
                {"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
@@ -2265,7 +2430,18 @@ static struct config_int ConfigureNamesInt[] =
                },
                &autovacuum_max_workers,
                3, 1, MAX_BACKENDS,
-               check_autovacuum_max_workers, assign_autovacuum_max_workers, NULL
+               check_autovacuum_max_workers, NULL, NULL
+       },
+
+       {
+               {"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM,
+                       gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."),
+                       NULL,
+                       GUC_UNIT_KB
+               },
+               &autovacuum_work_mem,
+               -1, -1, MAX_KILOBYTES,
+               check_autovacuum_work_mem, NULL, NULL
        },
 
        {
@@ -2362,8 +2538,13 @@ static struct config_int ConfigureNamesInt[] =
 
        {
                {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
-                       gettext_noop("Sets the size reserved for pg_stat_activity.current_query, in bytes."),
+                       gettext_noop("Sets the size reserved for pg_stat_activity.query, in bytes."),
                        NULL,
+
+                       /*
+                        * There is no _bytes_ unit, so the user can't supply units for
+                        * this.
+                        */
                },
                &pgstat_track_activity_query_size,
                1024, 100, 102400,
@@ -2493,7 +2674,7 @@ static struct config_real ConfigureNamesReal[] =
        },
        {
                {"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
-                       gettext_noop("Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples."),
+                       gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
                        NULL
                },
                &autovacuum_anl_scale,
@@ -2620,16 +2801,6 @@ static struct config_string ConfigureNamesString[] =
                NULL, NULL, NULL
        },
 
-       {
-               {"krb_srvname", PGC_SIGHUP, CONN_AUTH_SECURITY,
-                       gettext_noop("Sets the name of the Kerberos service."),
-                       NULL
-               },
-               &pg_krb_srvnam,
-               PG_KRB_SRVNAM,
-               NULL, NULL, NULL
-       },
-
        {
                {"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
                        gettext_noop("Sets the Bonjour service name."),
@@ -2705,7 +2876,18 @@ static struct config_string ConfigureNamesString[] =
        },
 
        {
-               {"shared_preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
+               {"session_preload_libraries", PGC_SUSET, CLIENT_CONN_PRELOAD,
+                       gettext_noop("Lists shared libraries to preload into each backend."),
+                       NULL,
+                       GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
+               },
+               &session_preload_libraries_string,
+               "",
+               NULL, NULL, NULL
+       },
+
+       {
+               {"shared_preload_libraries", PGC_POSTMASTER, CLIENT_CONN_PRELOAD,
                        gettext_noop("Lists shared libraries to preload into server."),
                        NULL,
                        GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
@@ -2716,8 +2898,8 @@ static struct config_string ConfigureNamesString[] =
        },
 
        {
-               {"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_OTHER,
-                       gettext_noop("Lists shared libraries to preload into each backend."),
+               {"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_PRELOAD,
+                       gettext_noop("Lists unprivileged shared libraries to preload into each backend."),
                        NULL,
                        GUC_LIST_INPUT | GUC_LIST_QUOTE
                },
@@ -2793,7 +2975,7 @@ static struct config_string ConfigureNamesString[] =
                                                 "depending on the platform."),
                        GUC_LIST_INPUT
                },
-               &log_destination_string,
+               &Log_destination_string,
                "stderr",
                check_log_destination, assign_log_destination, NULL
        },
@@ -2832,12 +3014,12 @@ static struct config_string ConfigureNamesString[] =
 
        {
                {"event_source", PGC_POSTMASTER, LOGGING_WHERE,
-                       gettext_noop("Sets the application name used to identify"
+                       gettext_noop("Sets the application name used to identify "
                                                 "PostgreSQL messages in the event log."),
                        NULL
                },
                &event_source,
-               "PostgreSQL",
+               DEFAULT_EVENT_SOURCE,
                NULL, NULL, NULL
        },
 
@@ -2884,14 +3066,18 @@ static struct config_string ConfigureNamesString[] =
        },
 
        {
-               {"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
-                       gettext_noop("Sets the directory where the Unix-domain socket will be created."),
+               {"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
+                       gettext_noop("Sets the directories where Unix-domain sockets will be created."),
                        NULL,
                        GUC_SUPERUSER_ONLY
                },
-               &UnixSocketDir,
+               &Unix_socket_directories,
+#ifdef HAVE_UNIX_SOCKETS
+               DEFAULT_PGSOCKET_DIR,
+#else
                "",
-               check_canonical_path, NULL, NULL
+#endif
+               NULL, NULL, NULL
        },
 
        {
@@ -2906,10 +3092,14 @@ static struct config_string ConfigureNamesString[] =
        },
 
        {
+               /*
+                * Can't be set by ALTER SYSTEM as it can lead to recursive definition
+                * of data_directory.
+                */
                {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
                        gettext_noop("Sets the server's data directory."),
                        NULL,
-                       GUC_SUPERUSER_ONLY
+                       GUC_SUPERUSER_ONLY | GUC_DISALLOW_IN_AUTO_FILE
                },
                &data_directory,
                NULL,
@@ -2960,6 +3150,46 @@ static struct config_string ConfigureNamesString[] =
                check_canonical_path, NULL, NULL
        },
 
+       {
+               {"ssl_cert_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+                       gettext_noop("Location of the SSL server certificate file."),
+                       NULL
+               },
+               &ssl_cert_file,
+               "server.crt",
+               NULL, NULL, NULL
+       },
+
+       {
+               {"ssl_key_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+                       gettext_noop("Location of the SSL server private key file."),
+                       NULL
+               },
+               &ssl_key_file,
+               "server.key",
+               NULL, NULL, NULL
+       },
+
+       {
+               {"ssl_ca_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+                       gettext_noop("Location of the SSL certificate authority file."),
+                       NULL
+               },
+               &ssl_ca_file,
+               "",
+               NULL, NULL, NULL
+       },
+
+       {
+               {"ssl_crl_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+                       gettext_noop("Location of the SSL certificate revocation list file."),
+                       NULL
+               },
+               &ssl_crl_file,
+               "",
+               NULL, NULL, NULL
+       },
+
        {
                {"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
                        gettext_noop("Writes temporary statistics files to the specified directory."),
@@ -2967,7 +3197,7 @@ static struct config_string ConfigureNamesString[] =
                        GUC_SUPERUSER_ONLY
                },
                &pgstat_temp_directory,
-               "pg_stat_tmp",
+               PG_STAT_TMP_DIR,
                check_canonical_path, assign_pgstat_temp_directory, NULL
        },
 
@@ -3000,7 +3230,22 @@ static struct config_string ConfigureNamesString[] =
                },
                &SSLCipherSuites,
 #ifdef USE_SSL
-               "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH",
+               "HIGH:MEDIUM:+3DES:!aNULL",
+#else
+               "none",
+#endif
+               NULL, NULL, NULL
+       },
+
+       {
+               {"ssl_ecdh_curve", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+                       gettext_noop("Sets the curve to use for ECDH."),
+                       NULL,
+                       GUC_SUPERUSER_ONLY
+               },
+               &SSLECDHCurve,
+#ifdef USE_SSL
+               "prime256v1",
 #else
                "none",
 #endif
@@ -3018,6 +3263,17 @@ static struct config_string ConfigureNamesString[] =
                check_application_name, assign_application_name, NULL
        },
 
+       {
+               {"cluster_name", PGC_POSTMASTER, LOGGING_WHAT,
+                       gettext_noop("Sets the name of the cluster which is included in the process title."),
+                       NULL,
+                       GUC_IS_NAME
+               },
+               &cluster_name,
+               "",
+               check_cluster_name, NULL, NULL
+       },
+
        /* End-of-list marker */
        {
                {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
@@ -3164,7 +3420,7 @@ static struct config_enum ConfigureNamesEnum[] =
                },
                &synchronous_commit,
                SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
-               NULL, NULL, NULL
+               NULL, assign_synchronous_commit, NULL
        },
 
        {
@@ -3203,6 +3459,16 @@ static struct config_enum ConfigureNamesEnum[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"dynamic_shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
+                       gettext_noop("Selects the dynamic shared memory implementation used."),
+                       NULL
+               },
+               &dynamic_shared_memory_type,
+               DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE, dynamic_shared_memory_options,
+               NULL, NULL, NULL
+       },
+
        {
                {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
                        gettext_noop("Selects the method used for forcing WAL updates to disk."),
@@ -3234,6 +3500,15 @@ static struct config_enum ConfigureNamesEnum[] =
                NULL, NULL, NULL
        },
 
+       {
+               {"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
+                       gettext_noop("Use of huge pages on Linux"),
+                       NULL
+               },
+               &huge_pages,
+               HUGE_PAGES_TRY, huge_pages_options,
+               NULL, NULL, NULL
+       },
 
        /* End-of-list marker */
        {
@@ -3283,7 +3558,7 @@ static void InitializeOneGUCOption(struct config_generic * gconf);
 static void push_old_value(struct config_generic * gconf, GucAction action);
 static void ReportGUCOption(struct config_generic * record);
 static void reapply_stacked_values(struct config_generic * variable,
-                                          struct config_string *pHolder,
+                                          struct config_string * pHolder,
                                           GucStack *stack,
                                           const char *curvalue,
                                           GucContext curscontext, GucSource cursource);
@@ -3292,6 +3567,9 @@ static void ShowAllGUCConfig(DestReceiver *dest);
 static char *_ShowOption(struct config_generic * record, bool use_units);
 static bool validate_option_array_item(const char *name, const char *value,
                                                   bool skipIfNoPermissions);
+static void write_auto_conf_file(int fd, const char *filename, ConfigVariable **head_p);
+static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
+                                                 char *config_file, char *name, char *value);
 
 
 /*
@@ -3302,6 +3580,9 @@ guc_malloc(int elevel, size_t size)
 {
        void       *data;
 
+       /* Avoid unportable behavior of malloc(0) */
+       if (size == 0)
+               size = 1;
        data = malloc(size);
        if (data == NULL)
                ereport(elevel,
@@ -3315,6 +3596,9 @@ guc_realloc(int elevel, void *old, size_t size)
 {
        void       *data;
 
+       /* Avoid unportable behavior of realloc(NULL, 0) */
+       if (old == NULL && size == 0)
+               size = 1;
        data = realloc(old, size);
        if (data == NULL)
                ereport(elevel,
@@ -3510,7 +3794,7 @@ get_guc_variables(void)
 
 
 /*
- * Build the sorted array.     This is split out so that it could be
+ * Build the sorted array.  This is split out so that it could be
  * re-executed after startup (eg, we could allow loadable modules to
  * add vars, and then we'd need to re-sort).
  */
@@ -3667,7 +3951,7 @@ add_placeholder_variable(const char *name, int elevel)
 
        /*
         * The char* is allocated at the end of the struct since we have no
-        * 'static' place to point to.  Note that the current value, as well as
+        * 'static' place to point to.  Note that the current value, as well as
         * the boot and reset values, start out NULL.
         */
        var->variable = (char **) (var + 1);
@@ -3709,7 +3993,7 @@ find_option(const char *name, bool create_placeholders, int elevel)
                return *res;
 
        /*
-        * See if the name is an obsolete name for a variable.  We assume that the
+        * See if the name is an obsolete name for a variable.  We assume that the
         * set of supported old names is short enough that a brute-force search is
         * the best way.
         */
@@ -3739,8 +4023,8 @@ find_option(const char *name, bool create_placeholders, int elevel)
 static int
 guc_var_compare(const void *a, const void *b)
 {
-       struct config_generic *confa = *(struct config_generic **) a;
-       struct config_generic *confb = *(struct config_generic **) b;
+       const struct config_generic *confa = *(struct config_generic * const *) a;
+       const struct config_generic *confb = *(struct config_generic * const *) b;
 
        return guc_name_compare(confa->name, confb->name);
 }
@@ -4054,6 +4338,7 @@ SelectConfigFiles(const char *userDoption, const char *progname)
        {
                write_stderr("%s cannot access the server configuration file \"%s\": %s\n",
                                         progname, ConfigFileName, strerror(errno));
+               free(configdir);
                return false;
        }
 
@@ -4090,10 +4375,18 @@ SelectConfigFiles(const char *userDoption, const char *progname)
         */
        SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
 
+       /*
+        * Now read the config file a second time, allowing any settings in
+        * the PG_AUTOCONF_FILENAME file to take effect.  (This is pretty ugly,
+        * but since we have to determine the DataDir before we can find the
+        * autoconf file, the alternatives seem worse.)
+        */
+       ProcessConfigFile(PGC_POSTMASTER);
+
        /*
         * If timezone_abbreviations wasn't set in the configuration file, install
-        * the default value.  We do it this way because we can't safely install
-        * "real" value until my_exec_path is set, which may not have happened
+        * the default value.  We do it this way because we can't safely install a
+        * "real" value until my_exec_path is set, which may not have happened
         * when InitializeGUCOptions runs, so the bootstrap default value cannot
         * be the real desired default.
         */
@@ -4746,7 +5039,7 @@ parse_int(const char *value, int *result, int flags, const char **hintmsg)
                {
                        /* Set hint for use if no match or trailing garbage */
                        if (hintmsg)
-                               *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\".");
+                               *hintmsg = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", \"GB\", and \"TB\".");
 
 #if BLCKSZ < 1024 || BLCKSZ > (1024*1024)
 #error BLCKSZ must be between 1KB and 1MB
@@ -4800,6 +5093,22 @@ parse_int(const char *value, int *result, int flags, const char **hintmsg)
                                                break;
                                }
                        }
+                       else if (strncmp(endptr, "TB", 2) == 0)
+                       {
+                               endptr += 2;
+                               switch (flags & GUC_UNIT_MEMORY)
+                               {
+                                       case GUC_UNIT_KB:
+                                               val *= KB_PER_TB;
+                                               break;
+                                       case GUC_UNIT_BLOCKS:
+                                               val *= KB_PER_TB / (BLCKSZ / 1024);
+                                               break;
+                                       case GUC_UNIT_XBLOCKS:
+                                               val *= KB_PER_TB / (XLOG_BLCKSZ / 1024);
+                                               break;
+                               }
+                       }
                }
                else if (flags & GUC_UNIT_TIME)
                {
@@ -5031,49 +5340,263 @@ config_enum_get_options(struct config_enum * record, const char *prefix,
        return retstr.data;
 }
 
-
 /*
- * Sets option `name' to given value.
- *
- * The value should be a string, which will be parsed and converted to
- * the appropriate data type.  The context and source parameters indicate
- * in which context this function is being called, so that it can apply the
- * access restrictions properly.
- *
- * If value is NULL, set the option to its default value (normally the
- * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
- *
- * action indicates whether to set the value globally in the session, locally
- * to the current top transaction, or just for the duration of a function call.
- *
- * If changeVal is false then don't really set the option but do all
- * the checks to see if it would work.
- *
- * elevel should normally be passed as zero, allowing this function to make
- * its standard choice of ereport level.  However some callers need to be
- * able to override that choice; they should pass the ereport level to use.
+ * Validates configuration parameter and value, by calling check hook functions
+ * depending on record's vartype. It validates if the parameter
+ * value given is in range of expected predefined value for that parameter.
  *
+ * freemem - true indicates memory for newval and newextra will be
+ *                      freed in this function, false indicates it will be freed
+ *                      by caller.
  * Return value:
- *     +1: the value is valid and was successfully applied.
- *     0:  the name or value is invalid (but see below).
- *     -1: the value was not applied because of context, priority, or changeVal.
- *
- * If there is an error (non-existing option, invalid value) then an
- * ereport(ERROR) is thrown *unless* this is called for a source for which
- * we don't want an ERROR (currently, those are defaults, the config file,
- * and per-database or per-user settings, as well as callers who specify
- * a less-than-ERROR elevel).  In those cases we write a suitable error
- * message via ereport() and return 0.
- *
- * See also SetConfigOption for an external interface.
+ *     1: the value is valid
+ *     0: the name or value is invalid
  */
-int
-set_config_option(const char *name, const char *value,
-                                 GucContext context, GucSource source,
-                                 GucAction action, bool changeVal, int elevel)
+static bool
+validate_conf_option(struct config_generic * record, const char *name,
+                                        const char *value, GucSource source, int elevel,
+                                        bool freemem, void *newval, void **newextra)
 {
-       struct config_generic *record;
-       bool            prohibitValueChange = false;
+       /*
+        * Validate the value for the passed record, to ensure it is in expected
+        * range.
+        */
+       switch (record->vartype)
+       {
+
+               case PGC_BOOL:
+                       {
+                               struct config_bool *conf = (struct config_bool *) record;
+                               bool            tmpnewval;
+
+                               if (newval == NULL)
+                                       newval = &tmpnewval;
+
+                               if (value != NULL)
+                               {
+                                       if (!parse_bool(value, newval))
+                                       {
+                                               ereport(elevel,
+                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                 errmsg("parameter \"%s\" requires a Boolean value",
+                                                                name)));
+                                               return 0;
+                                       }
+
+                                       if (!call_bool_check_hook(conf, newval, newextra,
+                                                                                         source, elevel))
+                                               return 0;
+
+                                       if (*newextra && freemem)
+                                               free(*newextra);
+                               }
+                       }
+                       break;
+               case PGC_INT:
+                       {
+                               struct config_int *conf = (struct config_int *) record;
+                               int                     tmpnewval;
+
+                               if (newval == NULL)
+                                       newval = &tmpnewval;
+
+                               if (value != NULL)
+                               {
+                                       const char *hintmsg;
+
+                                       if (!parse_int(value, newval, conf->gen.flags, &hintmsg))
+                                       {
+                                               ereport(elevel,
+                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                errmsg("invalid value for parameter \"%s\": \"%s\"",
+                                                               name, value),
+                                                                hintmsg ? errhint("%s", _(hintmsg)) : 0));
+                                               return 0;
+                                       }
+
+                                       if (*((int *) newval) < conf->min || *((int *) newval) > conf->max)
+                                       {
+                                               ereport(elevel,
+                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                                errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
+                                                       *((int *) newval), name, conf->min, conf->max)));
+                                               return 0;
+                                       }
+
+                                       if (!call_int_check_hook(conf, newval, newextra,
+                                                                                        source, elevel))
+                                               return 0;
+
+                                       if (*newextra && freemem)
+                                               free(*newextra);
+                               }
+                       }
+                       break;
+               case PGC_REAL:
+                       {
+                               struct config_real *conf = (struct config_real *) record;
+                               double          tmpnewval;
+
+                               if (newval == NULL)
+                                       newval = &tmpnewval;
+
+                               if (value != NULL)
+                               {
+                                       if (!parse_real(value, newval))
+                                       {
+                                               ereport(elevel,
+                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                 errmsg("parameter \"%s\" requires a numeric value",
+                                                                name)));
+                                               return 0;
+                                       }
+
+                                       if (*((double *) newval) < conf->min || *((double *) newval) > conf->max)
+                                       {
+                                               ereport(elevel,
+                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                                errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
+                                                *((double *) newval), name, conf->min, conf->max)));
+                                               return 0;
+                                       }
+
+                                       if (!call_real_check_hook(conf, newval, newextra,
+                                                                                         source, elevel))
+                                               return 0;
+
+                                       if (*newextra && freemem)
+                                               free(*newextra);
+                               }
+                       }
+                       break;
+               case PGC_STRING:
+                       {
+                               struct config_string *conf = (struct config_string *) record;
+                               char       *tempPtr;
+                               char      **tmpnewval = newval;
+
+                               if (newval == NULL)
+                                       tmpnewval = &tempPtr;
+
+                               if (value != NULL)
+                               {
+                                       /*
+                                        * The value passed by the caller could be transient, so
+                                        * we always strdup it.
+                                        */
+                                       *tmpnewval = guc_strdup(elevel, value);
+                                       if (*tmpnewval == NULL)
+                                               return 0;
+
+                                       /*
+                                        * The only built-in "parsing" check we have is to apply
+                                        * truncation if GUC_IS_NAME.
+                                        */
+                                       if (conf->gen.flags & GUC_IS_NAME)
+                                               truncate_identifier(*tmpnewval, strlen(*tmpnewval), true);
+
+                                       if (!call_string_check_hook(conf, tmpnewval, newextra,
+                                                                                               source, elevel))
+                                       {
+                                               free(*tmpnewval);
+                                               return 0;
+                                       }
+
+                                       /* Free the malloc'd data if any */
+                                       if (freemem)
+                                       {
+                                               if (*tmpnewval != NULL)
+                                                       free(*tmpnewval);
+                                               if (*newextra != NULL)
+                                                       free(*newextra);
+                                       }
+                               }
+                       }
+                       break;
+               case PGC_ENUM:
+                       {
+                               struct config_enum *conf = (struct config_enum *) record;
+                               int                     tmpnewval;
+
+                               if (newval == NULL)
+                                       newval = &tmpnewval;
+
+                               if (value != NULL)
+                               {
+                                       if (!config_enum_lookup_by_name(conf, value, newval))
+                                       {
+                                               char       *hintmsg;
+
+                                               hintmsg = config_enum_get_options(conf,
+                                                                                                               "Available values: ",
+                                                                                                                 ".", ", ");
+
+                                               ereport(ERROR,
+                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                errmsg("invalid value for parameter \"%s\": \"%s\"",
+                                                               name, value),
+                                                                hintmsg ? errhint("%s", _(hintmsg)) : 0));
+
+                                               if (hintmsg != NULL)
+                                                       pfree(hintmsg);
+                                               return 0;
+                                       }
+                                       if (!call_enum_check_hook(conf, newval, newextra,
+                                                                                         source, LOG))
+                                               return 0;
+
+                                       if (*newextra && freemem)
+                                               free(*newextra);
+                               }
+                       }
+                       break;
+       }
+       return 1;
+}
+
+
+/*
+ * Sets option `name' to given value.
+ *
+ * The value should be a string, which will be parsed and converted to
+ * the appropriate data type.  The context and source parameters indicate
+ * in which context this function is being called, so that it can apply the
+ * access restrictions properly.
+ *
+ * If value is NULL, set the option to its default value (normally the
+ * reset_val, but if source == PGC_S_DEFAULT we instead use the boot_val).
+ *
+ * action indicates whether to set the value globally in the session, locally
+ * to the current top transaction, or just for the duration of a function call.
+ *
+ * If changeVal is false then don't really set the option but do all
+ * the checks to see if it would work.
+ *
+ * elevel should normally be passed as zero, allowing this function to make
+ * its standard choice of ereport level.  However some callers need to be
+ * able to override that choice; they should pass the ereport level to use.
+ *
+ * Return value:
+ *     +1: the value is valid and was successfully applied.
+ *     0:      the name or value is invalid (but see below).
+ *     -1: the value was not applied because of context, priority, or changeVal.
+ *
+ * If there is an error (non-existing option, invalid value) then an
+ * ereport(ERROR) is thrown *unless* this is called for a source for which
+ * we don't want an ERROR (currently, those are defaults, the config file,
+ * and per-database or per-user settings, as well as callers who specify
+ * a less-than-ERROR elevel).  In those cases we write a suitable error
+ * message via ereport() and return 0.
+ *
+ * See also SetConfigOption for an external interface.
+ */
+int
+set_config_option(const char *name, const char *value,
+                                 GucContext context, GucSource source,
+                                 GucAction action, bool changeVal, int elevel)
+{
+       struct config_generic *record;
+       bool            prohibitValueChange = false;
        bool            makeDefault;
 
        if (elevel == 0)
@@ -5086,7 +5609,7 @@ set_config_option(const char *name, const char *value,
                         */
                        elevel = IsUnderPostmaster ? DEBUG3 : LOG;
                }
-               else if (source == PGC_S_DATABASE || source == PGC_S_USER ||
+               else if (source == PGC_S_GLOBAL || source == PGC_S_DATABASE || source == PGC_S_USER ||
                                 source == PGC_S_DATABASE_USER)
                        elevel = WARNING;
                else
@@ -5165,12 +5688,26 @@ set_config_option(const char *name, const char *value,
                                 * If a PGC_BACKEND parameter is changed in the config file,
                                 * we want to accept the new value in the postmaster (whence
                                 * it will propagate to subsequently-started backends), but
-                                * ignore it in existing backends.      This is a tad klugy, but
+                                * ignore it in existing backends.  This is a tad klugy, but
                                 * necessary because we don't re-read the config file during
                                 * backend start.
+                                *
+                                * In EXEC_BACKEND builds, this works differently: we load all
+                                * nondefault settings from the CONFIG_EXEC_PARAMS file during
+                                * backend start.  In that case we must accept PGC_SIGHUP
+                                * settings, so as to have the same value as if we'd forked
+                                * from the postmaster.  We detect this situation by checking
+                                * IsInitProcessingMode, which is a bit ugly, but it doesn't
+                                * seem worth passing down an explicit flag saying we're doing
+                                * read_nondefault_variables().
                                 */
+#ifdef EXEC_BACKEND
+                               if (IsUnderPostmaster && !IsInitProcessingMode())
+                                       return -1;
+#else
                                if (IsUnderPostmaster)
                                        return -1;
+#endif
                        }
                        else if (context != PGC_POSTMASTER && context != PGC_BACKEND &&
                                         source != PGC_S_CLIENT)
@@ -5208,7 +5745,7 @@ set_config_option(const char *name, const char *value,
         * An exception might be made if the reset value is assumed to be "safe".
         *
         * Note: this flag is currently used for "session_authorization" and
-        * "role".      We need to prohibit changing these inside a local userid
+        * "role".  We need to prohibit changing these inside a local userid
         * context because when we exit it, GUC won't be notified, leaving things
         * out of sync.  (This could be fixed by forcing a new GUC nesting level,
         * but that would change behavior in possibly-undesirable ways.)  Also, we
@@ -5279,16 +5816,9 @@ set_config_option(const char *name, const char *value,
 
                                if (value)
                                {
-                                       if (!parse_bool(value, &newval))
-                                       {
-                                               ereport(elevel,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                 errmsg("parameter \"%s\" requires a Boolean value",
-                                                                name)));
-                                               return 0;
-                                       }
-                                       if (!call_bool_check_hook(conf, &newval, &newextra,
-                                                                                         source, elevel))
+                                       if (!validate_conf_option(record, name, value, source,
+                                                                                         elevel, false, &newval,
+                                                                                         &newextra))
                                                return 0;
                                }
                                else if (source == PGC_S_DEFAULT)
@@ -5372,27 +5902,9 @@ set_config_option(const char *name, const char *value,
 
                                if (value)
                                {
-                                       const char *hintmsg;
-
-                                       if (!parse_int(value, &newval, conf->gen.flags, &hintmsg))
-                                       {
-                                               ereport(elevel,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                errmsg("invalid value for parameter \"%s\": \"%s\"",
-                                                               name, value),
-                                                                hintmsg ? errhint("%s", _(hintmsg)) : 0));
-                                               return 0;
-                                       }
-                                       if (newval < conf->min || newval > conf->max)
-                                       {
-                                               ereport(elevel,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
-                                                                               newval, name, conf->min, conf->max)));
-                                               return 0;
-                                       }
-                                       if (!call_int_check_hook(conf, &newval, &newextra,
-                                                                                        source, elevel))
+                                       if (!validate_conf_option(record, name, value, source,
+                                                                                         elevel, false, &newval,
+                                                                                         &newextra))
                                                return 0;
                                }
                                else if (source == PGC_S_DEFAULT)
@@ -5476,24 +5988,9 @@ set_config_option(const char *name, const char *value,
 
                                if (value)
                                {
-                                       if (!parse_real(value, &newval))
-                                       {
-                                               ereport(elevel,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                 errmsg("parameter \"%s\" requires a numeric value",
-                                                                name)));
-                                               return 0;
-                                       }
-                                       if (newval < conf->min || newval > conf->max)
-                                       {
-                                               ereport(elevel,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
-                                                                               newval, name, conf->min, conf->max)));
-                                               return 0;
-                                       }
-                                       if (!call_real_check_hook(conf, &newval, &newextra,
-                                                                                         source, elevel))
+                                       if (!validate_conf_option(record, name, value, source,
+                                                                                         elevel, false, &newval,
+                                                                                         &newextra))
                                                return 0;
                                }
                                else if (source == PGC_S_DEFAULT)
@@ -5577,27 +6074,10 @@ set_config_option(const char *name, const char *value,
 
                                if (value)
                                {
-                                       /*
-                                        * The value passed by the caller could be transient, so
-                                        * we always strdup it.
-                                        */
-                                       newval = guc_strdup(elevel, value);
-                                       if (newval == NULL)
-                                               return 0;
-
-                                       /*
-                                        * The only built-in "parsing" check we have is to apply
-                                        * truncation if GUC_IS_NAME.
-                                        */
-                                       if (conf->gen.flags & GUC_IS_NAME)
-                                               truncate_identifier(newval, strlen(newval), true);
-
-                                       if (!call_string_check_hook(conf, &newval, &newextra,
-                                                                                               source, elevel))
-                                       {
-                                               free(newval);
+                                       if (!validate_conf_option(record, name, value, source,
+                                                                                         elevel, false, &newval,
+                                                                                         &newextra))
                                                return 0;
-                                       }
                                }
                                else if (source == PGC_S_DEFAULT)
                                {
@@ -5703,26 +6183,9 @@ set_config_option(const char *name, const char *value,
 
                                if (value)
                                {
-                                       if (!config_enum_lookup_by_name(conf, value, &newval))
-                                       {
-                                               char       *hintmsg;
-
-                                               hintmsg = config_enum_get_options(conf,
-                                                                                                               "Available values: ",
-                                                                                                                 ".", ", ");
-
-                                               ereport(elevel,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                errmsg("invalid value for parameter \"%s\": \"%s\"",
-                                                               name, value),
-                                                                hintmsg ? errhint("%s", _(hintmsg)) : 0));
-
-                                               if (hintmsg)
-                                                       pfree(hintmsg);
-                                               return 0;
-                                       }
-                                       if (!call_enum_check_hook(conf, &newval, &newextra,
-                                                                                         source, elevel))
+                                       if (!validate_conf_option(record, name, value, source,
+                                                                                         elevel, false, &newval,
+                                                                                         &newextra))
                                                return 0;
                                }
                                else if (source == PGC_S_DEFAULT)
@@ -6019,7 +6482,7 @@ flatten_set_variable_args(const char *name, List *args)
                A_Const    *con;
 
                if (l != list_head(args))
-                       appendStringInfo(&buf, ", ");
+                       appendStringInfoString(&buf, ", ");
 
                if (IsA(arg, TypeCast))
                {
@@ -6073,7 +6536,7 @@ flatten_set_variable_args(const char *name, List *args)
                                else
                                {
                                        /*
-                                        * Plain string literal or identifier.  For quote mode,
+                                        * Plain string literal or identifier.  For quote mode,
                                         * quote it if it's not a vanilla identifier.
                                         */
                                        if (flags & GUC_LIST_QUOTE)
@@ -6092,12 +6555,305 @@ flatten_set_variable_args(const char *name, List *args)
        return buf.data;
 }
 
+/*
+ * Write updated configuration parameter values into a temporary file.
+ * This function traverses the list of parameters and quotes the string
+ * values before writing them.
+ */
+static void
+write_auto_conf_file(int fd, const char *filename, ConfigVariable **head_p)
+{
+       ConfigVariable *item;
+       StringInfoData buf;
+
+       initStringInfo(&buf);
+       appendStringInfoString(&buf, "# Do not edit this file manually!\n");
+       appendStringInfoString(&buf, "# It will be overwritten by ALTER SYSTEM command.\n");
+
+       /*
+        * write the file header message before contents, so that if there is no
+        * item it can contain message
+        */
+       if (write(fd, buf.data, buf.len) < 0)
+               ereport(ERROR,
+                               (errmsg("failed to write to \"%s\" file", filename)));
+       resetStringInfo(&buf);
+
+       /*
+        * traverse the list of parameters, quote the string parameter and write
+        * it to file. Once all parameters are written fsync the file.
+        */
+
+       for (item = *head_p; item != NULL; item = item->next)
+       {
+               char       *escaped;
+
+               appendStringInfoString(&buf, item->name);
+               appendStringInfoString(&buf, " = ");
+
+               appendStringInfoString(&buf, "\'");
+               escaped = escape_single_quotes_ascii(item->value);
+               appendStringInfoString(&buf, escaped);
+               free(escaped);
+               appendStringInfoString(&buf, "\'");
+
+               appendStringInfoString(&buf, "\n");
+
+               if (write(fd, buf.data, buf.len) < 0)
+                       ereport(ERROR,
+                                       (errmsg("failed to write to \"%s\" file", filename)));
+               resetStringInfo(&buf);
+       }
+
+       if (pg_fsync(fd) != 0)
+               ereport(ERROR,
+                               (errcode_for_file_access(),
+                                errmsg("could not fsync file \"%s\": %m", filename)));
+
+       pfree(buf.data);
+}
+
+
+/*
+ * This function takes list of all configuration parameters in
+ * PG_AUTOCONF_FILENAME and parameter to be updated as input arguments and
+ * replace the updated configuration parameter value in a list. If the
+ * parameter to be updated is new then it is appended to the list of
+ * parameters.
+ */
+static void
+replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
+                                                 char *config_file,
+                                                 char *name, char *value)
+{
+       ConfigVariable *item,
+                          *prev = NULL;
+
+       if (*head_p != NULL)
+       {
+               for (item = *head_p; item != NULL; item = item->next)
+               {
+                       if (strcmp(item->name, name) == 0)
+                       {
+                               pfree(item->value);
+                               if (value != NULL)
+                                       /* update the parameter value */
+                                       item->value = pstrdup(value);
+                               else
+                               {
+                                       /* delete the configuration parameter from list */
+                                       if (*head_p == item)
+                                               *head_p = item->next;
+                                       else
+                                               prev->next = item->next;
+
+                                       if (*tail_p == item)
+                                               *tail_p = prev;
+
+                                       pfree(item->name);
+                                       pfree(item->filename);
+                                       pfree(item);
+                               }
+                               return;
+                       }
+                       prev = item;
+               }
+       }
+
+       if (value == NULL)
+               return;
+
+       item = palloc(sizeof *item);
+       item->name = pstrdup(name);
+       item->value = pstrdup(value);
+       item->filename = pstrdup(config_file);
+       item->next = NULL;
+
+       if (*head_p == NULL)
+       {
+               item->sourceline = 1;
+               *head_p = item;
+       }
+       else
+       {
+               item->sourceline = (*tail_p)->sourceline + 1;
+               (*tail_p)->next = item;
+       }
+
+       *tail_p = item;
+
+       return;
+}
+
+
+/*
+ * Persist the configuration parameter value.
+ *
+ * This function takes all previous configuration parameters
+ * set by ALTER SYSTEM command and the currently set ones
+ * and write them all to the automatic configuration file.
+ *
+ * The configuration parameters are written to a temporary
+ * file then renamed to the final name.
+ *
+ * An LWLock is used to serialize writing to the same file.
+ *
+ * In case of an error, we leave the original automatic
+ * configuration file (PG_AUTOCONF_FILENAME) intact.
+ */
+void
+AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
+{
+       char       *name;
+       char       *value;
+       int                     Tmpfd = -1;
+       FILE       *infile;
+       struct config_generic *record;
+       ConfigVariable *head = NULL;
+       ConfigVariable *tail = NULL;
+       char            AutoConfFileName[MAXPGPATH];
+       char            AutoConfTmpFileName[MAXPGPATH];
+       struct stat st;
+       void       *newextra = NULL;
+
+       if (!superuser())
+               ereport(ERROR,
+                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                        (errmsg("must be superuser to execute ALTER SYSTEM command"))));
+
+       /*
+        * Validate the name and arguments [value1, value2 ... ].
+        */
+       name = altersysstmt->setstmt->name;
+
+       switch (altersysstmt->setstmt->kind)
+       {
+               case VAR_SET_VALUE:
+                       value = ExtractSetVariableArgs(altersysstmt->setstmt);
+                       break;
+
+               case VAR_SET_DEFAULT:
+                       value = NULL;
+                       break;
+               default:
+                       elog(ERROR, "unrecognized alter system stmt type: %d",
+                                altersysstmt->setstmt->kind);
+                       break;
+       }
+
+       record = find_option(name, false, LOG);
+       if (record == NULL)
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                          errmsg("unrecognized configuration parameter \"%s\"", name)));
+
+       /*
+        * Don't allow the parameters which can't be set in configuration
+        * files to be set in PG_AUTOCONF_FILENAME file.
+        */
+       if ((record->context == PGC_INTERNAL) ||
+               (record->flags & GUC_DISALLOW_IN_FILE) ||
+               (record->flags & GUC_DISALLOW_IN_AUTO_FILE))
+                ereport(ERROR,
+                                (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+                                 errmsg("parameter \"%s\" cannot be changed",
+                                                name)));
+
+       if (!validate_conf_option(record, name, value, PGC_S_FILE,
+                                                         ERROR, true, NULL,
+                                                         &newextra))
+               ereport(ERROR,
+               (errmsg("invalid value for parameter \"%s\": \"%s\"", name, value)));
+
+
+       /*
+        * Use data directory as reference path for PG_AUTOCONF_FILENAME and its
+        * corresponding temporary file.
+        */
+       join_path_components(AutoConfFileName, data_directory, PG_AUTOCONF_FILENAME);
+       canonicalize_path(AutoConfFileName);
+       snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s.%s",
+                        AutoConfFileName,
+                        "tmp");
+
+       /*
+        * One backend is allowed to operate on file PG_AUTOCONF_FILENAME, to
+        * ensure that we need to update the contents of the file with
+        * AutoFileLock. To ensure crash safety, first the contents are written to
+        * a temporary file which is then renameed to PG_AUTOCONF_FILENAME. In
+        * case there exists a temp file from previous crash, that can be reused.
+        */
+
+       LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
+
+       Tmpfd = open(AutoConfTmpFileName, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
+       if (Tmpfd < 0)
+               ereport(ERROR,
+                               (errcode_for_file_access(),
+                                errmsg("failed to open auto conf temp file \"%s\": %m ",
+                                               AutoConfTmpFileName)));
+
+       PG_TRY();
+       {
+               if (stat(AutoConfFileName, &st) == 0)
+               {
+                       /* open file PG_AUTOCONF_FILENAME */
+                       infile = AllocateFile(AutoConfFileName, "r");
+                       if (infile == NULL)
+                               ereport(ERROR,
+                                               (errmsg("failed to open auto conf file \"%s\": %m ",
+                                                               AutoConfFileName)));
+
+                       /* parse it */
+                       ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail);
+
+                       FreeFile(infile);
+               }
+
+               /*
+                * replace with new value if the configuration parameter already
+                * exists OR add it as a new cofiguration parameter in the file.
+                */
+               replace_auto_config_value(&head, &tail, AutoConfFileName, name, value);
+
+               /* Write and sync the new contents to the temporary file */
+               write_auto_conf_file(Tmpfd, AutoConfTmpFileName, &head);
+
+               close(Tmpfd);
+               Tmpfd = -1;
+
+               /*
+                * As the rename is atomic operation, if any problem occurs after this
+                * at max it can loose the parameters set by last ALTER SYSTEM
+                * command.
+                */
+               if (rename(AutoConfTmpFileName, AutoConfFileName) < 0)
+                       ereport(ERROR,
+                                       (errcode_for_file_access(),
+                                        errmsg("could not rename file \"%s\" to \"%s\" : %m",
+                                                       AutoConfTmpFileName, AutoConfFileName)));
+       }
+       PG_CATCH();
+       {
+               if (Tmpfd >= 0)
+                       close(Tmpfd);
+
+               unlink(AutoConfTmpFileName);
+               FreeConfigVariables(head);
+               PG_RE_THROW();
+       }
+       PG_END_TRY();
+
+       FreeConfigVariables(head);
+       LWLockRelease(AutoFileLock);
+       return;
+}
 
 /*
  * SET command
  */
 void
-ExecSetVariableStmt(VariableSetStmt *stmt)
+ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
 {
        GucAction       action = stmt->is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET;
 
@@ -6105,6 +6861,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
        {
                case VAR_SET_VALUE:
                case VAR_SET_CURRENT:
+                       if (stmt->is_local)
+                               WarnNoTransactionChain(isTopLevel, "SET LOCAL");
                        (void) set_config_option(stmt->name,
                                                                         ExtractSetVariableArgs(stmt),
                                                                         (superuser() ? PGC_SUSET : PGC_USERSET),
@@ -6126,6 +6884,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                        {
                                ListCell   *head;
 
+                               WarnNoTransactionChain(isTopLevel, "SET TRANSACTION");
+
                                foreach(head, stmt->args)
                                {
                                        DefElem    *item = (DefElem *) lfirst(head);
@@ -6174,6 +6934,8 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                                         errmsg("SET LOCAL TRANSACTION SNAPSHOT is not implemented")));
+
+                               WarnNoTransactionChain(isTopLevel, "SET TRANSACTION");
                                Assert(IsA(con, A_Const));
                                Assert(nodeTag(&con->val) == T_String);
                                ImportSnapshot(strVal(&con->val));
@@ -6183,7 +6945,13 @@ ExecSetVariableStmt(VariableSetStmt *stmt)
                                         stmt->name);
                        break;
                case VAR_SET_DEFAULT:
+                       if (stmt->is_local)
+                               WarnNoTransactionChain(isTopLevel, "SET LOCAL");
+                       /* fall through */
                case VAR_RESET:
+                       if (strcmp(stmt->name, "transaction_isolation") == 0)
+                               WarnNoTransactionChain(isTopLevel, "RESET TRANSACTION");
+
                        (void) set_config_option(stmt->name,
                                                                         NULL,
                                                                         (superuser() ? PGC_SUSET : PGC_USERSET),
@@ -6436,7 +7204,7 @@ define_custom_variable(struct config_generic * variable)
  */
 static void
 reapply_stacked_values(struct config_generic * variable,
-                                          struct config_string *pHolder,
+                                          struct config_string * pHolder,
                                           GucStack *stack,
                                           const char *curvalue,
                                           GucContext curscontext, GucSource cursource)
@@ -6475,7 +7243,7 @@ reapply_stacked_values(struct config_generic * variable,
                        case GUC_SET_LOCAL:
                                /* first, apply the masked value as SET */
                                (void) set_config_option(name, stack->masked.val.stringval,
-                                                                                stack->masked_scontext, PGC_S_SESSION,
+                                                                          stack->masked_scontext, PGC_S_SESSION,
                                                                                 GUC_ACTION_SET, true, WARNING);
                                /* then apply the current value as LOCAL */
                                (void) set_config_option(name, curvalue,
@@ -7293,7 +8061,12 @@ _ShowOption(struct config_generic * record, bool use_units)
                                                                break;
                                                }
 
-                                               if (result % KB_PER_GB == 0)
+                                               if (result % KB_PER_TB == 0)
+                                               {
+                                                       result /= KB_PER_TB;
+                                                       unit = "TB";
+                                               }
+                                               else if (result % KB_PER_GB == 0)
                                                {
                                                        result /= KB_PER_GB;
                                                        unit = "GB";
@@ -7579,6 +8352,12 @@ read_nondefault_variables(void)
        GucSource       varsource;
        GucContext      varscontext;
 
+       /*
+        * Assert that PGC_BACKEND case in set_config_option() will do the right
+        * thing.
+        */
+       Assert(IsInitProcessingMode());
+
        /*
         * Open file
         */
@@ -7672,7 +8451,7 @@ ParseLongOption(const char *string, char **name, char **value)
 
 /*
  * Handle options fetched from pg_db_role_setting.setconfig,
- * pg_proc.proconfig, etc.     Caller must specify proper context/source/action.
+ * pg_proc.proconfig, etc.  Caller must specify proper context/source/action.
  *
  * The array parameter must be an array of TEXT (it must not be NULL).
  */
@@ -7754,8 +8533,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
                name = record->name;
 
        /* build new item for array */
-       newval = palloc(strlen(name) + 1 + strlen(value) + 1);
-       sprintf(newval, "%s=%s", name, value);
+       newval = psprintf("%s=%s", name, value);
        datum = CStringGetTextDatum(newval);
 
        if (array)
@@ -7954,7 +8732,7 @@ GUCArrayReset(ArrayType *array)
  * Validate a proposed option setting for GUCArrayAdd/Delete/Reset.
  *
  * name is the option name.  value is the proposed value for the Add case,
- * or NULL for the Delete/Reset cases. If skipIfNoPermissions is true, it's
+ * or NULL for the Delete/Reset cases.  If skipIfNoPermissions is true, it's
  * not an error to have no permissions to set the option.
  *
  * Returns TRUE if OK, FALSE if skipIfNoPermissions is true and user does not
@@ -7977,8 +8755,8 @@ validate_option_array_item(const char *name, const char *value,
         *
         * name is not known, but exists or can be created as a placeholder (i.e.,
         * it has a prefixed name).  We allow this case if you're a superuser,
-        * otherwise not.  Superusers are assumed to know what they're doing.
-        * We can't allow it for other users, because when the placeholder is
+        * otherwise not.  Superusers are assumed to know what they're doing. We
+        * can't allow it for other users, because when the placeholder is
         * resolved it might turn out to be a SUSET variable;
         * define_custom_variable assumes we checked that.
         *
@@ -8035,7 +8813,7 @@ validate_option_array_item(const char *name, const char *value,
  * ERRCODE_INVALID_PARAMETER_VALUE SQLSTATE for check hook failures.
  *
  * Note that GUC_check_errmsg() etc are just macros that result in a direct
- * assignment to the associated variables.     That is ugly, but forced by the
+ * assignment to the associated variables.  That is ugly, but forced by the
  * limitations of C's macro mechanisms.
  */
 void
@@ -8347,19 +9125,6 @@ check_phony_autocommit(bool *newval, void **extra, GucSource source)
        return true;
 }
 
-static bool
-check_debug_assertions(bool *newval, void **extra, GucSource source)
-{
-#ifndef USE_ASSERT_CHECKING
-       if (*newval)
-       {
-               GUC_check_errmsg("assertion checking is not supported by this build");
-               return false;
-       }
-#endif
-       return true;
-}
-
 static bool
 check_bonjour(bool *newval, void **extra, GucSource source)
 {
@@ -8554,29 +9319,49 @@ show_tcp_keepalives_count(void)
 static bool
 check_maxconnections(int *newval, void **extra, GucSource source)
 {
-       if (*newval + autovacuum_max_workers + 1 > MAX_BACKENDS)
+       if (*newval + autovacuum_max_workers + 1 +
+               max_worker_processes > MAX_BACKENDS)
                return false;
        return true;
 }
 
-static void
-assign_maxconnections(int newval, void *extra)
+static bool
+check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
 {
-       MaxBackends = newval + autovacuum_max_workers + 1;
+       if (MaxConnections + *newval + 1 + max_worker_processes > MAX_BACKENDS)
+               return false;
+       return true;
 }
 
 static bool
-check_autovacuum_max_workers(int *newval, void **extra, GucSource source)
+check_autovacuum_work_mem(int *newval, void **extra, GucSource source)
 {
-       if (MaxConnections + *newval + 1 > MAX_BACKENDS)
-               return false;
+       /*
+        * -1 indicates fallback.
+        *
+        * If we haven't yet changed the boot_val default of -1, just let it be.
+        * Autovacuum will look to maintenance_work_mem instead.
+        */
+       if (*newval == -1)
+               return true;
+
+       /*
+        * We clamp manually-set values to at least 1MB.  Since
+        * maintenance_work_mem is always set to at least this value, do the same
+        * here.
+        */
+       if (*newval < 1024)
+               *newval = 1024;
+
        return true;
 }
 
-static void
-assign_autovacuum_max_workers(int newval, void *extra)
+static bool
+check_max_worker_processes(int *newval, void **extra, GucSource source)
 {
-       MaxBackends = MaxConnections + newval + 1;
+       if (MaxConnections + autovacuum_max_workers + 1 + *newval > MAX_BACKENDS)
+               return false;
+       return true;
 }
 
 static bool
@@ -8651,14 +9436,23 @@ static void
 assign_pgstat_temp_directory(const char *newval, void *extra)
 {
        /* check_canonical_path already canonicalized newval for us */
+       char       *dname;
        char       *tname;
        char       *fname;
 
-       tname = guc_malloc(ERROR, strlen(newval) + 12);         /* /pgstat.tmp */
-       sprintf(tname, "%s/pgstat.tmp", newval);
-       fname = guc_malloc(ERROR, strlen(newval) + 13);         /* /pgstat.stat */
-       sprintf(fname, "%s/pgstat.stat", newval);
+       /* directory */
+       dname = guc_malloc(ERROR, strlen(newval) + 1);          /* runtime dir */
+       sprintf(dname, "%s", newval);
+
+       /* global stats */
+       tname = guc_malloc(ERROR, strlen(newval) + 12);         /* /global.tmp */
+       sprintf(tname, "%s/global.tmp", newval);
+       fname = guc_malloc(ERROR, strlen(newval) + 13);         /* /global.stat */
+       sprintf(fname, "%s/global.stat", newval);
 
+       if (pgstat_stat_directory)
+               free(pgstat_stat_directory);
+       pgstat_stat_directory = dname;
        if (pgstat_stat_tmpname)
                free(pgstat_stat_tmpname);
        pgstat_stat_tmpname = tname;
@@ -8689,6 +9483,21 @@ assign_application_name(const char *newval, void *extra)
        pgstat_report_appname(newval);
 }
 
+static bool
+check_cluster_name(char **newval, void **extra, GucSource source)
+{
+       /* Only allow clean ASCII chars in the cluster name */
+       char       *p;
+
+       for (p = *newval; *p; p++)
+       {
+               if (*p < 32 || *p > 126)
+                       *p = '?';
+       }
+
+       return true;
+}
+
 static const char *
 show_unix_socket_permissions(void)
 {