diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index cf5d3f3b8555490b7ed454205e4de9cce592a5fd..dfb6348e1d633b26e7c4706f96b6030730c39df0 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.127 2006/07/25 03:51:21 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.128 2006/07/27 08:30:41 petere Exp $ --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -5482,6 +5482,12 @@ <entry></entry> <entry>current value of the parameter</entry> </row> + <row> + <entry><structfield>unit</structfield></entry> + <entry><type>text</type></entry> + <entry></entry> + <entry>implicit unit of the parameter</entry> + </row> <row> <entry><structfield>category</structfield></entry> <entry><type>text</type></entry> diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 45350ac7ae9c099bb340a0e9bd852cc7c53257d8..0acdd27507865fd6c33dca47c5698facb9553357 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.70 2006/07/26 11:35:55 petere Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.71 2006/07/27 08:30:41 petere Exp $ --> <chapter Id="runtime-config"> <title>Server Configuration</title> @@ -28,6 +28,20 @@ (all case-insensitive) or any unambiguous prefix of these. </para> + <para> + Some settings specify a memory or time value. Each of these has + an implicit unit, which is either kilobytes, blocks (typically 8 + kilobytes), milliseconds, seconds, or minutes. For convenience, a + (possibly different) unit can also be specified explicitly. Valid + memory units are <literal>kB</literal> (kilobytes), + <literal>MB</literal> (megabytes), and <literal>GB</literal> + (gigabytes); valid time units are <literal>ms</literal> + (milliseconds), <literal>s</literal> (seconds), + <literal>min</literal> (minutes), <literal>h</literal> (hours), + and <literal>d</literal> (days). Note that the multiplier for + memory units in 1024, not 1000. + </para> + <para> One way to set these parameters is to edit the file <filename>postgresql.conf</><indexterm><primary>postgresql.conf</></>, @@ -39,6 +53,7 @@ log_connections = yes log_destination = 'syslog' search_path = '"$user", public' +shared_buffers = 128MB </programlisting> One parameter is specified per line. The equal sign between name and value is optional. Whitespace is insignificant and blank lines are diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 2190caa7c724a86d69aaa301dd3459208c8c18bc..e88626aa5970ff53bde0b1eb38e53b74f3a9d15e 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -3,7 +3,7 @@ * * Copyright (c) 1996-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.28 2006/07/25 03:51:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.29 2006/07/27 08:30:41 petere Exp $ */ CREATE VIEW pg_roles AS @@ -172,7 +172,7 @@ CREATE VIEW pg_prepared_statements AS CREATE VIEW pg_settings AS SELECT * FROM pg_show_all_settings() AS A - (name text, setting text, category text, short_desc text, extra_desc text, + (name text, setting text, unit text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text); CREATE RULE pg_settings_u AS diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index dd59d5f99b2ceb7d919b188aff2673ee88957f68..82c1f03445037aa98db013155bb6cebd2ae61370 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -4,7 +4,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.37 2006/03/07 01:03:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.38 2006/07/27 08:30:41 petere Exp $ */ %{ @@ -68,7 +68,9 @@ SIGN ("-"|"+") DIGIT [0-9] HEXDIGIT [0-9a-fA-F] -INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+) +UNIT_LETTER [a-zA-Z] + +INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}* EXPONENT [Ee]{SIGN}?{DIGIT}+ REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}? diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ee05662b58c06bbad5444928988ff2842c798e17..5791e63d87b5e1ac439a81bf3e545270f474dc8f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.331 2006/07/26 11:39:47 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.332 2006/07/27 08:30:41 petere Exp $ * *-------------------------------------------------------------------- */ @@ -83,6 +83,14 @@ #define MAX_KILOBYTES (INT_MAX / 1024) #endif +#define KB_PER_MB (1024) +#define KB_PER_GB (1024*1024) + +#define MS_PER_S 1000 +#define MS_PER_MIN (1000 * 60) +#define MS_PER_H (1000 * 60 * 60) +#define MS_PER_D (1000 * 60 * 60 * 24) + /* XXX these should appear in other modules' header files */ extern bool Log_disconnections; extern bool check_function_bodies; @@ -1015,7 +1023,7 @@ static struct config_int ConfigureNamesInt[] = {"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS, gettext_noop("Waits N seconds on connection startup after authentication."), gettext_noop("This allows attaching a debugger to the process."), - GUC_NOT_IN_SAMPLE + GUC_NOT_IN_SAMPLE | GUC_UNIT_S }, &PostAuthDelay, 0, 0, INT_MAX, NULL, NULL @@ -1087,7 +1095,8 @@ static struct config_int ConfigureNamesInt[] = { {"deadlock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT, gettext_noop("The time in milliseconds to wait on lock before checking for deadlock."), - NULL + NULL, + GUC_UNIT_MS }, &DeadlockTimeout, 1000, 0, INT_MAX, NULL, NULL @@ -1125,7 +1134,8 @@ static struct config_int ConfigureNamesInt[] = { {"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM, gettext_noop("Sets the number of shared memory buffers used by the server."), - NULL + NULL, + GUC_UNIT_BLOCKS }, &NBuffers, 1000, 16, INT_MAX / 2, NULL, NULL @@ -1134,7 +1144,8 @@ static struct config_int ConfigureNamesInt[] = { {"temp_buffers", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum number of temporary buffers used by each session."), - NULL + NULL, + GUC_UNIT_BLOCKS }, &num_temp_buffers, 1000, 100, INT_MAX / 2, NULL, show_num_temp_buffers @@ -1167,7 +1178,8 @@ static struct config_int ConfigureNamesInt[] = gettext_noop("Sets the maximum memory to be used for query workspaces."), gettext_noop("This much memory may be used by each internal " "sort operation and hash table before switching to " - "temporary disk files.") + "temporary disk files."), + GUC_UNIT_KB }, &work_mem, 1024, 8 * BLCKSZ / 1024, MAX_KILOBYTES, NULL, NULL @@ -1176,7 +1188,8 @@ static struct config_int ConfigureNamesInt[] = { {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum memory to be used for maintenance operations."), - gettext_noop("This includes operations such as VACUUM and CREATE INDEX.") + gettext_noop("This includes operations such as VACUUM and CREATE INDEX."), + GUC_UNIT_KB }, &maintenance_work_mem, 16384, 1024, MAX_KILOBYTES, NULL, NULL @@ -1185,7 +1198,8 @@ static struct config_int ConfigureNamesInt[] = { {"max_stack_depth", PGC_SUSET, RESOURCES_MEM, gettext_noop("Sets the maximum stack depth, in kilobytes."), - NULL + NULL, + GUC_UNIT_KB }, &max_stack_depth, 2048, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL @@ -1230,7 +1244,8 @@ static struct config_int ConfigureNamesInt[] = { {"vacuum_cost_delay", PGC_USERSET, RESOURCES, gettext_noop("Vacuum cost delay in milliseconds."), - NULL + NULL, + GUC_UNIT_MS }, &VacuumCostDelay, 0, 0, 1000, NULL, NULL @@ -1239,7 +1254,8 @@ static struct config_int ConfigureNamesInt[] = { {"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM, gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."), - NULL + NULL, + GUC_UNIT_MS }, &autovacuum_vac_cost_delay, -1, -1, 1000, NULL, NULL @@ -1296,7 +1312,8 @@ static struct config_int ConfigureNamesInt[] = { {"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT, gettext_noop("Sets the maximum allowed duration (in milliseconds) of any statement."), - gettext_noop("A value of 0 turns off the timeout.") + gettext_noop("A value of 0 turns off the timeout."), + GUC_UNIT_MS }, &StatementTimeout, 0, 0, INT_MAX, NULL, NULL @@ -1333,7 +1350,8 @@ static struct config_int ConfigureNamesInt[] = { {"authentication_timeout", PGC_SIGHUP, CONN_AUTH_SECURITY, gettext_noop("Sets the maximum time in seconds to complete client authentication."), - NULL + NULL, + GUC_UNIT_S }, &AuthenticationTimeout, 60, 1, 600, NULL, NULL @@ -1344,7 +1362,7 @@ static struct config_int ConfigureNamesInt[] = {"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS, gettext_noop("no description available"), NULL, - GUC_NOT_IN_SAMPLE + GUC_NOT_IN_SAMPLE | GUC_UNIT_S }, &PreAuthDelay, 0, 0, 60, NULL, NULL @@ -1362,7 +1380,8 @@ static struct config_int ConfigureNamesInt[] = { {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS, gettext_noop("Sets the maximum time in seconds between automatic WAL checkpoints."), - NULL + NULL, + GUC_UNIT_S }, &CheckPointTimeout, 300, 30, 3600, NULL, NULL @@ -1424,7 +1443,8 @@ static struct config_int ConfigureNamesInt[] = {"log_min_duration_statement", PGC_SUSET, LOGGING_WHEN, gettext_noop("Sets the minimum execution time in milliseconds above which statements will " "be logged."), - gettext_noop("Zero prints all queries. The default is -1 (turning this feature off).") + gettext_noop("Zero prints all queries. The default is -1 (turning this feature off)."), + GUC_UNIT_MS }, &log_min_duration_statement, -1, -1, INT_MAX / 1000, NULL, NULL @@ -1433,7 +1453,8 @@ static struct config_int ConfigureNamesInt[] = { {"bgwriter_delay", PGC_SIGHUP, RESOURCES, gettext_noop("Background writer sleep time between rounds in milliseconds"), - NULL + NULL, + GUC_UNIT_MS }, &BgWriterDelay, 200, 10, 10000, NULL, NULL @@ -1460,7 +1481,8 @@ static struct config_int ConfigureNamesInt[] = { {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE, gettext_noop("Automatic log file rotation will occur after N minutes"), - NULL + NULL, + GUC_UNIT_MIN }, &Log_RotationAge, HOURS_PER_DAY * MINS_PER_HOUR, 0, INT_MAX / MINS_PER_HOUR, NULL, NULL @@ -1469,7 +1491,8 @@ static struct config_int ConfigureNamesInt[] = { {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE, gettext_noop("Automatic log file rotation will occur after N kilobytes"), - NULL + NULL, + GUC_UNIT_KB }, &Log_RotationSize, 10 * 1024, 0, INT_MAX / 1024, NULL, NULL @@ -1518,7 +1541,8 @@ static struct config_int ConfigureNamesInt[] = { {"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM, gettext_noop("Time to sleep between autovacuum runs, in seconds."), - NULL + NULL, + GUC_UNIT_S }, &autovacuum_naptime, 60, 1, INT_MAX, NULL, NULL @@ -1544,6 +1568,7 @@ static struct config_int ConfigureNamesInt[] = {"tcp_keepalives_idle", PGC_USERSET, CLIENT_CONN_OTHER, gettext_noop("Seconds between issuing TCP keepalives."), gettext_noop("A value of 0 uses the system default."), + GUC_UNIT_S }, &tcp_keepalives_idle, 0, 0, INT_MAX, assign_tcp_keepalives_idle, show_tcp_keepalives_idle @@ -1553,6 +1578,7 @@ static struct config_int ConfigureNamesInt[] = {"tcp_keepalives_interval", PGC_USERSET, CLIENT_CONN_OTHER, gettext_noop("Seconds between TCP keepalive retransmits."), gettext_noop("A value of 0 uses the system default."), + GUC_UNIT_S }, &tcp_keepalives_interval, 0, 0, INT_MAX, assign_tcp_keepalives_interval, show_tcp_keepalives_interval @@ -1584,7 +1610,8 @@ static struct config_int ConfigureNamesInt[] = gettext_noop("Sets the planner's assumption about size of the disk cache."), gettext_noop("That is, the portion of the kernel's disk cache that " "will be used for PostgreSQL data files. This is measured in disk " - "pages, which are normally 8 kB each.") + "pages, which are normally 8 kB each."), + GUC_UNIT_BLOCKS, }, &effective_cache_size, DEFAULT_EFFECTIVE_CACHE_SIZE, 1, INT_MAX, NULL, NULL @@ -2233,7 +2260,7 @@ static void push_old_value(struct config_generic * gconf); static void ReportGUCOption(struct config_generic * record); static void ShowGUCConfigOption(const char *name, DestReceiver *dest); static void ShowAllGUCConfig(DestReceiver *dest); -static char *_ShowOption(struct config_generic * record); +static char *_ShowOption(struct config_generic * record, bool use_units); static bool is_newvalue_equal(struct config_generic *record, const char *newvalue); @@ -3427,7 +3454,7 @@ ReportGUCOption(struct config_generic * record) { if (reporting_enabled && (record->flags & GUC_REPORT)) { - char *val = _ShowOption(record); + char *val = _ShowOption(record, false); StringInfoData msgbuf; pq_beginmessage(&msgbuf, 'S'); @@ -3513,13 +3540,86 @@ parse_bool(const char *value, bool *result) * value there. */ static bool -parse_int(const char *value, int *result) +parse_int(const char *value, int *result, int flags) { long val; char *endptr; errno = 0; val = strtol(value, &endptr, 0); + + if ((flags & GUC_UNIT_MEMORY) && endptr != value) + { + bool used = false; + + while (*endptr == ' ') + endptr++; + + if (strcmp(endptr, "kB") == 0) + { + used = true; + endptr += 2; + } + else if (strcmp(endptr, "MB") == 0) + { + val *= KB_PER_MB; + used = true; + endptr += 2; + } + else if (strcmp(endptr, "GB") == 0) + { + val *= KB_PER_MB; + used = true; + endptr += 2; + } + + if (used && (flags & GUC_UNIT_BLOCKS)) + val /= (BLCKSZ/1024); + } + + if ((flags & GUC_UNIT_TIME) && endptr != value) + { + bool used = false; + + while (*endptr == ' ') + endptr++; + + if (strcmp(endptr, "ms") == 0) + { + used = true; + endptr += 2; + } + else if (strcmp(endptr, "s") == 0) + { + val *= MS_PER_S; + used = true; + endptr += 1; + } + else if (strcmp(endptr, "min") == 0) + { + val *= MS_PER_MIN; + used = true; + endptr += 3; + } + else if (strcmp(endptr, "h") == 0) + { + val *= MS_PER_H; + used = true; + endptr += 1; + } + else if (strcmp(endptr, "d") == 0) + { + val *= MS_PER_D; + used = true; + endptr += 1; + } + + if (used && (flags & GUC_UNIT_S)) + val /= MS_PER_S; + else if (used && (flags & GUC_UNIT_MIN)) + val /= MS_PER_MIN; + } + if (endptr == value || *endptr != '\0' || errno == ERANGE #ifdef HAVE_LONG_INT_64 /* if long > 32 bits, check for overflow of int4 */ @@ -3850,7 +3950,7 @@ set_config_option(const char *name, const char *value, if (value) { - if (!parse_int(value, &newval)) + if (!parse_int(value, &newval, conf->gen.flags)) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -4754,7 +4854,7 @@ ShowAllGUCConfig(DestReceiver *dest) /* assign to the values array */ values[0] = (char *) conf->name; - values[1] = _ShowOption(conf); + values[1] = _ShowOption(conf, true); values[2] = (char *) conf->short_desc; /* send it to dest */ @@ -4790,7 +4890,7 @@ GetConfigOptionByName(const char *name, const char **varname) if (varname) *varname = record->name; - return _ShowOption(record); + return _ShowOption(record, true); } /* @@ -4823,25 +4923,49 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) values[0] = conf->name; /* setting : use _ShowOption in order to avoid duplicating the logic */ - values[1] = _ShowOption(conf); + values[1] = _ShowOption(conf, false); + + /* unit */ + if (conf->vartype == PGC_INT) + { + if (conf->flags & GUC_UNIT_KB) + values[2] = "kB"; + else if (conf->flags & GUC_UNIT_BLOCKS) + { + static char buf[8]; + + snprintf(buf, sizeof(buf), "%dkB", BLCKSZ/1024); + values[2] = buf; + } + else if (conf->flags & GUC_UNIT_MS) + values[2] = "ms"; + else if (conf->flags & GUC_UNIT_S) + values[2] = "s"; + else if (conf->flags & GUC_UNIT_MIN) + values[2] = "min"; + else + values[2] = ""; + } + else + values[2] = NULL; /* group */ - values[2] = config_group_names[conf->group]; + values[3] = config_group_names[conf->group]; /* short_desc */ - values[3] = conf->short_desc; + values[4] = conf->short_desc; /* extra_desc */ - values[4] = conf->long_desc; + values[5] = conf->long_desc; /* context */ - values[5] = GucContext_Names[conf->context]; + values[6] = GucContext_Names[conf->context]; /* vartype */ - values[6] = config_type_names[conf->vartype]; + values[7] = config_type_names[conf->vartype]; /* source */ - values[7] = GucSource_Names[conf->source]; + values[8] = GucSource_Names[conf->source]; /* now get the type specifc attributes */ switch (conf->vartype) @@ -4849,10 +4973,10 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) case PGC_BOOL: { /* min_val */ - values[8] = NULL; + values[9] = NULL; /* max_val */ - values[9] = NULL; + values[10] = NULL; } break; @@ -4862,11 +4986,11 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) /* min_val */ snprintf(buffer, sizeof(buffer), "%d", lconf->min); - values[8] = pstrdup(buffer); + values[9] = pstrdup(buffer); /* max_val */ snprintf(buffer, sizeof(buffer), "%d", lconf->max); - values[9] = pstrdup(buffer); + values[10] = pstrdup(buffer); } break; @@ -4876,21 +5000,21 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) /* min_val */ snprintf(buffer, sizeof(buffer), "%g", lconf->min); - values[8] = pstrdup(buffer); + values[9] = pstrdup(buffer); /* max_val */ snprintf(buffer, sizeof(buffer), "%g", lconf->max); - values[9] = pstrdup(buffer); + values[10] = pstrdup(buffer); } break; case PGC_STRING: { /* min_val */ - values[8] = NULL; + values[9] = NULL; /* max_val */ - values[9] = NULL; + values[10] = NULL; } break; @@ -4901,10 +5025,10 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow) */ /* min_val */ - values[8] = NULL; + values[9] = NULL; /* max_val */ - values[9] = NULL; + values[10] = NULL; } break; } @@ -4947,7 +5071,7 @@ show_config_by_name(PG_FUNCTION_ARGS) * show_all_settings - equiv to SHOW ALL command but implemented as * a Table Function. */ -#define NUM_PG_SETTINGS_ATTS 10 +#define NUM_PG_SETTINGS_ATTS 11 Datum show_all_settings(PG_FUNCTION_ARGS) @@ -4979,21 +5103,23 @@ show_all_settings(PG_FUNCTION_ARGS) TEXTOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "category", + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "unit", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "short_desc", + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "category", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 5, "extra_desc", + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "short_desc", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "context", + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "extra_desc", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 7, "vartype", + TupleDescInitEntry(tupdesc, (AttrNumber) 7, "context", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 8, "source", + TupleDescInitEntry(tupdesc, (AttrNumber) 8, "vartype", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 9, "min_val", + TupleDescInitEntry(tupdesc, (AttrNumber) 9, "source", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 10, "max_val", + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "min_val", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "max_val", TEXTOID, -1, 0); /* @@ -5056,7 +5182,7 @@ show_all_settings(PG_FUNCTION_ARGS) } static char * -_ShowOption(struct config_generic * record) +_ShowOption(struct config_generic * record, bool use_units) { char buffer[256]; const char *val; @@ -5082,8 +5208,66 @@ _ShowOption(struct config_generic * record) val = (*conf->show_hook) (); else { - snprintf(buffer, sizeof(buffer), "%d", - *conf->variable); + char unit[4]; + int result = *conf->variable; + + if (use_units && result > 0 && (record->flags & GUC_UNIT_MEMORY)) + { + if (record->flags & GUC_UNIT_BLOCKS) + result *= BLCKSZ/1024; + + if (result % KB_PER_GB == 0) + { + result /= KB_PER_GB; + strcpy(unit, "GB"); + } + else if (result % KB_PER_MB == 0) + { + result /= KB_PER_MB; + strcpy(unit, "MB"); + } + else + { + strcpy(unit, "kB"); + } + } + else if (use_units && result > 0 && (record->flags & GUC_UNIT_TIME)) + { + if (record->flags & GUC_UNIT_S) + result = result * MS_PER_S; + else if (record->flags & GUC_UNIT_MIN) + result = result * MS_PER_MIN; + + if (result % MS_PER_D == 0) + { + result /= MS_PER_D; + strcpy(unit, "d"); + } + else if (result % MS_PER_H == 0) + { + result /= MS_PER_H; + strcpy(unit, "h"); + } + else if (result % MS_PER_MIN == 0) + { + result /= MS_PER_MIN; + strcpy(unit, "min"); + } + else if (result % MS_PER_S == 0) + { + result /= MS_PER_S; + strcpy(unit, "s"); + } + else + { + strcpy(unit, "ms"); + } + } + else + strcpy(unit, ""); + + snprintf(buffer, sizeof(buffer), "%d%s", + (int)result, unit); val = buffer; } } @@ -5144,7 +5328,7 @@ is_newvalue_equal(struct config_generic *record, const char *newvalue) struct config_int *conf = (struct config_int *) record; int newval; - return parse_int(newvalue, &newval) && *conf->variable == newval; + return parse_int(newvalue, &newval, record->flags) && *conf->variable == newval; } case PGC_REAL: { diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 89c496ee2e03687004193af70a1aea661e38d641..63bed4e91951b6bcf49c6dd2d2ec97ff9943c9f2 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * Portions taken from FreeBSD. * - * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.118 2006/06/18 15:38:37 petere Exp $ + * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.119 2006/07/27 08:30:41 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1105,16 +1105,16 @@ test_config_settings(void) * */ -#define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10) +#define MIN_BUFS_FOR_CONNS(nconns) ((nconns) * 10 * (BLCKSZ/1024)) #define FSM_FOR_BUFS(nbuffers) ((nbuffers) > 1000 ? 50 * (nbuffers) : 20000) static const int trial_conns[] = { 100, 50, 40, 30, 20, 10 }; static const int trial_bufs[] = { - 4000, 3500, 3000, 2500, 2000, 1500, - 1000, 900, 800, 700, 600, 500, - 400, 300, 200, 100, 50 + 32000, 28000, 24000, 20000, 16000, 12000, + 8000, 7200, 6400, 5600, 4800, 4000, + 3200, 2400, 1600, 800, 400 }; char cmd[MAXPGPATH]; @@ -1140,7 +1140,7 @@ test_config_settings(void) snprintf(cmd, sizeof(cmd), "%s\"%s\" --boot -x0 %s " "-c max_connections=%d " - "-c shared_buffers=%d " + "-c shared_buffers=%dkB " "-c max_fsm_pages=%d " "template1 < \"%s\" > \"%s\" 2>&1%s", SYSTEMQUOTE, backend_exec, boot_options, @@ -1175,7 +1175,7 @@ test_config_settings(void) snprintf(cmd, sizeof(cmd), "%s\"%s\" --boot -x0 %s " "-c max_connections=%d " - "-c shared_buffers=%d " + "-c shared_buffers=%dkB " "-c max_fsm_pages=%d " "template1 < \"%s\" > \"%s\" 2>&1%s", SYSTEMQUOTE, backend_exec, boot_options, @@ -1188,7 +1188,7 @@ test_config_settings(void) n_buffers = test_buffs; n_fsm_pages = FSM_FOR_BUFS(n_buffers); - printf("%d/%d\n", n_buffers, n_fsm_pages); + printf("%dkB/%d\n", n_buffers, n_fsm_pages); } /* @@ -1211,7 +1211,7 @@ setup_config(void) snprintf(repltok, sizeof(repltok), "max_connections = %d", n_connections); conflines = replace_token(conflines, "#max_connections = 100", repltok); - snprintf(repltok, sizeof(repltok), "shared_buffers = %d", n_buffers); + snprintf(repltok, sizeof(repltok), "shared_buffers = %dkB", n_buffers); conflines = replace_token(conflines, "#shared_buffers = 1000", repltok); snprintf(repltok, sizeof(repltok), "max_fsm_pages = %d", n_fsm_pages); diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index 822bcfc98356368875db4bb6eefcf0e8bd44e065..ecb49cb22a99fb1686a4a634b9f61c48f285971a 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -7,7 +7,7 @@ * * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.23 2006/07/13 16:49:20 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.24 2006/07/27 08:30:41 petere Exp $ * *------------------------------------------------------------------------- */ @@ -130,6 +130,15 @@ struct config_generic #define GUC_SUPERUSER_ONLY 0x0100 /* show only to superusers */ #define GUC_IS_NAME 0x0200 /* limit string to NAMEDATALEN-1 */ +#define GUC_UNIT_KB 0x0400 /* value is in 1 kB */ +#define GUC_UNIT_BLOCKS 0x0800 /* value is in blocks */ +#define GUC_UNIT_MEMORY (GUC_UNIT_KB|GUC_UNIT_BLOCKS) + +#define GUC_UNIT_MS 0x1000 /* value is in milliseconds */ +#define GUC_UNIT_S 0x2000 /* value is in seconds */ +#define GUC_UNIT_MIN 0x4000 /* value is in minutes */ +#define GUC_UNIT_TIME (GUC_UNIT_MS|GUC_UNIT_S|GUC_UNIT_MIN) + /* bit values in status field */ #define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */ #define GUC_HAVE_LOCAL 0x0002 /* a SET LOCAL has been executed */ diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 350d73a735344227ce28d0b97c178537a9560467..0815196bbceb31da390313ca40cc67eaad7841b2 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1285,7 +1285,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem pg_prepared_xacts | SELECT p."transaction", p.gid, p."prepared", u.rolname AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, "prepared" timestamp with time zone, ownerid oid, dbid oid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid))); pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid; pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); - pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text); + pg_settings | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, unit text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text); pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin; pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.rolname AS usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start, pg_stat_get_backend_start(s.backendid) AS backend_start, pg_stat_get_backend_client_addr(s.backendid) AS client_addr, pg_stat_get_backend_client_port(s.backendid) AS client_port FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_authid u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.oid)); pg_stat_all_indexes | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"]));