mirror of https://github.com/postgres/postgres
That means you can now set your options in either or all of $PGDATA/configuration, some postmaster option (--enable-fsync=off), or set a SET command. The list of options is in backend/utils/misc/guc.c, documentation will be written post haste. pg_options is gone, so is that pq_geqo config file. Also removed were backend -K, -Q, and -T options (no longer applicable, although -d0 does the same as -Q). Added to configure an --enable-syslog option. changed all callers from TPRINTF to elog(DEBUG)REL7_1_STABLE
parent
5e4d554bae
commit
6a68f42648
@ -1,350 +0,0 @@ |
||||
/*------------------------------------------------------------------------
|
||||
* |
||||
* geqo_params.c |
||||
* routines for determining necessary genetic optimization parameters |
||||
* |
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* $Id: geqo_params.c,v 1.22 2000/01/26 05:56:33 momjian Exp $ |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
/* contributed by:
|
||||
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
* Martin Utesch * Institute of Automatic Control * |
||||
= = University of Mining and Technology = |
||||
* utesch@aut.tu-freiberg.de * Freiberg, Germany * |
||||
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
*/ |
||||
|
||||
#include <time.h> |
||||
#include <math.h> |
||||
#include <ctype.h> |
||||
|
||||
#include "postgres.h" |
||||
#include "miscadmin.h" |
||||
#include "nodes/pg_list.h" |
||||
#include "nodes/primnodes.h" |
||||
#include "nodes/relation.h" |
||||
#include "optimizer/clauses.h" |
||||
#include "optimizer/cost.h" |
||||
#include "optimizer/geqo.h" |
||||
#include "optimizer/geqo_gene.h" |
||||
#include "optimizer/internal.h" |
||||
#include "optimizer/pathnode.h" |
||||
#include "optimizer/paths.h" |
||||
#include "storage/fd.h" |
||||
|
||||
|
||||
/*
|
||||
* Parameter values read from the config file (or defaulted) are stored here |
||||
* by geqo_params(). |
||||
*/ |
||||
int PoolSize; |
||||
int Generations; |
||||
long RandomSeed; |
||||
double SelectionBias; |
||||
|
||||
|
||||
#define POOL_TAG "Pool_Size" |
||||
#define TRIAL_TAG "Generations" |
||||
#define RAND_TAG "Random_Seed" |
||||
#define BIAS_TAG "Selection_Bias" |
||||
|
||||
#define EFFORT_TAG "Effort"/* optimization effort and */ |
||||
#define LOW "low" /* corresponding tags */ |
||||
#define MEDIUM "medium" |
||||
#define HIGH "high" |
||||
|
||||
#define MAX_TOKEN 80 /* Maximum size of one token in the * |
||||
* configuration file */ |
||||
|
||||
static int gimme_pool_size(int string_length); |
||||
static int gimme_number_generations(int pool_size, int effort); |
||||
static int next_token(FILE *, char *, int); |
||||
static double geqo_log(double x, double b); |
||||
|
||||
/*
|
||||
* geqo_param |
||||
* get ga parameters out of "$PGDATA/pg_geqo" file. |
||||
*/ |
||||
void |
||||
geqo_params(int string_length) |
||||
{ |
||||
int i; |
||||
|
||||
char buf[MAX_TOKEN]; |
||||
FILE *file; |
||||
|
||||
char *conf_file; |
||||
|
||||
/* these flag variables signal that a value has been set from the file */ |
||||
int pool_size = 0; |
||||
int number_trials = 0; |
||||
int random_seed = 0; |
||||
int selection_bias = 0; |
||||
int effort = 0; |
||||
|
||||
|
||||
/* put together the full pathname to the config file */ |
||||
conf_file = (char *) palloc((strlen(DataDir) + strlen(GEQO_FILE) + 2) * sizeof(char)); |
||||
|
||||
sprintf(conf_file, "%s/%s", DataDir, GEQO_FILE); |
||||
|
||||
/* open the config file */ |
||||
#ifndef __CYGWIN32__ |
||||
file = AllocateFile(conf_file, "r"); |
||||
#else |
||||
file = AllocateFile(conf_file, "rb"); |
||||
#endif |
||||
if (file) |
||||
{ |
||||
|
||||
/*
|
||||
* empty and comment line stuff |
||||
*/ |
||||
while ((i = next_token(file, buf, sizeof(buf))) != EOF) |
||||
{ |
||||
/* If only token on the line, ignore */ |
||||
if (i == '\n') |
||||
continue; |
||||
|
||||
/* Comment -- read until end of line then next line */ |
||||
if (buf[0] == '#') |
||||
{ |
||||
while (next_token(file, buf, sizeof(buf)) == 0); |
||||
continue; |
||||
} |
||||
|
||||
/*
|
||||
* get ga parameters by parsing |
||||
*/ |
||||
|
||||
/*------------------------------------------------- pool size */ |
||||
if (strcmp(buf, POOL_TAG) == 0) |
||||
{ |
||||
i = next_token(file, buf, sizeof(buf)); /* get next token */ |
||||
|
||||
if (i != EOF) /* only ignore if we got no text at all */ |
||||
{ |
||||
if (sscanf(buf, "%d", &PoolSize) == 1) |
||||
pool_size = 1; |
||||
} |
||||
|
||||
} |
||||
|
||||
/*------------------------------------------------- number of trials */ |
||||
else if (strcmp(buf, TRIAL_TAG) == 0) |
||||
{ |
||||
i = next_token(file, buf, sizeof(buf)); |
||||
|
||||
if (i != EOF) |
||||
{ |
||||
if (sscanf(buf, "%d", &Generations) == 1) |
||||
number_trials = 1; |
||||
} |
||||
|
||||
} |
||||
|
||||
/*------------------------------------------------- optimization effort */ |
||||
else if (strcmp(buf, EFFORT_TAG) == 0) |
||||
{ |
||||
i = next_token(file, buf, sizeof(buf)); |
||||
|
||||
if (i != EOF) |
||||
{ |
||||
if (strcmp(buf, LOW) == 0) |
||||
effort = LOW_EFFORT; |
||||
else if (strcmp(buf, MEDIUM) == 0) |
||||
effort = MEDIUM_EFFORT; |
||||
else if (strcmp(buf, HIGH) == 0) |
||||
effort = HIGH_EFFORT; |
||||
/* undocumented extension: specify effort numerically */ |
||||
else if (isdigit(buf[0])) |
||||
effort = atoi(buf); |
||||
} |
||||
|
||||
} |
||||
|
||||
/*------------------------------------------- random seed */ |
||||
else if (strcmp(buf, RAND_TAG) == 0) |
||||
{ |
||||
i = next_token(file, buf, sizeof(buf)); |
||||
|
||||
if (i != EOF) |
||||
{ |
||||
if (sscanf(buf, "%ld", &RandomSeed) == 1) |
||||
random_seed = 1; |
||||
} |
||||
|
||||
} |
||||
|
||||
/*------------------------------------------- selection bias */ |
||||
else if (strcmp(buf, BIAS_TAG) == 0) |
||||
{ |
||||
i = next_token(file, buf, sizeof(buf)); |
||||
|
||||
if (i != EOF) |
||||
{ |
||||
if (sscanf(buf, "%lf", &SelectionBias) == 1) |
||||
selection_bias = 1; |
||||
} |
||||
|
||||
} |
||||
|
||||
/* unrecognized tags */ |
||||
else |
||||
{ |
||||
if (i != EOF) |
||||
{ |
||||
} |
||||
|
||||
elog(DEBUG, "geqo_params: unknown parameter type \"%s\"\nin file \'%s\'", buf, conf_file); |
||||
|
||||
/* if not at end-of-line, keep reading til we are */ |
||||
while (i == 0) |
||||
i = next_token(file, buf, sizeof(buf)); |
||||
} |
||||
} |
||||
|
||||
FreeFile(file); |
||||
|
||||
pfree(conf_file); |
||||
} |
||||
|
||||
else |
||||
elog(DEBUG, "geqo_params: ga parameter file\n\'%s\'\ndoes not exist or permissions are not setup correctly", conf_file); |
||||
|
||||
/*
|
||||
* parameter checkings follow |
||||
*/ |
||||
|
||||
/**************** PoolSize: essential ****************/ |
||||
if (!(pool_size)) |
||||
{ |
||||
PoolSize = gimme_pool_size(string_length); |
||||
|
||||
elog(DEBUG, "geqo_params: no pool size specified;\nusing computed value of %d", PoolSize); |
||||
} |
||||
|
||||
|
||||
/**************** Effort: essential ****************/ |
||||
if (!(effort)) |
||||
{ |
||||
effort = MEDIUM_EFFORT; |
||||
|
||||
elog(DEBUG, "geqo_params: no optimization effort specified;\nusing value of %d", effort); |
||||
|
||||
} |
||||
|
||||
/**************** Generations: essential ****************/ |
||||
if (!(number_trials)) |
||||
{ |
||||
Generations = gimme_number_generations(PoolSize, effort); |
||||
|
||||
elog(DEBUG, "geqo_params: no number of trials specified;\nusing computed value of %d", Generations); |
||||
|
||||
} |
||||
|
||||
/* RandomSeed: */ |
||||
if (!(random_seed)) |
||||
{ |
||||
RandomSeed = (long) time(NULL); |
||||
|
||||
elog(DEBUG, "geqo_params: no random seed specified;\nusing computed value of %ld", RandomSeed); |
||||
} |
||||
|
||||
/* SelectionBias: */ |
||||
if (!(selection_bias)) |
||||
{ |
||||
SelectionBias = SELECTION_BIAS; |
||||
|
||||
elog(DEBUG, "geqo_params: no selection bias specified;\nusing default value of %f", SelectionBias); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/*
|
||||
* Grab one token out of fp. Defined as the next string of non-whitespace |
||||
* in the file. After we get the token, continue reading until EOF, end of |
||||
* line or the next token. If it's the last token on the line, return '\n' |
||||
* for the value. If we get EOF before reading a token, return EOF. In all |
||||
* other cases return 0. |
||||
*/ |
||||
static int |
||||
next_token(FILE *fp, char *buf, int bufsz) |
||||
{ |
||||
int c; |
||||
char *eb = buf + (bufsz - 1); |
||||
|
||||
/* Discard inital whitespace */ |
||||
while (isspace(c = getc(fp))); |
||||
|
||||
/* EOF seen before any token so return EOF */ |
||||
if (c == EOF) |
||||
return -1; |
||||
|
||||
/* Form a token in buf */ |
||||
do |
||||
{ |
||||
if (buf < eb) |
||||
*buf++ = c; |
||||
c = getc(fp); |
||||
} while (!isspace(c) && c != EOF); |
||||
*buf = '\0'; |
||||
|
||||
/* Discard trailing tabs and spaces */ |
||||
while (c == ' ' || c == '\t') |
||||
c = getc(fp); |
||||
|
||||
/* Put back the char that was non-whitespace (putting back EOF is ok) */ |
||||
ungetc(c, fp); |
||||
|
||||
/* If we ended with a newline, return that, otherwise return 0 */ |
||||
return c == '\n' ? '\n' : 0; |
||||
} |
||||
|
||||
/* gimme_pool_size
|
||||
* compute good estimation for pool size |
||||
* according to number of involved rels in a query |
||||
*/ |
||||
static int |
||||
gimme_pool_size(int string_length) |
||||
{ |
||||
double exponent; |
||||
double size; |
||||
|
||||
exponent = (double) string_length + 1.0; |
||||
|
||||
size = pow(2.0, exponent); |
||||
|
||||
if (size < MIN_POOL) |
||||
return MIN_POOL; |
||||
else if (size > MAX_POOL) |
||||
return MAX_POOL; |
||||
else |
||||
return (int) ceil(size); |
||||
} |
||||
|
||||
/* gimme_number_generations
|
||||
* compute good estimation for number of generations size |
||||
* for convergence |
||||
*/ |
||||
static int |
||||
gimme_number_generations(int pool_size, int effort) |
||||
{ |
||||
int number_gens; |
||||
|
||||
number_gens = (int) ceil(geqo_log((double) pool_size, 2.0)); |
||||
|
||||
return effort * number_gens; |
||||
} |
||||
|
||||
static double |
||||
geqo_log(double x, double b) |
||||
{ |
||||
return (log(x) / log(b)); |
||||
} |
@ -1,72 +0,0 @@ |
||||
#*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
# pg_geqo * |
||||
# ------- = |
||||
# * |
||||
# Example Genetic Algorithm config file = |
||||
# for the PostgreSQL * |
||||
# Genetic Query Optimization (GEQO) module = |
||||
# * |
||||
#*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
# Martin Utesch * Institute of Automatic Control * |
||||
# = University of Mining and Technology = |
||||
# utesch@aut.tu-freiberg.de * Freiberg, Germany * |
||||
#*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
|
||||
# To make this file do something, copy it to '$PGDATA/pg_geqo' |
||||
# and edit parameters to taste. |
||||
# If '$PGDATA/pg_geqo' doesn't exist, the system will use default parameters. |
||||
# The file is re-read for every GEQO optimization, if it does exist. |
||||
|
||||
# comment character is '#' |
||||
# |
||||
# separator between recognized tag and possible value |
||||
# must be white space |
||||
|
||||
# QS: means query size, which is the number of relations |
||||
# contained in a query |
||||
|
||||
#=================+===================+=============================+ |
||||
# RECOGNIZED TAGS | POSSIBLE VALUES | DEFAULTS | |
||||
#=================+===================+=============================+ |
||||
# 'Pool_Size' | positive int | 2^(QS+1), but not less than | |
||||
# | | 128 nor more than 1024. | |
||||
#-----------------+-------------------+-----------------------------+ |
||||
# 'Effort' | [low,medium,high] | medium | |
||||
#-----------------+-------------------+-----------------------------+ |
||||
# 'Generations' | positive int | Effort * log2(Pool_Size) | |
||||
#-----------------+-------------------+-----------------------------+ |
||||
# 'Selection_Bias'| [1.50 .. 2.00] | 2.0 | |
||||
#-----------------+-------------------+-----------------------------+ |
||||
# 'Random_Seed' | positive long | time(NULL) | |
||||
#=================+===================+=============================+ |
||||
|
||||
# 'Pool_Size' is essential for the genetic algorithm performance. |
||||
# It gives us the number of individuals within one population. |
||||
# |
||||
# 'Effort' 'low' means integer value of 1, 'medium' 40, and 'high' 80. |
||||
# Note: Effort is *only* used to derive a default value for Generations |
||||
# --- if you specify Generations then Effort does not matter. |
||||
# |
||||
# 'Generations' specifies the number of iterations in the genetic algorithm. |
||||
# |
||||
# GEQO runtime is roughly proportional to Pool_Size + Generations. |
||||
# |
||||
# 'Selection_Bias' gives us the selective pressure within the |
||||
# population. |
||||
# |
||||
# 'Random_Seed' is the random seed for the random() function. |
||||
# You don't have to set it. If you do set it, then successive GEQO |
||||
# runs will produce repeatable results, whereas if you don't set it |
||||
# there will be some randomness in the results... |
||||
|
||||
# All parameters will be computed within the GEQO module when they |
||||
# are not set in the pg_geqo file. |
||||
|
||||
|
||||
# Example pg_geqo settings: |
||||
# |
||||
#Pool_Size 128 |
||||
#Effort low |
||||
#Generations 200 |
||||
#Random_Seed 830518260 |
||||
#Selection_Bias 1.750000 |
@ -1,249 +0,0 @@ |
||||
# pg_options file |
||||
|
||||
# Documented for Debian release 7.0-0.beta4-1 |
||||
# Copyright (c) Oliver Elphick <olly@lfix.co.uk> |
||||
# Licence: May be used without any payment or restriction, except that |
||||
# the copyright and licence must be preserved. |
||||
|
||||
# pg_options controls certain options and tracing features of the |
||||
# PostgreSQL backend. It is read by postmaster and postgres before |
||||
# command line arguments are examined, so command line arguments |
||||
# will override any settings here. |
||||
|
||||
# This file should be located at $PGDATA/pg_options. In Debian, this is |
||||
# a symbolic link to /etc/postgresql/pg_options. |
||||
|
||||
# The capitalised words refer to the internal #defines in the source code |
||||
# which use these options. Options can be turned on and off while the |
||||
# postmaster is running by editing this file and sending a SIGHUP to |
||||
# the postmaster. |
||||
|
||||
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# File format # |
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# option = integer : set option to the specified value |
||||
# option + : set option to 1 |
||||
# option - : set option to 0 |
||||
# |
||||
# Comments begin with #, whitespace is ignored completely. |
||||
# Options are separated by newlines (or by commas -- but why make it |
||||
# needlessly difficult to read the file?) |
||||
|
||||
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# Tracing options # |
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# all [TRACE_ALL] |
||||
# This governs what tracing occurs. If it is 0, tracing is |
||||
# controlled by the more specific options listed below. Set this to 1 |
||||
# to trace everything, regardless of the settings below; set to -1 to |
||||
# turn off all tracing. |
||||
# |
||||
# Any of these tracing options can be turned on with the command line |
||||
# option `-T "option[,...]"' |
||||
|
||||
all = 0 |
||||
|
||||
|
||||
# verbose [TRACE_VERBOSE] -- command line option `-d n' with n >= 1 |
||||
# Turns on verbose tracing of various events |
||||
|
||||
verbose = 0 |
||||
|
||||
|
||||
# query [TRACE_QUERY] -- command line option `-d n' with n >= 2 |
||||
# Traces the query string before and after rewriting |
||||
|
||||
query = 0 |
||||
|
||||
|
||||
# plan [TRACE_PLAN] -- command line option `-d n' with n >= 4 |
||||
# Traces plan trees in raw output format (see also pretty_plan) |
||||
|
||||
plan = 0 |
||||
|
||||
|
||||
# parse [TRACE_PARSE] -- command line option `-d n' with n >= 3 |
||||
# Traces the parser output in raw form (see also pretty_parse) |
||||
|
||||
parse = 0 |
||||
|
||||
|
||||
# rewritten [TRACE_REWRITTEN] |
||||
# Traces the query after rewriting, in raw form (see also pretty_rewritten) |
||||
|
||||
rewritten = 0 |
||||
|
||||
|
||||
# pretty_plan [TRACE_PRETTY_PLAN] |
||||
# shows indented multiline versions of plan trees (see also plan) |
||||
|
||||
pretty_plan = 0 |
||||
|
||||
|
||||
# pretty_parse [TRACE_PRETTY_PARSE] |
||||
# Traces the parser output in a readable form (see also parse) |
||||
|
||||
pretty_parse = 0 |
||||
|
||||
|
||||
# pretty_rewritten [TRACE_PRETTY_REWRITTEN] |
||||
# -- command line option `-d n' with n >= 5 |
||||
# Traces the query after rewriting, in a readable form (see also rewritten) |
||||
|
||||
pretty_rewritten = 0 |
||||
|
||||
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# Locks # |
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
|
||||
# TRACE_SHORTLOCKS |
||||
# This value is currently unused but needed as an index placeholder. |
||||
# It must be left set to 0, or mayhem may result, including segmentation |
||||
# violations, perhaps. |
||||
|
||||
shortlocks = 0 |
||||
|
||||
|
||||
# TRACE_LOCKS |
||||
# Enable or disable tracing of ordinary locks |
||||
|
||||
locks = 0 |
||||
|
||||
|
||||
# TRACE_USERLOCKS |
||||
# Enable or disable tracing of user (advisory) locks |
||||
|
||||
userlocks = 0 |
||||
|
||||
|
||||
# TRACE_SPINLOCKS |
||||
# Enables or disables tracing of spinlocks, but only if LOCKDEBUG was |
||||
# defined when PostgreSQL was compiled. (In the Debian release, |
||||
# LOCKDEBUG is not defined, so this option is inoperative.) |
||||
|
||||
spinlocks = 0 |
||||
|
||||
|
||||
# TRACE_LOCKOIDMIN |
||||
# This option is is used to avoid tracing locks on system relations, which |
||||
# would produce a lot of output. You should specify a value greater than |
||||
# the maximum oid of system relations, which can be found with the |
||||
# following query: |
||||
# |
||||
# select max(int4in(int4out(oid))) from pg_class where relname ~ '^pg_'; |
||||
# |
||||
# To get a useful lock trace you can set the following pg_options: |
||||
# |
||||
# verbose+, query+, locks+, userlocks+, lock_debug_oidmin=17500 |
||||
|
||||
lock_debug_oidmin = 0 |
||||
|
||||
|
||||
# TRACE_LOCKRELATION |
||||
# This option can be used to trace unconditionally a single relation, |
||||
# for example pg_listener, if you suspect there are locking problems. |
||||
|
||||
lock_debug_relid = 0 |
||||
|
||||
|
||||
# TRACE_NOTIFY |
||||
# Turn on tracing of asynchronous notifications from the backend. |
||||
|
||||
notify = 0 |
||||
|
||||
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# Memory Allocation # |
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# These do not appear to be used at 7.0beta4 |
||||
|
||||
# TRACE_MALLOC |
||||
|
||||
malloc = 0 |
||||
|
||||
# TRACE_PALLOC |
||||
|
||||
palloc = 0 |
||||
|
||||
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# Statistics # |
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# The statistics options are not controlled by either TRACE_ALL, or |
||||
# by USE_SYSLOG. These options cannot be used togther with the |
||||
# command line option `-s'. |
||||
|
||||
# TRACE_PARSERSTATS |
||||
# Prints parser statistics to standard error -- command line `-tpa[rser]' |
||||
|
||||
parserstats = 0 |
||||
|
||||
|
||||
# TRACE_PLANNERSTATS |
||||
# Prints planner statistics to standard error -- command line `-tpl[anner]' |
||||
|
||||
plannerstats = 0 |
||||
|
||||
|
||||
# TRACE_EXECUTORSTATS |
||||
# Prints executor statistics to standard error -- command line `-te[xecutor]' |
||||
|
||||
executorstats = 0 |
||||
|
||||
|
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
# options controlling run-time behaviour # |
||||
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# |
||||
|
||||
# OPT_LOCKREADPRIORITY |
||||
# lock priority, see lock.c -- Does not appear to be used |
||||
|
||||
lock_read_priority = 0 |
||||
|
||||
|
||||
# OPT_DEADLOCKTIMEOUT |
||||
# deadlock timeout; set this to a non-zero integer, which is the number |
||||
# of seconds that the backend should wait before deciding that it is in |
||||
# a deadlock and timing out. The system default is 1 second. |
||||
|
||||
deadlock_timeout = 0 |
||||
|
||||
|
||||
# nofsync [OPT_NOFSYNC] -- command line option `-F' |
||||
# If this is non-zero, fsync will be turned off; this means that saving |
||||
# to disk will be left to the normal operating system sync. If this |
||||
# option is zero, every transaction will trigger a sync to disk; this |
||||
# gives increased safety at the expense of performance. |
||||
|
||||
nofsync = 0 |
||||
|
||||
|
||||
# OPT_SYSLOG |
||||
# This controls the destination of [many] messages and traces: |
||||
# 0 : write to stdout or stderr |
||||
# 1 : write to stdout or stderr, and also through syslogd |
||||
# 2 : log only through syslogd |
||||
# [Not all messages have been converted to use routines controlled by |
||||
# this parameter; unconverted ones will print to stdout or stderr |
||||
# unconditionally and never to syslogd.] |
||||
|
||||
syslog = 0 |
||||
|
||||
|
||||
# OPT_HOSTLOOKUP |
||||
# enable hostname lookup in ps_status. If this is set, a reverse |
||||
# lookup will be done on the connecting IP address (for TCP/IP |
||||
# connections) for inclusion in the ps_status display. |
||||
|
||||
hostlookup = 0 |
||||
|
||||
|
||||
# OPT_SHOWPORTNUMBER |
||||
# show port number in ps_status. If this is set, the TCP port number |
||||
# will be included in the ps_status display (for TCP/IP connections). |
||||
|
||||
showportnumber = 0 |
||||
|
@ -0,0 +1,282 @@ |
||||
/* -*-pgsql-c-*- */ |
||||
/* |
||||
* Scanner for the configuration file |
||||
* |
||||
* Copyright 2000 by PostgreSQL Global Development Group |
||||
* |
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc-file.l,v 1.1 2000/05/31 00:28:34 petere Exp $ |
||||
*/ |
||||
|
||||
%{ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include <string.h> |
||||
#include <stdarg.h> |
||||
#include <sys/stat.h> |
||||
#include <unistd.h> |
||||
#include <errno.h> |
||||
|
||||
#include "miscadmin.h" |
||||
#include "storage/fd.h" |
||||
#include "utils/elog.h" |
||||
#include "utils/guc.h" |
||||
|
||||
static unsigned ConfigFileLineno; |
||||
|
||||
enum { |
||||
GUC_ID = 1, |
||||
GUC_STRING = 2, |
||||
GUC_INTEGER = 3, |
||||
GUC_REAL = 4, |
||||
GUC_EQUALS = 5, |
||||
GUC_EOL = 99, |
||||
GUC_ERROR = 100, |
||||
}; |
||||
|
||||
#if defined(yywrap) |
||||
#undef yywrap |
||||
#endif /* yywrap */ |
||||
|
||||
#define YY_USER_INIT (ConfigFileLineno = 1) |
||||
#define YY_NO_UNPUT |
||||
|
||||
%} |
||||
|
||||
SIGN ("-"|"+") |
||||
DIGIT [0-9] |
||||
HEXDIGIT [0-9a-fA-F] |
||||
|
||||
INTEGER {SIGN}?({DIGIT}+|0x{HEXDIGIT}+) |
||||
|
||||
EXPONENT [Ee]{SIGN}?{DIGIT}+ |
||||
REAL {SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}? |
||||
|
||||
LETTER [A-Za-z_\200-\377] |
||||
LETTER_OR_DIGIT [A-Za-z_0-9\200-\377] |
||||
|
||||
ID {LETTER}{LETTER_OR_DIGIT}* |
||||
/* |
||||
* FIXME: This string syntax is nice and all but of course the quotes |
||||
* need to be stripped before we can make any use of the string value. |
||||
* There is a function in parser/scansup.c that does this but it uses |
||||
* palloc and there might be a little more magic needed to get it to |
||||
* work right. Now there are no string options, and if there were then |
||||
* the unquoted (`ID') tokens should still work. Of course this only |
||||
* affects the configuration file. |
||||
*/ |
||||
STRING \'([^'\n]|\\.)*' |
||||
|
||||
%% |
||||
|
||||
\n ConfigFileLineno++; return GUC_EOL; |
||||
[ \t\r]+ /* eat whitespace */ |
||||
#.*$ /* eat comment */ |
||||
|
||||
{ID} return GUC_ID; |
||||
{STRING} return GUC_STRING; |
||||
{INTEGER} return GUC_INTEGER; |
||||
{REAL} return GUC_REAL; |
||||
= return GUC_EQUALS; |
||||
|
||||
. return GUC_ERROR; |
||||
|
||||
%% |
||||
|
||||
|
||||
struct name_value_pair |
||||
{ |
||||
char *name; |
||||
char *value; |
||||
struct name_value_pair *next; |
||||
}; |
||||
|
||||
|
||||
|
||||
/* |
||||
* Free a list of name/value pairs, including the names and the values |
||||
*/ |
||||
static void |
||||
free_name_value_list(struct name_value_pair * list) |
||||
{ |
||||
struct name_value_pair *item; |
||||
|
||||
item = list; |
||||
while (item) |
||||
{ |
||||
struct name_value_pair *save; |
||||
|
||||
save = item->next; |
||||
free(item->name); |
||||
free(item->value); |
||||
free(item); |
||||
item = save; |
||||
} |
||||
} |
||||
|
||||
|
||||
/* |
||||
* Official function to read and process the configuration file. The |
||||
* parameter indicates in what context the file is being read |
||||
* (postmaster startup, backend startup, or SIGHUP). All options |
||||
* mentioned in the configuration file are set to new values. This |
||||
* function does not return if an error occurs. If an error occurs, no |
||||
* values will be changed. |
||||
*/ |
||||
void |
||||
ProcessConfigFile(unsigned int context) |
||||
{ |
||||
int token, parse_state; |
||||
char *opt_name, *opt_value; |
||||
char *filename; |
||||
struct stat stat_buf; |
||||
struct name_value_pair *item, *head, *tail; |
||||
int elevel; |
||||
FILE * fp; |
||||
|
||||
Assert(context == PGC_POSTMASTER || context == PGC_BACKEND || context == PGC_SIGHUP); |
||||
Assert(DataDir); |
||||
elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR; |
||||
|
||||
/* |
||||
* Open file |
||||
*/ |
||||
filename = malloc(strlen(DataDir) + 16); |
||||
if (filename == NULL) |
||||
{ |
||||
elog(elevel, "out of memory"); |
||||
return; |
||||
} |
||||
sprintf(filename, "%s/configuration", DataDir); |
||||
|
||||
fp = AllocateFile(filename, "r"); |
||||
if (!fp) |
||||
{ |
||||
free(filename); |
||||
/* File not found is fine */ |
||||
if (errno != ENOENT) |
||||
elog(elevel, "could not read configuration: %s", strerror(errno)); |
||||
return; |
||||
} |
||||
|
||||
/* |
||||
* Check if the file is group or world writeable. If so, reject. |
||||
*/ |
||||
if (fstat(fileno(fp), &stat_buf) == -1) |
||||
{ |
||||
FreeFile(fp); |
||||
free(filename); |
||||
elog(elevel, "could not stat configuration file: %s", strerror(errno)); |
||||
return; |
||||
} |
||||
|
||||
if (stat_buf.st_mode & (S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH)) |
||||
{ |
||||
FreeFile(fp); |
||||
free(filename); |
||||
elog(elevel, "configuration file has wrong permissions"); |
||||
return; |
||||
} |
||||
|
||||
/* |
||||
* Parse |
||||
*/ |
||||
yyin = fp; |
||||
parse_state = 0; |
||||
head = tail = NULL; |
||||
opt_name = opt_value = NULL; |
||||
|
||||
while((token = yylex())) |
||||
switch(parse_state) |
||||
{ |
||||
case 0: /* no previous input */ |
||||
if (token == GUC_EOL) /* empty line */ |
||||
continue; |
||||
if (token != GUC_ID) |
||||
goto parse_error; |
||||
opt_name = strdup(yytext); |
||||
if (opt_name == NULL) |
||||
goto out_of_memory; |
||||
parse_state = 1; |
||||
break; |
||||
|
||||
case 1: /* found name */ |
||||
/* ignore equals sign */ |
||||
if (token == GUC_EQUALS) |
||||
token = yylex(); |
||||
|
||||
if (token != GUC_ID && token != GUC_STRING && token != GUC_INTEGER && token != GUC_REAL) |
||||
goto parse_error; |
||||
opt_value = strdup(yytext); |
||||
if (opt_value == NULL) |
||||
goto out_of_memory; |
||||
parse_state = 2; |
||||
break; |
||||
|
||||
case 2: /* now we'd like an end of line */ |
||||
if (token != GUC_EOL) |
||||
goto parse_error; |
||||
|
||||
/* append to list */ |
||||
item = malloc(sizeof *item); |
||||
if (item == NULL) |
||||
goto out_of_memory; |
||||
item->name = opt_name; |
||||
item->value = opt_value; |
||||
item->next = NULL; |
||||
|
||||
if (!head) |
||||
tail = head = item; |
||||
else |
||||
{ |
||||
tail->next = item; |
||||
tail = item; |
||||
} |
||||
|
||||
parse_state = 0; |
||||
break; |
||||
} |
||||
|
||||
FreeFile(fp); |
||||
free(filename); |
||||
|
||||
/* |
||||
* Check if all options are valid |
||||
*/ |
||||
for(item = head; item; item=item->next) |
||||
{ |
||||
if (!set_config_option(item->name, item->value, context, false)) |
||||
goto cleanup_exit; |
||||
} |
||||
|
||||
/* If we got here all the options parsed okay. */ |
||||
for(item = head; item; item=item->next) |
||||
set_config_option(item->name, item->value, context, true); |
||||
|
||||
cleanup_exit: |
||||
free_name_value_list(head); |
||||
return; |
||||
|
||||
parse_error: |
||||
FreeFile(fp); |
||||
free(filename); |
||||
free_name_value_list(head); |
||||
elog(elevel, "%s:%u: syntax error (ps:%d, t:%d)", filename, |
||||
ConfigFileLineno, parse_state, token); |
||||
return; |
||||
|
||||
out_of_memory: |
||||
FreeFile(fp); |
||||
free(filename); |
||||
free_name_value_list(head); |
||||
elog(elevel, "out of memory"); |
||||
return; |
||||
} |
||||
|
||||
|
||||
|
||||
int |
||||
yywrap(void) |
||||
{ |
||||
return 1; |
||||
} |
@ -0,0 +1,692 @@ |
||||
/*--------------------------------------------------------------------
|
||||
* guc.c |
||||
* |
||||
* Support for grand unified configuration scheme, including SET |
||||
* command, configuration file, and command line options. |
||||
* |
||||
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.1 2000/05/31 00:28:34 petere Exp $ |
||||
* |
||||
* Copyright 2000 by PostgreSQL Global Development Group |
||||
* Written by Peter Eisentraut <peter_e@gmx.net>. |
||||
*-------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include <errno.h> |
||||
#include <float.h> |
||||
#include <limits.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "utils/guc.h" |
||||
|
||||
#include "access/transam.h" |
||||
#include "commands/async.h" |
||||
#include "miscadmin.h" |
||||
#include "optimizer/cost.h" |
||||
#include "optimizer/geqo.h" |
||||
#include "optimizer/paths.h" |
||||
#include "optimizer/planmain.h" |
||||
#include "parser/parse_expr.h" |
||||
#include "storage/fd.h" |
||||
#include "storage/lock.h" |
||||
#include "storage/proc.h" |
||||
#include "storage/spin.h" |
||||
#include "tcop/tcopprot.h" |
||||
#include "utils/builtins.h" |
||||
#include "utils/elog.h" |
||||
|
||||
|
||||
/* XXX should be in a header file */ |
||||
extern bool Log_connections; |
||||
|
||||
/*
|
||||
* Debugging options |
||||
*/ |
||||
bool Debug_print_query = false; |
||||
bool Debug_print_plan = false; |
||||
bool Debug_print_parse = false; |
||||
bool Debug_print_rewritten = false; |
||||
bool Debug_pretty_print = false; |
||||
|
||||
bool Show_parser_stats = false; |
||||
bool Show_planner_stats = false; |
||||
bool Show_executor_stats = false; |
||||
bool Show_query_stats = false; /* this is sort of all three above together */ |
||||
bool Show_btree_build_stats = false; |
||||
|
||||
|
||||
|
||||
enum config_type |
||||
{ |
||||
PGC_NONE = 0, |
||||
PGC_BOOL, |
||||
PGC_INT, |
||||
PGC_REAL, |
||||
PGC_STRING |
||||
}; |
||||
|
||||
|
||||
struct config_generic |
||||
{ |
||||
const char *name; |
||||
GucContext context; |
||||
void *variable; |
||||
}; |
||||
|
||||
|
||||
struct config_bool |
||||
{ |
||||
const char *name; |
||||
GucContext context; |
||||
bool *variable; |
||||
bool default_val; |
||||
}; |
||||
|
||||
|
||||
struct config_int |
||||
{ |
||||
const char *name; |
||||
GucContext context; |
||||
int *variable; |
||||
int default_val; |
||||
int min; |
||||
int max; |
||||
}; |
||||
|
||||
|
||||
struct config_real |
||||
{ |
||||
const char *name; |
||||
GucContext context; |
||||
double *variable; |
||||
double default_val; |
||||
double min; |
||||
double max; |
||||
}; |
||||
|
||||
/*
|
||||
* String value options are allocated with strdup, not with the |
||||
* pstrdup/palloc mechanisms. That is because configuration settings |
||||
* are already in place before the memory subsystem is up. It would |
||||
* perhaps be an idea to change that sometime. |
||||
*/ |
||||
struct config_string |
||||
{ |
||||
const char *name; |
||||
GucContext context; |
||||
char *variable; |
||||
const char *default_val; |
||||
bool (*parse_hook)(const char *); |
||||
}; |
||||
|
||||
|
||||
|
||||
/******** option names follow ********/ |
||||
|
||||
static struct config_bool |
||||
ConfigureNamesBool[] = |
||||
{ |
||||
{"enable_seqscan", PGC_USERSET, &enable_seqscan, true}, |
||||
{"enable_indexscan", PGC_USERSET, &enable_indexscan, true}, |
||||
{"enable_tidscan", PGC_USERSET, &enable_tidscan, true}, |
||||
{"enable_sort", PGC_USERSET, &enable_sort, true}, |
||||
{"enable_nestloop", PGC_USERSET, &enable_nestloop, true}, |
||||
{"enable_mergejoin", PGC_USERSET, &enable_mergejoin, true}, |
||||
{"enable_hashjoin", PGC_USERSET, &enable_hashjoin, true}, |
||||
|
||||
{"ksqo", PGC_USERSET, &_use_keyset_query_optimizer, false}, |
||||
{"geqo", PGC_USERSET, &enable_geqo, true}, |
||||
|
||||
{"net_server", PGC_POSTMASTER, &NetServer, false}, |
||||
{"fsync", PGC_POSTMASTER, &enableFsync, true}, |
||||
|
||||
{"log_connections", PGC_POSTMASTER, &Log_connections, false}, |
||||
|
||||
{"debug_print_query", PGC_SUSET, &Debug_print_query, false}, |
||||
{"debug_print_parse", PGC_SUSET, &Debug_print_parse, false}, |
||||
{"debug_print_rewritten", PGC_SUSET, &Debug_print_rewritten, false}, |
||||
{"debug_print_plan", PGC_SUSET, &Debug_print_plan, false}, |
||||
{"debug_pretty_print", PGC_SUSET, &Debug_pretty_print, false}, |
||||
|
||||
{"show_parser_stats", PGC_SUSET, &Show_parser_stats, false}, |
||||
{"show_planner_stats", PGC_SUSET, &Show_planner_stats, false}, |
||||
{"show_executor_stats", PGC_SUSET, &Show_executor_stats, false}, |
||||
{"show_query_stats", PGC_SUSET, &Show_query_stats, false}, |
||||
#ifdef BTREE_BUILD_STATS |
||||
{"show_btree_build_stats", PGC_SUSET, &Show_btree_build_stats, false}, |
||||
#endif |
||||
|
||||
{"trace_notify", PGC_SUSET, &Trace_notify, false}, |
||||
|
||||
#ifdef LOCK_DEBUG |
||||
{"trace_locks", PGC_SUSET, &Trace_locks, false}, |
||||
{"trace_userlocks", PGC_SUSET, &Trace_userlocks, false}, |
||||
{"trace_spinlocks", PGC_SUSET, &Trace_spinlocks, false}, |
||||
{"debug_deadlocks", PGC_SUSET, &Debug_deadlocks, false}, |
||||
#endif |
||||
|
||||
{"hostlookup", PGC_POSTMASTER, &HostnameLookup, false}, |
||||
{"showportnumber", PGC_POSTMASTER, &ShowPortNumber, false}, |
||||
|
||||
{NULL, 0, NULL, false} |
||||
}; |
||||
|
||||
|
||||
static struct config_int |
||||
ConfigureNamesInt[] = |
||||
{ |
||||
{"geqo_rels", PGC_USERSET, &geqo_rels, |
||||
DEFAULT_GEQO_RELS, 2, INT_MAX}, |
||||
{"geqo_pool_size", PGC_USERSET, &Geqo_pool_size, |
||||
DEFAULT_GEQO_POOL_SIZE, 0, MAX_GEQO_POOL_SIZE}, |
||||
{"geqo_effort", PGC_USERSET, &Geqo_effort, |
||||
1, 1, INT_MAX}, |
||||
{"geqo_generations", PGC_USERSET, &Geqo_generations, |
||||
0, 0, INT_MAX}, |
||||
{"geqo_random_seed", PGC_USERSET, &Geqo_random_seed, |
||||
-1, INT_MIN, INT_MAX}, |
||||
|
||||
{"deadlock_timeout", PGC_POSTMASTER, &DeadlockTimeout, |
||||
1000, 0, INT_MAX}, |
||||
|
||||
#ifdef ENABLE_SYSLOG |
||||
{"syslog", PGC_POSTMASTER, &Use_syslog, |
||||
0, 0, 2}, |
||||
#endif |
||||
|
||||
/*
|
||||
* Note: There is some postprocessing done in PostmasterMain() to |
||||
* make sure the buffers are at least twice the number of |
||||
* backends, so the constraints here are partially unused. |
||||
*/ |
||||
{"max_backends", PGC_POSTMASTER, &MaxBackends, |
||||
DEF_MAXBACKENDS, 1, MAXBACKENDS}, |
||||
{"shmem_buffers", PGC_POSTMASTER, &NBuffers, |
||||
DEF_NBUFFERS, 16, INT_MAX}, |
||||
{"port", PGC_POSTMASTER, &PostPortName, |
||||
DEF_PGPORT, 1, 65535}, |
||||
|
||||
/* XXX Is this really changeable at runtime? */ |
||||
{"sort_mem", PGC_SUSET, &SortMem, |
||||
512, 1, INT_MAX}, |
||||
|
||||
{"debug_level", PGC_SUSET, &DebugLvl, |
||||
0, 0, 16}, |
||||
|
||||
#ifdef LOCK_DEBUG |
||||
{"trace_lock_oidmin", PGC_SUSET, &Trace_lock_oidmin, |
||||
BootstrapObjectIdData, 1, INT_MAX}, |
||||
{"trace_lock_table", PGC_SUSET, &Trace_lock_table, |
||||
0, 0, INT_MAX}, |
||||
#endif |
||||
{"max_expr_depth", PGC_USERSET, &max_expr_depth, |
||||
DEFAULT_MAX_EXPR_DEPTH, 10, INT_MAX}, |
||||
|
||||
{NULL, 0, NULL, 0, 0, 0} |
||||
}; |
||||
|
||||
|
||||
static struct config_real |
||||
ConfigureNamesReal[] = |
||||
{ |
||||
{"effective_cache_size", PGC_USERSET, &effective_cache_size, |
||||
DEFAULT_EFFECTIVE_CACHE_SIZE, 0, DBL_MAX}, |
||||
{"random_page_cost", PGC_USERSET, &random_page_cost, |
||||
DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX}, |
||||
{"cpu_tuple_cost", PGC_USERSET, &cpu_tuple_cost, |
||||
DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX}, |
||||
{"cpu_index_tuple_cost", PGC_USERSET, &cpu_index_tuple_cost, |
||||
DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX}, |
||||
{"cpu_operator_cost", PGC_USERSET, &cpu_operator_cost, |
||||
DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX}, |
||||
|
||||
{"geqo_selection_bias", PGC_USERSET, &Geqo_selection_bias, |
||||
DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS}, |
||||
|
||||
{NULL, 0, NULL, 0.0, 0.0, 0.0} |
||||
}; |
||||
|
||||
|
||||
static struct config_string |
||||
ConfigureNamesString[] = |
||||
{ |
||||
/* none so far */ |
||||
|
||||
{NULL, 0, NULL, NULL, NULL} |
||||
}; |
||||
|
||||
/******** end of options list ********/ |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Look up option NAME. If it exists, return it's data type, else |
||||
* PGC_NONE (zero). If record is not NULL, store the description of |
||||
* the option there. |
||||
*/ |
||||
static enum config_type |
||||
find_option(const char * name, struct config_generic ** record) |
||||
{ |
||||
int i; |
||||
|
||||
Assert(name); |
||||
|
||||
for (i = 0; ConfigureNamesBool[i].name; i++) |
||||
if (strcasecmp(ConfigureNamesBool[i].name, name)==0) |
||||
{ |
||||
if (record) |
||||
*record = (struct config_generic *)&ConfigureNamesBool[i]; |
||||
return PGC_BOOL; |
||||
} |
||||
|
||||
for (i = 0; ConfigureNamesInt[i].name; i++) |
||||
if (strcasecmp(ConfigureNamesInt[i].name, name)==0) |
||||
{ |
||||
if (record) |
||||
*record = (struct config_generic *)&ConfigureNamesInt[i]; |
||||
return PGC_INT; |
||||
} |
||||
|
||||
for (i = 0; ConfigureNamesReal[i].name; i++) |
||||
if (strcasecmp(ConfigureNamesReal[i].name, name)==0) |
||||
{ |
||||
if (record) |
||||
*record = (struct config_generic *)&ConfigureNamesReal[i]; |
||||
return PGC_REAL; |
||||
} |
||||
|
||||
for (i = 0; ConfigureNamesString[i].name; i++) |
||||
if (strcasecmp(ConfigureNamesString[i].name, name)==0) |
||||
{ |
||||
if (record) |
||||
*record = (struct config_generic *)&ConfigureNamesString[i]; |
||||
return PGC_REAL; |
||||
} |
||||
|
||||
return PGC_NONE; |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Reset all options to their specified default values. Should only be |
||||
* called at program startup. |
||||
*/ |
||||
void |
||||
ResetAllOptions(void) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; ConfigureNamesBool[i].name; i++) |
||||
*(ConfigureNamesBool[i].variable) = ConfigureNamesBool[i].default_val; |
||||
|
||||
for (i = 0; ConfigureNamesInt[i].name; i++) |
||||
*(ConfigureNamesInt[i].variable) = ConfigureNamesInt[i].default_val; |
||||
|
||||
for (i = 0; ConfigureNamesReal[i].name; i++) |
||||
*(ConfigureNamesReal[i].variable) = ConfigureNamesReal[i].default_val; |
||||
|
||||
for (i = 0; ConfigureNamesString[i].name; i++) |
||||
{ |
||||
char * str = NULL; |
||||
|
||||
if (ConfigureNamesString[i].default_val) |
||||
{ |
||||
str = strdup(ConfigureNamesString[i].default_val); |
||||
if (str == NULL) |
||||
elog(ERROR, "out of memory"); |
||||
} |
||||
ConfigureNamesString[i].variable = str; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Try to interpret value as boolean value. Valid values are: true, |
||||
* false, yes, no, on, off, 1, 0. If the string parses okay, return |
||||
* true, else false. If result is not NULL, return the parsing result |
||||
* there. |
||||
*/ |
||||
static bool |
||||
parse_bool(const char * value, bool * result) |
||||
{ |
||||
size_t len = strlen(value); |
||||
|
||||
if (strncasecmp(value, "true", len)==0) |
||||
{ |
||||
if (result) |
||||
*result = true; |
||||
} |
||||
else if (strncasecmp(value, "false", len)==0) |
||||
{ |
||||
if (result) |
||||
*result = false; |
||||
} |
||||
|
||||
else if (strncasecmp(value, "yes", len)==0) |
||||
{ |
||||
if (result) |
||||
*result = true; |
||||
} |
||||
else if (strncasecmp(value, "no", len)==0) |
||||
{ |
||||
if (result) |
||||
*result = false; |
||||
} |
||||
|
||||
else if (strcasecmp(value, "on")==0) |
||||
{ |
||||
if (result) |
||||
*result = true; |
||||
} |
||||
else if (strcasecmp(value, "off")==0) |
||||
{ |
||||
if (result) |
||||
*result = false; |
||||
} |
||||
|
||||
else if (strcasecmp(value, "1")==0) |
||||
{ |
||||
if (result) |
||||
*result = true; |
||||
} |
||||
else if (strcasecmp(value, "0")==0) |
||||
{ |
||||
if (result) |
||||
*result = false; |
||||
} |
||||
|
||||
else |
||||
return false; |
||||
return true; |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Try to parse value as an integer. The accepted formats are the |
||||
* usual decimal, octal, or hexadecimal formats. If the string parses |
||||
* okay, return true, else false. If result is not NULL, return the |
||||
* value there. |
||||
*/ |
||||
static bool |
||||
parse_int(const char * value, int * result) |
||||
{ |
||||
long val; |
||||
char * endptr; |
||||
|
||||
errno = 0; |
||||
val = strtol(value, &endptr, 0); |
||||
if (endptr == value || *endptr != '\0' || errno == ERANGE) |
||||
return false; |
||||
if (result) |
||||
*result = (int)val; |
||||
return true; |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Try to parse value as a floating point constant in the usual |
||||
* format. If the value parsed okay return true, else false. If |
||||
* result is not NULL, return the semantic value there. |
||||
*/ |
||||
static bool |
||||
parse_real(const char * value, double * result) |
||||
{ |
||||
double val; |
||||
char * endptr; |
||||
|
||||
errno = 0; |
||||
val = strtod(value, &endptr); |
||||
if (endptr == value || *endptr != '\0' || errno == ERANGE) |
||||
return false; |
||||
if (result) |
||||
*result = val; |
||||
return true; |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Sets option `name' to given value. The value should be a string |
||||
* which is going to be parsed and converted to the appropriate data |
||||
* type. Parameter context should indicate in which context this |
||||
* function is being called so it can apply the access restrictions |
||||
* properly. |
||||
* |
||||
* If value is NULL, set the option to its default value. If the |
||||
* parameter DoIt is false then don't really set the option but do all |
||||
* the checks to see if it would work. |
||||
* |
||||
* If there is an error (non-existing option, invalid value) then an |
||||
* elog(ERROR) is thrown *unless* this is called as part of the |
||||
* configuration file re-read in the SIGHUP handler, in which case we |
||||
* simply write the error message via elog(DEBUG) and return false. In |
||||
* all other cases the function returns true. This is working around |
||||
* the deficiencies in the elog mechanism, so don't blame me. |
||||
* |
||||
* See also SetConfigOption for an external interface. |
||||
*/ |
||||
bool |
||||
set_config_option(const char * name, const char * value, GucContext |
||||
context, bool DoIt) |
||||
{ |
||||
struct config_generic * record; |
||||
enum config_type type; |
||||
int elevel; |
||||
|
||||
elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR; |
||||
|
||||
type = find_option(name, &record); |
||||
if (type == PGC_NONE) |
||||
{ |
||||
elog(elevel, "not a valid option name: %s", name); |
||||
return false; |
||||
} |
||||
|
||||
if (record->context < context) |
||||
{ |
||||
/* can't set option right now */ |
||||
switch (context) |
||||
{ |
||||
case PGC_USERSET: |
||||
elog(ERROR, "permission denied"); |
||||
/*NORETURN*/ |
||||
case PGC_SUSET: |
||||
elog(ERROR, "%s can only be set at startup", name); |
||||
/*NORETURN*/ |
||||
case PGC_SIGHUP: |
||||
/* ignore the option */ |
||||
return true; |
||||
case PGC_BACKEND: |
||||
/* ignore; is this the right thing to do? */ |
||||
return true; |
||||
default: |
||||
elog(FATAL, "%s:%d: internal error", __FILE__, __LINE__); |
||||
/*NORETURN*/ |
||||
} |
||||
} |
||||
|
||||
switch(type) |
||||
{ |
||||
case PGC_BOOL: |
||||
{ |
||||
struct config_bool * conf = (struct config_bool *)record; |
||||
|
||||
if (value) |
||||
{ |
||||
bool boolval; |
||||
if (!parse_bool(value, &boolval)) |
||||
{ |
||||
elog(elevel, "expected boolean value for option %s", name); |
||||
return false; |
||||
} |
||||
if (DoIt) |
||||
*conf->variable = boolval; |
||||
} |
||||
else if (DoIt) |
||||
*conf->variable = conf->default_val; |
||||
break; |
||||
} |
||||
|
||||
case PGC_INT: |
||||
{ |
||||
struct config_int * conf = (struct config_int *)record; |
||||
|
||||
if (value) |
||||
{ |
||||
int intval; |
||||
|
||||
if (!parse_int(value, &intval)) |
||||
{ |
||||
elog(elevel, "expected integer value for option %s", name); |
||||
return false; |
||||
} |
||||
if (intval < conf->min || intval > conf->max) |
||||
{ |
||||
elog(elevel, "value out of permissible range %d .. %d", conf->min, conf->max); |
||||
return false; |
||||
} |
||||
if (DoIt) |
||||
*conf->variable = intval; |
||||
} |
||||
else if (DoIt) |
||||
*conf->variable = conf->default_val; |
||||
break; |
||||
} |
||||
|
||||
case PGC_REAL: |
||||
{ |
||||
struct config_real * conf = (struct config_real *)record; |
||||
|
||||
if (value) |
||||
{ |
||||
double dval; |
||||
|
||||
if (!parse_real(value, &dval)) |
||||
{ |
||||
elog(elevel, "expected real number for option %s", name); |
||||
return false; |
||||
} |
||||
if (dval < conf->min || dval > conf->max) |
||||
{ |
||||
elog(elevel, "value out of permissible range %g .. %g", conf->min, conf->max); |
||||
return false; |
||||
} |
||||
if (DoIt) |
||||
*conf->variable = dval; |
||||
} |
||||
else if (DoIt) |
||||
*conf->variable = conf->default_val; |
||||
break; |
||||
} |
||||
|
||||
case PGC_STRING: |
||||
{ |
||||
struct config_string * conf = (struct config_string *)record; |
||||
|
||||
if (value) |
||||
{ |
||||
if (conf->parse_hook && !(conf->parse_hook)(value)) |
||||
{ |
||||
elog(elevel, "value '%s' not accepted for option %s", value, name); |
||||
return false; |
||||
} |
||||
if (DoIt) |
||||
{ |
||||
char * str; |
||||
|
||||
str = strdup(value); |
||||
if (str == NULL) |
||||
{ |
||||
elog(elevel, "out of memory"); |
||||
return false; |
||||
} |
||||
free(conf->variable); |
||||
conf->variable = str; |
||||
} |
||||
} |
||||
else if (DoIt) |
||||
{ |
||||
char * str; |
||||
|
||||
str = strdup(conf->default_val); |
||||
if (str == NULL) |
||||
{ |
||||
elog(elevel, "out of memory"); |
||||
return false; |
||||
} |
||||
free(conf->variable); |
||||
conf->variable = str; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
default: ; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* Set a config option to the given value. See also set_config_option, |
||||
* this is just the wrapper to be called from the outside. |
||||
*/ |
||||
void |
||||
SetConfigOption(const char * name, const char * value, GucContext |
||||
context) |
||||
{ |
||||
(void)set_config_option(name, value, context, true); |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* This is more or less the SHOW command. It returns a string with the |
||||
* value of the option `name'. If the option doesn't exist, throw an |
||||
* elog and don't return. issuper should be true if and only if the |
||||
* current user is a superuser. Normal users don't have read |
||||
* permission on all options. |
||||
* |
||||
* The string is *not* allocated for modification and is really only |
||||
* valid until the next call to configuration related functions. |
||||
*/ |
||||
const char * |
||||
GetConfigOption(const char * name, bool issuper) |
||||
{ |
||||
struct config_generic * record; |
||||
static char buffer[256]; |
||||
enum config_type opttype; |
||||
|
||||
opttype = find_option(name, &record); |
||||
if (opttype == PGC_NONE) |
||||
elog(ERROR, "not a valid option name: %s", name); |
||||
|
||||
if (record->context < PGC_USERSET && !issuper) |
||||
elog(ERROR, "permission denied"); |
||||
|
||||
switch(opttype) |
||||
{ |
||||
case PGC_BOOL: |
||||
return *((struct config_bool *)record)->variable ? "true" : "false"; |
||||
|
||||
case PGC_INT: |
||||
snprintf(buffer, 256, "%d", *((struct config_int *)record)->variable); |
||||
return buffer; |
||||
|
||||
case PGC_REAL: |
||||
snprintf(buffer, 256, "%g", *((struct config_real *)record)->variable); |
||||
return buffer; |
||||
|
||||
case PGC_STRING: |
||||
return ((struct config_string *)record)->variable; |
||||
|
||||
default: |
||||
; |
||||
} |
||||
return NULL; |
||||
}
|
@ -1,511 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* trace.c |
||||
* |
||||
* Conditional trace and logging functions. |
||||
* |
||||
* Massimo Dal Zotto <dz@cs.unitn.it> |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include <unistd.h> |
||||
#include <signal.h> |
||||
#include <sys/time.h> |
||||
#include <sys/types.h> |
||||
#include <sys/stat.h> |
||||
#include <fcntl.h> |
||||
#ifdef USE_SYSLOG |
||||
#include <syslog.h> |
||||
#endif |
||||
|
||||
#include "miscadmin.h" |
||||
#include "utils/trace.h" |
||||
|
||||
#include <ctype.h> |
||||
|
||||
#ifdef MULTIBYTE |
||||
#include "mb/pg_wchar.h" |
||||
#endif |
||||
|
||||
/*
|
||||
* We could support trace messages of indefinite length, as elog() does, |
||||
* but it's probably not worth the trouble. Instead limit trace message |
||||
* length to this. |
||||
*/ |
||||
#define TRACEMSG_MAXLEN 4096 |
||||
|
||||
#ifdef USE_SYSLOG |
||||
/*
|
||||
* Global option to control the use of syslog(3) for logging: |
||||
* |
||||
* 0 stdout/stderr only |
||||
* 1 stdout/stderr + syslog |
||||
* 2 syslog only |
||||
*/ |
||||
#define UseSyslog pg_options[OPT_SYSLOG] |
||||
#define PG_LOG_FACILITY LOG_LOCAL0 |
||||
#define PG_LOG_IDENT "postgres" |
||||
#else |
||||
#define UseSyslog 0 |
||||
#endif |
||||
|
||||
/*
|
||||
* Trace option names, must match the constants in trace_opts[]. |
||||
*/ |
||||
static char *opt_names[] = { |
||||
"all", /* 0=trace some, 1=trace all, -1=trace
|
||||
* none */ |
||||
"verbose", |
||||
"query", |
||||
"plan", |
||||
"parse", |
||||
"rewritten", |
||||
"pretty_plan", |
||||
"pretty_parse", |
||||
"pretty_rewritten", |
||||
"parserstats", |
||||
"plannerstats", |
||||
"executorstats", |
||||
"shortlocks", /* currently unused but needed, see lock.c */ |
||||
"locks", |
||||
"userlocks", |
||||
"spinlocks", |
||||
"notify", |
||||
"malloc", |
||||
"palloc", |
||||
"lock_debug_oidmin", |
||||
"lock_debug_relid", |
||||
"lock_read_priority", /* lock priority, see lock.c */ |
||||
"deadlock_timeout", /* deadlock timeout, see proc.c */ |
||||
"nofsync", /* turn fsync off */ |
||||
"syslog", /* use syslog for error messages */ |
||||
"hostlookup", /* enable hostname lookup in ps_status */ |
||||
"showportnumber", /* show port number in ps_status */ |
||||
|
||||
/* NUM_PG_OPTIONS *//* must be the last item of enum */ |
||||
}; |
||||
|
||||
/*
|
||||
* Array of trace flags which can be set or reset independently. |
||||
*/ |
||||
int pg_options[NUM_PG_OPTIONS] = {0}; |
||||
|
||||
/*
|
||||
* Print a timestamp and a message to stdout if the trace flag |
||||
* indexed by the flag value is set. |
||||
*/ |
||||
int |
||||
tprintf(int flag, const char *fmt,...) |
||||
{ |
||||
va_list ap; |
||||
char line[TRACEMSG_MAXLEN + TIMESTAMP_SIZE + 1]; |
||||
|
||||
#ifdef USE_SYSLOG |
||||
int log_level; |
||||
|
||||
#endif |
||||
|
||||
if ((flag == TRACE_ALL) || (pg_options[TRACE_ALL] > 0)) |
||||
{ |
||||
/* unconditional trace or trace all option set */ |
||||
} |
||||
else if (pg_options[TRACE_ALL] == 0) |
||||
{ |
||||
if ((flag < 0) || (flag >= NUM_PG_OPTIONS) || (!pg_options[flag])) |
||||
return 0; |
||||
} |
||||
else if (pg_options[TRACE_ALL] < 0) |
||||
return 0; |
||||
|
||||
#ifdef ELOG_TIMESTAMPS |
||||
strcpy(line, tprintf_timestamp()); |
||||
#endif |
||||
va_start(ap, fmt); |
||||
vsnprintf(line + TIMESTAMP_SIZE, TRACEMSG_MAXLEN, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
#ifdef USE_SYSLOG |
||||
log_level = ((flag == TRACE_ALL) ? LOG_INFO : LOG_DEBUG); |
||||
write_syslog(log_level, line + TIMESTAMP_SIZE); |
||||
#endif |
||||
|
||||
if (UseSyslog <= 1) |
||||
{ |
||||
puts(line); |
||||
fflush(stdout); |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
/*
|
||||
* Print a timestamp and a message to stdout or to syslog. |
||||
*/ |
||||
#ifdef NOT_USED |
||||
int |
||||
tprintf1(const char *fmt,...) |
||||
{ |
||||
va_list ap; |
||||
char line[TRACEMSG_MAXLEN + TIMESTAMP_SIZE + 1]; |
||||
|
||||
#ifdef ELOG_TIMESTAMPS |
||||
strcpy(line, tprintf_timestamp()); |
||||
#endif |
||||
va_start(ap, fmt); |
||||
vsnprintf(line + TIMESTAMP_SIZE, TRACEMSG_MAXLEN, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
#ifdef USE_SYSLOG |
||||
write_syslog(LOG_INFO, line + TIMESTAMP_SIZE); |
||||
#endif |
||||
|
||||
if (UseSyslog <= 1) |
||||
{ |
||||
puts(line); |
||||
fflush(stdout); |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
/*
|
||||
* Print a timestamp and a message to stderr. |
||||
*/ |
||||
int |
||||
eprintf(const char *fmt,...) |
||||
{ |
||||
va_list ap; |
||||
char line[TRACEMSG_MAXLEN + TIMESTAMP_SIZE + 1]; |
||||
|
||||
#ifdef ELOG_TIMESTAMPS |
||||
strcpy(line, tprintf_timestamp()); |
||||
#endif |
||||
va_start(ap, fmt); |
||||
vsnprintf(line + TIMESTAMP_SIZE, TRACEMSG_MAXLEN, fmt, ap); |
||||
va_end(ap); |
||||
|
||||
#ifdef USE_SYSLOG |
||||
write_syslog(LOG_ERR, line + TIMESTAMP_SIZE); |
||||
#endif |
||||
|
||||
if (UseSyslog <= 1) |
||||
{ |
||||
fputs(line, stderr); |
||||
fputc('\n', stderr); |
||||
fflush(stderr); |
||||
} |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
#ifdef USE_SYSLOG |
||||
/*
|
||||
* Write a message line to syslog if the syslog option is set. |
||||
*/ |
||||
void |
||||
write_syslog(int level, char *line) |
||||
{ |
||||
#ifndef PG_SYSLOG_LIMIT |
||||
#define PG_SYSLOG_LIMIT 128 |
||||
#endif /* PG_SYSLOG_LIMIT */ |
||||
|
||||
static int openlog_done = 0; |
||||
static char buf[PG_SYSLOG_LIMIT+1]; |
||||
static int logid = 0; |
||||
|
||||
if (UseSyslog >= 1) |
||||
{ |
||||
int len = strlen(line); |
||||
int buflen; |
||||
int seq = 0; |
||||
int l; |
||||
int i; |
||||
|
||||
if (!openlog_done) |
||||
{ |
||||
openlog_done = 1; |
||||
openlog(PG_LOG_IDENT, LOG_PID | LOG_NDELAY, PG_LOG_FACILITY); |
||||
} |
||||
|
||||
/* divide into multiple syslog() calls if message is
|
||||
* too long |
||||
*/ |
||||
if (len > PG_SYSLOG_LIMIT) |
||||
{ |
||||
logid++; |
||||
|
||||
while (len > 0) |
||||
{ |
||||
strncpy(buf, line, PG_SYSLOG_LIMIT); |
||||
buf[PG_SYSLOG_LIMIT] = '\0'; |
||||
|
||||
l = strlen(buf); |
||||
#ifdef MULTIBYTE |
||||
/* trim to multibyte letter boundary */
|
||||
buflen = pg_mbcliplen(buf, l, l); |
||||
buf[buflen] = '\0'; |
||||
l = strlen(buf); |
||||
#endif |
||||
/* already word boundary? */ |
||||
if (isspace(line[l]) || line[l] == '\0') |
||||
{ |
||||
buflen = l; |
||||
} |
||||
else |
||||
{ |
||||
/* try to divide in word boundary */ |
||||
i = l - 1; |
||||
while(i > 0 && !isspace(buf[i])) |
||||
{ |
||||
i--; |
||||
} |
||||
if (i <= 0) /* couldn't divide word boundary */ |
||||
{ |
||||
buflen = l; |
||||
} |
||||
else |
||||
{ |
||||
buflen = i; |
||||
buf[i] = '\0'; |
||||
} |
||||
} |
||||
|
||||
seq++; |
||||
/*
|
||||
* Here we actually call syslog(). |
||||
* For segmented messages, we add logid |
||||
* (incremented at each write_syslog call), |
||||
* and seq (incremented at each syslog call |
||||
* within a write_syslog call). |
||||
* This will prevent syslog to surpress |
||||
* "same" messages... |
||||
*/ |
||||
syslog(level, "[%d-%d] %s", logid, seq, buf); |
||||
line += buflen; |
||||
len -= buflen; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
syslog(level, "%s", line); |
||||
} |
||||
} |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#ifdef ELOG_TIMESTAMPS |
||||
/*
|
||||
* Return a timestamp string like "980119.17:25:59.902 [21974] " |
||||
*/ |
||||
char * |
||||
tprintf_timestamp() |
||||
{ |
||||
struct timeval tv; |
||||
struct timezone tz = {0, 0}; |
||||
struct tm *time; |
||||
time_t tm; |
||||
static char timestamp[32], |
||||
pid[8]; |
||||
|
||||
gettimeofday(&tv, &tz); |
||||
tm = tv.tv_sec; |
||||
time = localtime(&tm); |
||||
|
||||
sprintf(pid, "[%d]", MyProcPid); |
||||
sprintf(timestamp, "%02d%02d%02d.%02d:%02d:%02d.%03d %7s ", |
||||
time->tm_year % 100, time->tm_mon + 1, time->tm_mday, |
||||
time->tm_hour, time->tm_min, time->tm_sec, |
||||
(int) (tv.tv_usec / 1000), pid); |
||||
|
||||
return timestamp; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#ifdef NOT_USED |
||||
static int |
||||
option_flag(int flag) |
||||
{ |
||||
if ((flag < 0) || (flag >= NUM_PG_OPTIONS)) |
||||
return 0; |
||||
return pg_options[flag]; |
||||
} |
||||
|
||||
int |
||||
set_option_flag(int flag, int value) |
||||
{ |
||||
if ((flag < 0) || (flag >= NUM_PG_OPTIONS)) |
||||
return -1; |
||||
|
||||
pg_options[flag] = value; |
||||
return value; |
||||
} |
||||
|
||||
#endif |
||||
|
||||
/*
|
||||
* Parse an option string like "name,name+,name-,name=value". |
||||
* Single options are delimited by ',',space,tab,newline or cr. |
||||
* |
||||
* If 'secure' is false, the option string came from a remote client via |
||||
* connection "debug options" field --- do not obey any requests that |
||||
* might potentially be security loopholes. |
||||
*/ |
||||
void |
||||
parse_options(char *str, bool secure) |
||||
{ |
||||
char *s, |
||||
*name; |
||||
int i, |
||||
len, |
||||
val, |
||||
is_comment; |
||||
|
||||
Assert((sizeof(opt_names) / sizeof(char *)) == NUM_PG_OPTIONS); |
||||
|
||||
str = strdup(str); |
||||
for (s = str; *s;) |
||||
{ |
||||
is_comment = 0; |
||||
name = s; |
||||
val = 1; |
||||
for (; *s; s++) |
||||
{ |
||||
switch (*s) |
||||
{ |
||||
case '#': |
||||
is_comment = 1; |
||||
break; |
||||
case '=': |
||||
*s++ = '\0'; |
||||
val = strtol(s, &s, 10); |
||||
goto setval; |
||||
case '-': |
||||
*s++ = '\0'; |
||||
val = 0; |
||||
goto setval; |
||||
case '+': |
||||
*s++ = '\0'; |
||||
val = 1; |
||||
goto setval; |
||||
case ' ': |
||||
case ',': |
||||
case '\t': |
||||
case '\n': |
||||
case '\r': |
||||
*s = ','; |
||||
val = 1; |
||||
goto setval; |
||||
} |
||||
} |
||||
setval: |
||||
for (; *s; s++) |
||||
{ |
||||
if (*s == ',') |
||||
{ |
||||
*s++ = '\0'; |
||||
break; |
||||
} |
||||
} |
||||
len = strlen(name); |
||||
if (len == 0) |
||||
continue; |
||||
for (i = 0; i < NUM_PG_OPTIONS; i++) |
||||
{ |
||||
if (strncmp(name, opt_names[i], len) == 0) |
||||
{ |
||||
pg_options[i] = val; |
||||
break; |
||||
} |
||||
} |
||||
if (!is_comment && (i >= NUM_PG_OPTIONS)) |
||||
fprintf(stderr, "invalid option: %s\n", name); |
||||
} |
||||
free(str); |
||||
} |
||||
|
||||
#define BUF_SIZE 4096 |
||||
|
||||
void |
||||
read_pg_options(SIGNAL_ARGS) |
||||
{ |
||||
int fd; |
||||
int n; |
||||
int verbose; |
||||
char buffer[BUF_SIZE]; |
||||
char c; |
||||
char *s, |
||||
*p; |
||||
|
||||
if (!DataDir) |
||||
{ |
||||
fprintf(stderr, "read_pg_options: DataDir not defined\n"); |
||||
return; |
||||
} |
||||
|
||||
snprintf(buffer, BUF_SIZE - 1, "%s/%s", DataDir, "pg_options"); |
||||
#ifndef __CYGWIN32__ |
||||
if ((fd = open(buffer, O_RDONLY)) < 0) |
||||
#else |
||||
if ((fd = open(buffer, O_RDONLY | O_BINARY)) < 0) |
||||
#endif |
||||
return; |
||||
|
||||
if ((n = read(fd, buffer, BUF_SIZE - 1)) > 0) |
||||
{ |
||||
/* collpse buffer in place removing comments and spaces */ |
||||
for (s = buffer, p = buffer, c = '\0'; s < (buffer + n);) |
||||
{ |
||||
switch (*s) |
||||
{ |
||||
case '#': |
||||
while ((s < (buffer + n)) && (*s++ != '\n')); |
||||
break; |
||||
case ' ': |
||||
case '\t': |
||||
case '\n': |
||||
case '\r': |
||||
if (c != ',') |
||||
c = *p++ = ','; |
||||
s++; |
||||
break; |
||||
default: |
||||
c = *p++ = *s++; |
||||
break; |
||||
} |
||||
} |
||||
if (c == ',') |
||||
p--; |
||||
*p = '\0'; |
||||
verbose = pg_options[TRACE_VERBOSE]; |
||||
parse_options(buffer, true); |
||||
verbose |= pg_options[TRACE_VERBOSE]; |
||||
if (verbose || postgres_signal_arg == SIGHUP) |
||||
tprintf(TRACE_ALL, "read_pg_options: %s", buffer); |
||||
} |
||||
|
||||
close(fd); |
||||
} |
||||
|
||||
void |
||||
show_options(void) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i < NUM_PG_OPTIONS; i++) |
||||
elog(NOTICE, "%s=%d", opt_names[i], pg_options[i]); |
||||
} |
||||
|
||||
/*
|
||||
* Local variables: |
||||
* tab-width: 4 |
||||
* c-indent-level: 4 |
||||
* c-basic-offset: 4 |
||||
* End: |
||||
*/ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,47 @@ |
||||
/*
|
||||
* guc.h |
||||
* |
||||
* External declarations pertaining to backend/utils/misc/guc.c and |
||||
* backend/utils/misc/guc-file.l |
||||
* |
||||
* $Header: /cvsroot/pgsql/src/include/utils/guc.h,v 1.1 2000/05/31 00:28:40 petere Exp $ |
||||
*/ |
||||
#ifndef GUC_H |
||||
#define GUC_H |
||||
|
||||
#include "postgres.h" |
||||
|
||||
/*
|
||||
* This is sort of a permission list. Those contexts with a higher |
||||
* number can also be set via the lower numbered ways. |
||||
*/ |
||||
typedef enum { |
||||
PGC_POSTMASTER = 1, /* static postmaster option */ |
||||
PGC_BACKEND = 2, /* per backend startup option */ |
||||
PGC_SIGHUP = 4, /* can change this option via SIGHUP */ |
||||
PGC_SUSET = 8, /* can change this option via SET if superuser */ |
||||
PGC_USERSET = 16, /* everyone can change this option via SET */ |
||||
} GucContext; |
||||
|
||||
|
||||
void SetConfigOption(const char * name, const char * value, GucContext context); |
||||
const char * GetConfigOption(const char * name, bool issuper); |
||||
void ProcessConfigFile(GucContext context); |
||||
void ResetAllOptions(void); |
||||
|
||||
bool set_config_option(const char * name, const char * value, GucContext context, bool DoIt); |
||||
|
||||
|
||||
extern bool Debug_print_query; |
||||
extern bool Debug_print_plan; |
||||
extern bool Debug_print_parse; |
||||
extern bool Debug_print_rewritten; |
||||
extern bool Debug_pretty_print; |
||||
|
||||
extern bool Show_parser_stats; |
||||
extern bool Show_planner_stats; |
||||
extern bool Show_executor_stats; |
||||
extern bool Show_query_stats; |
||||
extern bool Show_btree_build_stats; |
||||
|
||||
#endif /*GUC_H*/ |
@ -1,91 +0,0 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* trace.h |
||||
* |
||||
* Conditional trace definitions. |
||||
* |
||||
* Massimo Dal Zotto <dz@cs.unitn.it> |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#ifndef TRACE_H |
||||
#define TRACE_H |
||||
|
||||
#include <string.h> |
||||
#include <time.h> |
||||
|
||||
#ifdef ELOG_TIMESTAMPS |
||||
char *tprintf_timestamp(void); |
||||
|
||||
#define TIMESTAMP_SIZE 28 |
||||
#else |
||||
#define TIMESTAMP_SIZE 0 |
||||
#endif |
||||
|
||||
extern int tprintf(int flag, const char *fmt,...); |
||||
extern int eprintf(const char *fmt,...); |
||||
extern void write_syslog(int level, char *line); |
||||
extern void show_options(void); |
||||
extern void parse_options(char *str, bool secure); |
||||
extern void read_pg_options(SIGNAL_ARGS); |
||||
|
||||
/*
|
||||
* Trace options, used as index into pg_options. |
||||
* Must match the constants in pg_options[]. |
||||
*/ |
||||
enum pg_option_enum |
||||
{ |
||||
TRACE_ALL, /* 0=trace some, 1=trace all, -1=trace
|
||||
* none */ |
||||
TRACE_VERBOSE, |
||||
TRACE_QUERY, |
||||
TRACE_PLAN, |
||||
TRACE_PARSE, |
||||
TRACE_REWRITTEN, |
||||
TRACE_PRETTY_PLAN, /* indented multiline versions of trees */ |
||||
TRACE_PRETTY_PARSE, |
||||
TRACE_PRETTY_REWRITTEN, |
||||
TRACE_PARSERSTATS, |
||||
TRACE_PLANNERSTATS, |
||||
TRACE_EXECUTORSTATS, |
||||
TRACE_SHORTLOCKS, /* currently unused but needed, see lock.c */ |
||||
TRACE_LOCKS, |
||||
TRACE_USERLOCKS, |
||||
TRACE_SPINLOCKS, |
||||
TRACE_NOTIFY, |
||||
TRACE_MALLOC, |
||||
TRACE_PALLOC, |
||||
TRACE_LOCKOIDMIN, |
||||
TRACE_LOCKRELATION, |
||||
OPT_LOCKREADPRIORITY, /* lock priority, see lock.c */ |
||||
OPT_DEADLOCKTIMEOUT, /* deadlock timeout, see proc.c */ |
||||
OPT_NOFSYNC, /* turn fsync off */ |
||||
OPT_SYSLOG, /* use syslog for error messages */ |
||||
OPT_HOSTLOOKUP, /* enable hostname lookup in ps_status */ |
||||
OPT_SHOWPORTNUMBER, /* show port number in ps_status */ |
||||
|
||||
NUM_PG_OPTIONS /* must be the last item of enum */ |
||||
}; |
||||
|
||||
extern int pg_options[NUM_PG_OPTIONS]; |
||||
|
||||
#ifdef __GNUC__ |
||||
#define PRINTF(args...) tprintf1(args) |
||||
#define EPRINTF(args...) eprintf(args) |
||||
#define TPRINTF(flag, args...) tprintf(flag, args) |
||||
#else |
||||
#define PRINTF tprintf1 |
||||
#define EPRINTF eprintf |
||||
#define TPRINTF tprintf |
||||
#endif |
||||
|
||||
#endif /* TRACE_H */ |
||||
|
||||
/*
|
||||
* Local variables: |
||||
* tab-width: 4 |
||||
* c-indent-level: 4 |
||||
* c-basic-offset: 4 |
||||
* End: |
||||
*/ |
Loading…
Reference in new issue