]> 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 b0c14a2dfce41b1631e15ce3b26c6b5feaeb49e9..6c52db859032af33eccb1eb53a890506f4e7b181 100644 (file)
@@ -6,7 +6,7 @@
  * See src/backend/utils/misc/README for more information.
  *
  *
- * Copyright (c) 2000-2013, PostgreSQL Global Development Group
+ * Copyright (c) 2000-2014, PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
@@ -57,6 +57,7 @@
 #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"
@@ -64,6 +65,7 @@
 #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"
@@ -83,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"
@@ -175,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);
@@ -200,6 +198,7 @@ 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);
 
@@ -207,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.
@@ -383,6 +386,23 @@ 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
  */
@@ -393,11 +413,6 @@ 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;
@@ -429,6 +444,7 @@ int                 temp_file_limit = -1;
 
 int                    num_temp_buffers = 1024;
 
+char      *cluster_name = "";
 char      *data_directory;
 char      *ConfigFileName;
 char      *HbaFileName;
@@ -443,6 +459,12 @@ 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
@@ -470,10 +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 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;
@@ -868,11 +891,11 @@ static struct config_bool ConfigureNamesBool[] =
        },
 
        {
-               {"wal_log_hintbits", PGC_POSTMASTER, WAL_SETTINGS,
+               {"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
                },
-               &walLogHintbits,
+               &wal_log_hints,
                false,
                NULL, NULL, NULL
        },
@@ -905,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
@@ -916,7 +939,7 @@ static struct config_bool ConfigureNamesBool[] =
 #else
                false,
 #endif
-               check_debug_assertions, NULL, NULL
+               NULL, NULL, NULL
        },
 
        {
@@ -1484,7 +1507,7 @@ static struct config_bool ConfigureNamesBool[] =
 
        {
                {"data_checksums", PGC_INTERNAL, PRESET_OPTIONS,
-                       gettext_noop("Shows whether data checksums are turned on for this cluster"),
+                       gettext_noop("Shows whether data checksums are turned on for this cluster."),
                        NULL,
                        GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
                },
@@ -1744,7 +1767,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_KB
                },
                &work_mem,
-               1024, 64, MAX_KILOBYTES,
+               4096, 64, MAX_KILOBYTES,
                NULL, NULL, NULL
        },
 
@@ -1755,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
        },
 
@@ -1946,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."),
@@ -2074,12 +2117,12 @@ static struct config_int ConfigureNamesInt[] =
        },
 
        {
-               {"xloginsert_slots", PGC_POSTMASTER, WAL_SETTINGS,
-                       gettext_noop("Sets the number of slots for concurrent xlog insertions."),
+               {"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_slots,
+               &num_xloginsert_locks,
                8, 1, 1000,
                NULL, NULL, NULL
        },
@@ -2095,6 +2138,17 @@ static struct config_int ConfigureNamesInt[] =
                NULL, NULL, NULL
        },
 
+       {
+               /* 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."),
@@ -2358,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,
@@ -2445,8 +2509,8 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_BLOCKS,
                },
                &effective_cache_size,
-               -1, -1, INT_MAX,
-               check_effective_cache_size, NULL, NULL
+               DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX,
+               NULL, NULL, NULL
        },
 
        {
@@ -2476,6 +2540,11 @@ static struct config_int ConfigureNamesInt[] =
                {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
                        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,
@@ -2732,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."),
@@ -2960,7 +3019,7 @@ static struct config_string ConfigureNamesString[] =
                        NULL
                },
                &event_source,
-               "PostgreSQL",
+               DEFAULT_EVENT_SOURCE,
                NULL, NULL, NULL
        },
 
@@ -3033,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,
@@ -3134,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
        },
 
@@ -3167,7 +3230,7 @@ static struct config_string ConfigureNamesString[] =
                },
                &SSLCipherSuites,
 #ifdef USE_SSL
-               "DEFAULT:!LOW:!EXP:!MD5:@STRENGTH",
+               "HIGH:MEDIUM:+3DES:!aNULL",
 #else
                "none",
 #endif
@@ -3200,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
@@ -3426,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 */
        {
@@ -3484,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);
 
 
 /*
@@ -3708,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).
  */
@@ -3865,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);
@@ -3907,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.
         */
@@ -4289,6 +4375,14 @@ 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 a
@@ -4298,8 +4392,6 @@ SelectConfigFiles(const char *userDoption, const char *progname)
         */
        pg_timezone_abbrev_initialize();
 
-       set_default_effective_cache_size();
-
        /*
         * Figure out where pg_hba.conf is, and make sure the path is absolute.
         */
@@ -4565,7 +4657,7 @@ NewGUCNestLevel(void)
 /*
  * Do GUC processing at transaction or subtransaction commit or abort, or
  * when exiting a function that has proconfig settings, or when undoing a
- * transient assignment to some GUC variables. (The name is thus a bit of
+ * transient assignment to some GUC variables.  (The name is thus a bit of
  * a misnomer; perhaps it should be ExitGUCNestLevel or some such.)
  * During abort, we discard all GUC settings that were applied at nesting
  * levels >= nestLevel.  nestLevel == 1 corresponds to the main transaction.
@@ -5248,6 +5340,220 @@ config_enum_get_options(struct config_enum * record, const char *prefix,
        return retstr.data;
 }
 
+/*
+ * 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
+ *     0: the name or value is invalid
+ */
+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)
+{
+       /*
+        * 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.
@@ -5382,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)
@@ -5425,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
@@ -5496,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)
@@ -5589,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)
@@ -5693,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)
@@ -5794,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)
                                {
@@ -5920,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)
@@ -6290,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)
@@ -6309,6 +6555,299 @@ 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
@@ -6333,6 +6872,7 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
                                                                         0);
                        break;
                case VAR_SET_MULTI:
+
                        /*
                         * Special-case SQL syntaxes.  The TRANSACTION and SESSION
                         * CHARACTERISTICS cases effectively set more than one variable
@@ -6618,7 +7158,7 @@ define_custom_variable(struct config_generic * variable)
         * variable.  Essentially, we need to duplicate all the active and stacked
         * values, but with appropriate validation and datatype adjustment.
         *
-        * If an assignment fails, we report a WARNING and keep going.  We don't
+        * If an assignment fails, we report a WARNING and keep going.  We don't
         * want to throw ERROR for bad values, because it'd bollix the add-on
         * module that's presumably halfway through getting loaded.  In such cases
         * the default or previous state will become active instead.
@@ -6646,7 +7186,7 @@ define_custom_variable(struct config_generic * variable)
        /*
         * Free up as much as we conveniently can of the placeholder structure.
         * (This neglects any stack items, so it's possible for some memory to be
-        * leaked.      Since this can only happen once per session per variable, it
+        * leaked.  Since this can only happen once per session per variable, it
         * doesn't seem worth spending much code on.)
         */
        set_string_field(pHolder, pHolder->variable, NULL);
@@ -6719,7 +7259,7 @@ reapply_stacked_values(struct config_generic * variable,
        else
        {
                /*
-                * We are at the end of the stack.      If the active/previous value is
+                * We are at the end of the stack.  If the active/previous value is
                 * different from the reset value, it must represent a previously
                 * committed session value.  Apply it, and then drop the stack entry
                 * that set_config_option will have created under the impression that
@@ -7812,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
         */
@@ -7905,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).
  */
@@ -8186,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
@@ -8267,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
@@ -8579,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)
 {
@@ -8950,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)
 {