The heralded `Grand Unified Configuration scheme' (GUC)
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)
This commit is contained in:
parent
5e4d554bae
commit
6a68f42648
@ -34,7 +34,7 @@
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.51 2000/05/30 16:36:14 momjian Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/Makefile,v 1.52 2000/05/31 00:28:13 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -205,9 +205,7 @@ endif
|
||||
install-templates: $(TEMPLATEDIR) \
|
||||
global1.bki.source local1_template1.bki.source \
|
||||
global1.description local1_template1.description \
|
||||
libpq/pg_hba.conf.sample libpq/pg_ident.conf.sample \
|
||||
optimizer/geqo/pg_geqo.sample \
|
||||
pg_options.sample
|
||||
libpq/pg_hba.conf.sample libpq/pg_ident.conf.sample
|
||||
$(INSTALL) $(INSTLOPTS) global1.bki.source \
|
||||
$(TEMPLATEDIR)/global1.bki.source
|
||||
$(INSTALL) $(INSTLOPTS) global1.description \
|
||||
@ -220,10 +218,6 @@ install-templates: $(TEMPLATEDIR) \
|
||||
$(TEMPLATEDIR)/pg_hba.conf.sample
|
||||
$(INSTALL) $(INSTLOPTS) libpq/pg_ident.conf.sample \
|
||||
$(TEMPLATEDIR)/pg_ident.conf.sample
|
||||
$(INSTALL) $(INSTLOPTS) optimizer/geqo/pg_geqo.sample \
|
||||
$(TEMPLATEDIR)/pg_geqo.sample
|
||||
$(INSTALL) $(INSTLOPTS) pg_options.sample \
|
||||
$(TEMPLATEDIR)/pg_options.sample
|
||||
|
||||
install-headers: prebuildheaders $(SRCDIR)/include/config.h
|
||||
-@if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.54 2000/04/12 17:14:49 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.55 2000/05/31 00:28:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,11 +25,8 @@
|
||||
#include "catalog/index.h"
|
||||
#include "executor/executor.h"
|
||||
#include "miscadmin.h"
|
||||
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
#define ShowExecutorStats pg_options[TRACE_EXECUTORSTATS]
|
||||
#endif
|
||||
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/guc.h"
|
||||
|
||||
bool BuildingBtree = false; /* see comment in btbuild() */
|
||||
bool FastBuild = true; /* use sort/build instead of insertion
|
||||
@ -96,9 +93,9 @@ btbuild(Relation heap,
|
||||
usefast = (FastBuild && IsNormalProcessingMode());
|
||||
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
if (ShowExecutorStats)
|
||||
if (Show_btree_build_stats)
|
||||
ResetUsage();
|
||||
#endif
|
||||
#endif /* BTREE_BUILD_STATS */
|
||||
|
||||
/* see if index is unique */
|
||||
isunique = IndexIsUniqueNoCache(RelationGetRelid(index));
|
||||
@ -287,13 +284,13 @@ btbuild(Relation heap,
|
||||
}
|
||||
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
if (ShowExecutorStats)
|
||||
if (Show_btree_build_stats)
|
||||
{
|
||||
fprintf(stderr, "! BtreeBuild Stats:\n");
|
||||
fprintf(stderr, "BTREE BUILD STATS\n");
|
||||
ShowUsage();
|
||||
ResetUsage();
|
||||
}
|
||||
#endif
|
||||
#endif /* BTREE_BUILD_STATS */
|
||||
|
||||
/*
|
||||
* Since we just counted the tuples in the heap, we update its stats
|
||||
|
@ -28,7 +28,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.52 2000/04/12 17:14:49 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.53 2000/05/31 00:28:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -36,13 +36,11 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/nbtree.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/tuplesort.h"
|
||||
|
||||
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
#define ShowExecutorStats pg_options[TRACE_EXECUTORSTATS]
|
||||
#endif
|
||||
|
||||
/*
|
||||
* turn on debugging output.
|
||||
*
|
||||
@ -136,13 +134,13 @@ void
|
||||
_bt_leafbuild(BTSpool *btspool)
|
||||
{
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
if (ShowExecutorStats)
|
||||
if (Show_btree_build_stats)
|
||||
{
|
||||
fprintf(stderr, "! BtreeBuild (Spool) Stats:\n");
|
||||
fprintf(StatFp, "BTREE BUILD (Spool) STATISTICS\n");
|
||||
ShowUsage();
|
||||
ResetUsage();
|
||||
}
|
||||
#endif
|
||||
#endif /* BTREE_BUILD_STATS */
|
||||
tuplesort_performsort(btspool->sortstate);
|
||||
|
||||
_bt_load(btspool->index, btspool);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.83 2000/05/30 04:24:35 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.84 2000/05/31 00:28:14 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -267,7 +267,7 @@ BootstrapMain(int argc, char *argv[])
|
||||
Noversion = true;
|
||||
break;
|
||||
case 'F':
|
||||
disableFsync = true;
|
||||
enableFsync = false;
|
||||
break;
|
||||
case 'Q':
|
||||
Quiet = true;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.61 2000/05/28 17:55:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.62 2000/05/31 00:28:15 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -90,7 +90,7 @@
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
|
||||
/* stuff that we really ought not be touching directly :-( */
|
||||
extern TransactionState CurrentTransactionState;
|
||||
@ -128,6 +128,8 @@ static void NotifyMyFrontEnd(char *relname, int32 listenerPID);
|
||||
static int AsyncExistsPendingNotify(char *relname);
|
||||
static void ClearPendingNotifies(void);
|
||||
|
||||
bool Trace_notify = false;
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------
|
||||
@ -149,7 +151,8 @@ Async_Notify(char *relname)
|
||||
{
|
||||
char *notifyName;
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "Async_Notify: %s", relname);
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "Async_Notify: %s", relname);
|
||||
|
||||
if (!pendingNotifies)
|
||||
pendingNotifies = DLNewList();
|
||||
@ -202,7 +205,8 @@ Async_Listen(char *relname, int pid)
|
||||
int alreadyListener = 0;
|
||||
TupleDesc tupDesc;
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "Async_Listen: %s", relname);
|
||||
|
||||
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
@ -304,7 +308,8 @@ Async_Unlisten(char *relname, int pid)
|
||||
return;
|
||||
}
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "Async_Unlisten %s", relname);
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "Async_Unlisten %s", relname);
|
||||
|
||||
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
|
||||
/* Note we assume there can be only one matching tuple. */
|
||||
@ -346,7 +351,8 @@ Async_UnlistenAll()
|
||||
HeapTuple lTuple;
|
||||
ScanKeyData key[1];
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "Async_UnlistenAll");
|
||||
|
||||
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
@ -452,7 +458,8 @@ AtCommit_Notify()
|
||||
return;
|
||||
}
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "AtCommit_Notify");
|
||||
|
||||
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
|
||||
tdesc = RelationGetDescr(lRel);
|
||||
@ -485,13 +492,16 @@ AtCommit_Notify()
|
||||
* be bad for applications that ignore self-notify
|
||||
* messages.
|
||||
*/
|
||||
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify: notifying self");
|
||||
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "AtCommit_Notify: notifying self");
|
||||
|
||||
NotifyMyFrontEnd(relname, listenerPID);
|
||||
}
|
||||
else
|
||||
{
|
||||
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify: notifying pid %d",
|
||||
listenerPID);
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "AtCommit_Notify: notifying pid %d", listenerPID);
|
||||
|
||||
/*
|
||||
* If someone has already notified this listener, we don't
|
||||
@ -551,7 +561,8 @@ AtCommit_Notify()
|
||||
|
||||
ClearPendingNotifies();
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify: done");
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "AtCommit_Notify: done");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -624,10 +635,13 @@ Async_NotifyHandler(SIGNAL_ARGS)
|
||||
if (notifyInterruptOccurred)
|
||||
{
|
||||
/* Here, it is finally safe to do stuff. */
|
||||
TPRINTF(TRACE_NOTIFY,
|
||||
"Async_NotifyHandler: perform async notify");
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "Async_NotifyHandler: perform async notify");
|
||||
|
||||
ProcessIncomingNotify();
|
||||
TPRINTF(TRACE_NOTIFY, "Async_NotifyHandler: done");
|
||||
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "Async_NotifyHandler: done");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -693,10 +707,13 @@ EnableNotifyInterrupt(void)
|
||||
notifyInterruptEnabled = 0;
|
||||
if (notifyInterruptOccurred)
|
||||
{
|
||||
TPRINTF(TRACE_NOTIFY,
|
||||
"EnableNotifyInterrupt: perform async notify");
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "EnableNotifyInterrupt: perform async notify");
|
||||
|
||||
ProcessIncomingNotify();
|
||||
TPRINTF(TRACE_NOTIFY, "EnableNotifyInterrupt: done");
|
||||
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "EnableNotifyInterrupt: done");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -751,7 +768,9 @@ ProcessIncomingNotify(void)
|
||||
char *relname;
|
||||
int32 sourcePID;
|
||||
|
||||
TPRINTF(TRACE_NOTIFY, "ProcessIncomingNotify");
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "ProcessIncomingNotify");
|
||||
|
||||
PS_SET_STATUS("async_notify");
|
||||
|
||||
notifyInterruptOccurred = 0;
|
||||
@ -784,8 +803,11 @@ ProcessIncomingNotify(void)
|
||||
d = heap_getattr(lTuple, Anum_pg_listener_relname, tdesc, &isnull);
|
||||
relname = (char *) DatumGetPointer(d);
|
||||
/* Notify the frontend */
|
||||
TPRINTF(TRACE_NOTIFY, "ProcessIncomingNotify: received %s from %d",
|
||||
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "ProcessIncomingNotify: received %s from %d",
|
||||
relname, (int) sourcePID);
|
||||
|
||||
NotifyMyFrontEnd(relname, sourcePID);
|
||||
/* Rewrite the tuple with 0 in notification column */
|
||||
rTuple = heap_modifytuple(lTuple, lRel, value, nulls, repl);
|
||||
@ -820,7 +842,9 @@ ProcessIncomingNotify(void)
|
||||
pq_flush();
|
||||
|
||||
PS_SET_STATUS("idle");
|
||||
TPRINTF(TRACE_NOTIFY, "ProcessIncomingNotify: done");
|
||||
|
||||
if (Trace_notify)
|
||||
elog(DEBUG, "ProcessIncomingNotify: done");
|
||||
}
|
||||
|
||||
/* Send NOTIFY message to my front end. */
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.34 2000/04/12 17:15:00 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.35 2000/05/31 00:28:15 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,17 +27,14 @@
|
||||
#include "optimizer/paths.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
#include "utils/tqual.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
#include "mb/pg_wchar.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* XXX should be in a header file */
|
||||
extern bool _use_keyset_query_optimizer;
|
||||
|
||||
|
||||
static bool show_date(void);
|
||||
static bool reset_date(void);
|
||||
@ -45,51 +42,7 @@ static bool parse_date(char *);
|
||||
static bool show_timezone(void);
|
||||
static bool reset_timezone(void);
|
||||
static bool parse_timezone(char *);
|
||||
static bool show_effective_cache_size(void);
|
||||
static bool reset_effective_cache_size(void);
|
||||
static bool parse_effective_cache_size(char *);
|
||||
static bool show_random_page_cost(void);
|
||||
static bool reset_random_page_cost(void);
|
||||
static bool parse_random_page_cost(char *);
|
||||
static bool show_cpu_tuple_cost(void);
|
||||
static bool reset_cpu_tuple_cost(void);
|
||||
static bool parse_cpu_tuple_cost(char *);
|
||||
static bool show_cpu_index_tuple_cost(void);
|
||||
static bool reset_cpu_index_tuple_cost(void);
|
||||
static bool parse_cpu_index_tuple_cost(char *);
|
||||
static bool show_cpu_operator_cost(void);
|
||||
static bool reset_cpu_operator_cost(void);
|
||||
static bool parse_cpu_operator_cost(char *);
|
||||
static bool reset_enable_seqscan(void);
|
||||
static bool show_enable_seqscan(void);
|
||||
static bool parse_enable_seqscan(char *);
|
||||
static bool reset_enable_indexscan(void);
|
||||
static bool show_enable_indexscan(void);
|
||||
static bool parse_enable_indexscan(char *);
|
||||
static bool reset_enable_tidscan(void);
|
||||
static bool show_enable_tidscan(void);
|
||||
static bool parse_enable_tidscan(char *);
|
||||
static bool reset_enable_sort(void);
|
||||
static bool show_enable_sort(void);
|
||||
static bool parse_enable_sort(char *);
|
||||
static bool reset_enable_nestloop(void);
|
||||
static bool show_enable_nestloop(void);
|
||||
static bool parse_enable_nestloop(char *);
|
||||
static bool reset_enable_mergejoin(void);
|
||||
static bool show_enable_mergejoin(void);
|
||||
static bool parse_enable_mergejoin(char *);
|
||||
static bool reset_enable_hashjoin(void);
|
||||
static bool show_enable_hashjoin(void);
|
||||
static bool parse_enable_hashjoin(char *);
|
||||
static bool reset_geqo(void);
|
||||
static bool show_geqo(void);
|
||||
static bool parse_geqo(char *);
|
||||
static bool show_ksqo(void);
|
||||
static bool reset_ksqo(void);
|
||||
static bool parse_ksqo(char *);
|
||||
static bool reset_max_expr_depth(void);
|
||||
static bool show_max_expr_depth(void);
|
||||
static bool parse_max_expr_depth(char *);
|
||||
|
||||
static bool show_XactIsoLevel(void);
|
||||
static bool reset_XactIsoLevel(void);
|
||||
static bool parse_XactIsoLevel(char *);
|
||||
@ -97,6 +50,7 @@ static bool parse_random_seed(char *);
|
||||
static bool show_random_seed(void);
|
||||
static bool reset_random_seed(void);
|
||||
|
||||
|
||||
/*
|
||||
* get_token
|
||||
* Obtain the next item in a comma-separated list of items,
|
||||
@ -210,447 +164,6 @@ get_token(char **tok, char **val, char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic parse routine for boolean ON/OFF variables
|
||||
*/
|
||||
static bool
|
||||
parse_boolean_var(char *value,
|
||||
bool *variable, const char *varname, bool defaultval)
|
||||
{
|
||||
if (value == NULL)
|
||||
{
|
||||
*variable = defaultval;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (strcasecmp(value, "on") == 0)
|
||||
*variable = true;
|
||||
else if (strcasecmp(value, "off") == 0)
|
||||
*variable = false;
|
||||
else
|
||||
elog(ERROR, "Bad value for %s (%s)", varname, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_SEQSCAN
|
||||
*/
|
||||
static bool
|
||||
parse_enable_seqscan(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_seqscan,
|
||||
"ENABLE_SEQSCAN", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_seqscan()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_SEQSCAN is %s",
|
||||
enable_seqscan ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_seqscan()
|
||||
{
|
||||
enable_seqscan = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_INDEXSCAN
|
||||
*/
|
||||
static bool
|
||||
parse_enable_indexscan(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_indexscan,
|
||||
"ENABLE_INDEXSCAN", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_indexscan()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_INDEXSCAN is %s",
|
||||
enable_indexscan ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_indexscan()
|
||||
{
|
||||
enable_indexscan = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_TIDSCAN
|
||||
*/
|
||||
static bool
|
||||
parse_enable_tidscan(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_tidscan,
|
||||
"ENABLE_TIDSCAN", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_tidscan()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_TIDSCAN is %s",
|
||||
enable_tidscan ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_tidscan()
|
||||
{
|
||||
enable_tidscan = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_SORT
|
||||
*/
|
||||
static bool
|
||||
parse_enable_sort(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_sort,
|
||||
"ENABLE_SORT", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_sort()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_SORT is %s",
|
||||
enable_sort ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_sort()
|
||||
{
|
||||
enable_sort = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_NESTLOOP
|
||||
*/
|
||||
static bool
|
||||
parse_enable_nestloop(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_nestloop,
|
||||
"ENABLE_NESTLOOP", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_nestloop()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_NESTLOOP is %s",
|
||||
enable_nestloop ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_nestloop()
|
||||
{
|
||||
enable_nestloop = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_MERGEJOIN
|
||||
*/
|
||||
static bool
|
||||
parse_enable_mergejoin(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_mergejoin,
|
||||
"ENABLE_MERGEJOIN", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_mergejoin()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_MERGEJOIN is %s",
|
||||
enable_mergejoin ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_mergejoin()
|
||||
{
|
||||
enable_mergejoin = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENABLE_HASHJOIN
|
||||
*/
|
||||
static bool
|
||||
parse_enable_hashjoin(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &enable_hashjoin,
|
||||
"ENABLE_HASHJOIN", true);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_enable_hashjoin()
|
||||
{
|
||||
elog(NOTICE, "ENABLE_HASHJOIN is %s",
|
||||
enable_hashjoin ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_enable_hashjoin()
|
||||
{
|
||||
enable_hashjoin = true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* GEQO
|
||||
*
|
||||
*/
|
||||
static bool
|
||||
parse_geqo(char *value)
|
||||
{
|
||||
char *tok,
|
||||
*val,
|
||||
*rest;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_geqo();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rest = get_token(&tok, &val, value);
|
||||
|
||||
/* expect one and only one item */
|
||||
if (tok == NULL)
|
||||
elog(ERROR, "Value undefined");
|
||||
if (rest && *rest != '\0')
|
||||
elog(ERROR, "Unable to parse '%s'", rest);
|
||||
|
||||
if (strcasecmp(tok, "on") == 0)
|
||||
{
|
||||
int new_geqo_rels = GEQO_RELS;
|
||||
|
||||
if (val != NULL)
|
||||
{
|
||||
new_geqo_rels = pg_atoi(val, sizeof(int), '\0');
|
||||
if (new_geqo_rels <= 1)
|
||||
elog(ERROR, "Bad value for # of relations (%s)", val);
|
||||
}
|
||||
enable_geqo = true;
|
||||
geqo_rels = new_geqo_rels;
|
||||
}
|
||||
else if (strcasecmp(tok, "off") == 0)
|
||||
{
|
||||
if (val != NULL)
|
||||
elog(ERROR, "%s does not allow a parameter", tok);
|
||||
enable_geqo = false;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "Bad value for GEQO (%s)", value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_geqo()
|
||||
{
|
||||
if (enable_geqo)
|
||||
elog(NOTICE, "GEQO is ON beginning with %d relations", geqo_rels);
|
||||
else
|
||||
elog(NOTICE, "GEQO is OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_geqo(void)
|
||||
{
|
||||
#ifdef GEQO
|
||||
enable_geqo = true;
|
||||
#else
|
||||
enable_geqo = false;
|
||||
#endif
|
||||
geqo_rels = GEQO_RELS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* EFFECTIVE_CACHE_SIZE
|
||||
*/
|
||||
static bool
|
||||
parse_effective_cache_size(char *value)
|
||||
{
|
||||
float64 res;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_effective_cache_size();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = float8in((char *) value);
|
||||
effective_cache_size = *res;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_effective_cache_size()
|
||||
{
|
||||
elog(NOTICE, "EFFECTIVE_CACHE_SIZE is %g (%dK pages)",
|
||||
effective_cache_size, BLCKSZ / 1024);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_effective_cache_size()
|
||||
{
|
||||
effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* RANDOM_PAGE_COST
|
||||
*/
|
||||
static bool
|
||||
parse_random_page_cost(char *value)
|
||||
{
|
||||
float64 res;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_random_page_cost();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = float8in((char *) value);
|
||||
random_page_cost = *res;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_random_page_cost()
|
||||
{
|
||||
elog(NOTICE, "RANDOM_PAGE_COST is %g", random_page_cost);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_random_page_cost()
|
||||
{
|
||||
random_page_cost = DEFAULT_RANDOM_PAGE_COST;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU_TUPLE_COST
|
||||
*/
|
||||
static bool
|
||||
parse_cpu_tuple_cost(char *value)
|
||||
{
|
||||
float64 res;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_cpu_tuple_cost();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = float8in((char *) value);
|
||||
cpu_tuple_cost = *res;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_cpu_tuple_cost()
|
||||
{
|
||||
elog(NOTICE, "CPU_TUPLE_COST is %g", cpu_tuple_cost);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_cpu_tuple_cost()
|
||||
{
|
||||
cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU_INDEX_TUPLE_COST
|
||||
*/
|
||||
static bool
|
||||
parse_cpu_index_tuple_cost(char *value)
|
||||
{
|
||||
float64 res;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_cpu_index_tuple_cost();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = float8in((char *) value);
|
||||
cpu_index_tuple_cost = *res;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_cpu_index_tuple_cost()
|
||||
{
|
||||
elog(NOTICE, "CPU_INDEX_TUPLE_COST is %g", cpu_index_tuple_cost);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_cpu_index_tuple_cost()
|
||||
{
|
||||
cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* CPU_OPERATOR_COST
|
||||
*/
|
||||
static bool
|
||||
parse_cpu_operator_cost(char *value)
|
||||
{
|
||||
float64 res;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_cpu_operator_cost();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = float8in((char *) value);
|
||||
cpu_operator_cost = *res;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_cpu_operator_cost()
|
||||
{
|
||||
elog(NOTICE, "CPU_OPERATOR_COST is %g", cpu_operator_cost);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_cpu_operator_cost()
|
||||
{
|
||||
cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* DATE_STYLE
|
||||
@ -917,71 +430,7 @@ reset_timezone()
|
||||
return TRUE;
|
||||
} /* reset_timezone() */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
KSQO code will one day be unnecessary when the optimizer makes use of
|
||||
indexes when multiple ORs are specified in the where clause.
|
||||
See optimizer/prep/prepkeyset.c for more on this.
|
||||
daveh@insightdist.com 6/16/98
|
||||
-----------------------------------------------------------------------*/
|
||||
static bool
|
||||
parse_ksqo(char *value)
|
||||
{
|
||||
return parse_boolean_var(value, &_use_keyset_query_optimizer,
|
||||
"KSQO", false);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_ksqo()
|
||||
{
|
||||
elog(NOTICE, "KSQO is %s",
|
||||
_use_keyset_query_optimizer ? "ON" : "OFF");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_ksqo()
|
||||
{
|
||||
_use_keyset_query_optimizer = false;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* MAX_EXPR_DEPTH
|
||||
*/
|
||||
static bool
|
||||
parse_max_expr_depth(char *value)
|
||||
{
|
||||
int newval;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
reset_max_expr_depth();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
newval = pg_atoi(value, sizeof(int), '\0');
|
||||
|
||||
if (newval < 10) /* somewhat arbitrary limit */
|
||||
elog(ERROR, "Bad value for MAX_EXPR_DEPTH (%s)", value);
|
||||
|
||||
max_expr_depth = newval;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
show_max_expr_depth()
|
||||
{
|
||||
elog(NOTICE, "MAX_EXPR_DEPTH is %d", max_expr_depth);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_max_expr_depth(void)
|
||||
{
|
||||
max_expr_depth = DEFAULT_MAX_EXPR_DEPTH;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* SET TRANSACTION */
|
||||
|
||||
@ -1038,37 +487,6 @@ reset_XactIsoLevel()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pg_options
|
||||
*/
|
||||
static bool
|
||||
parse_pg_options(char *value)
|
||||
{
|
||||
if (!superuser())
|
||||
elog(ERROR, "Only users with superuser privilege can set pg_options");
|
||||
if (value == NULL)
|
||||
read_pg_options(0);
|
||||
else
|
||||
parse_options((char *) value, TRUE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool
|
||||
show_pg_options(void)
|
||||
{
|
||||
show_options();
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool
|
||||
reset_pg_options(void)
|
||||
{
|
||||
if (!superuser())
|
||||
elog(ERROR, "Only users with superuser privilege can set pg_options");
|
||||
read_pg_options(0);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Random number seed
|
||||
@ -1105,157 +523,75 @@ reset_random_seed(void)
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static struct VariableParsers
|
||||
{
|
||||
const char *name;
|
||||
bool (*parser) (char *);
|
||||
bool (*show) ();
|
||||
bool (*reset) ();
|
||||
} VariableParsers[] =
|
||||
|
||||
{
|
||||
{
|
||||
"datestyle", parse_date, show_date, reset_date
|
||||
},
|
||||
{
|
||||
"timezone", parse_timezone, show_timezone, reset_timezone
|
||||
},
|
||||
{
|
||||
"effective_cache_size", parse_effective_cache_size,
|
||||
show_effective_cache_size, reset_effective_cache_size
|
||||
},
|
||||
{
|
||||
"random_page_cost", parse_random_page_cost,
|
||||
show_random_page_cost, reset_random_page_cost
|
||||
},
|
||||
{
|
||||
"cpu_tuple_cost", parse_cpu_tuple_cost,
|
||||
show_cpu_tuple_cost, reset_cpu_tuple_cost
|
||||
},
|
||||
{
|
||||
"cpu_index_tuple_cost", parse_cpu_index_tuple_cost,
|
||||
show_cpu_index_tuple_cost, reset_cpu_index_tuple_cost
|
||||
},
|
||||
{
|
||||
"cpu_operator_cost", parse_cpu_operator_cost,
|
||||
show_cpu_operator_cost, reset_cpu_operator_cost
|
||||
},
|
||||
{
|
||||
"enable_seqscan", parse_enable_seqscan,
|
||||
show_enable_seqscan, reset_enable_seqscan
|
||||
},
|
||||
{
|
||||
"enable_indexscan", parse_enable_indexscan,
|
||||
show_enable_indexscan, reset_enable_indexscan
|
||||
},
|
||||
{
|
||||
"enable_tidscan", parse_enable_tidscan,
|
||||
show_enable_tidscan, reset_enable_tidscan
|
||||
},
|
||||
{
|
||||
"enable_sort", parse_enable_sort,
|
||||
show_enable_sort, reset_enable_sort
|
||||
},
|
||||
{
|
||||
"enable_nestloop", parse_enable_nestloop,
|
||||
show_enable_nestloop, reset_enable_nestloop
|
||||
},
|
||||
{
|
||||
"enable_mergejoin", parse_enable_mergejoin,
|
||||
show_enable_mergejoin, reset_enable_mergejoin
|
||||
},
|
||||
{
|
||||
"enable_hashjoin", parse_enable_hashjoin,
|
||||
show_enable_hashjoin, reset_enable_hashjoin
|
||||
},
|
||||
{
|
||||
"geqo", parse_geqo, show_geqo, reset_geqo
|
||||
},
|
||||
#ifdef MULTIBYTE
|
||||
{
|
||||
"client_encoding", parse_client_encoding, show_client_encoding, reset_client_encoding
|
||||
},
|
||||
{
|
||||
"server_encoding", parse_server_encoding, show_server_encoding, reset_server_encoding
|
||||
},
|
||||
#endif
|
||||
{
|
||||
"ksqo", parse_ksqo, show_ksqo, reset_ksqo
|
||||
},
|
||||
{
|
||||
"max_expr_depth", parse_max_expr_depth,
|
||||
show_max_expr_depth, reset_max_expr_depth
|
||||
},
|
||||
{
|
||||
"XactIsoLevel", parse_XactIsoLevel, show_XactIsoLevel, reset_XactIsoLevel
|
||||
},
|
||||
{
|
||||
"pg_options", parse_pg_options, show_pg_options, reset_pg_options
|
||||
},
|
||||
{
|
||||
"seed", parse_random_seed, show_random_seed, reset_random_seed
|
||||
},
|
||||
{
|
||||
NULL, NULL, NULL, NULL
|
||||
}
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
* Set the named variable, or reset to default value if value is NULL
|
||||
*/
|
||||
bool
|
||||
void
|
||||
SetPGVariable(const char *name, const char *value)
|
||||
{
|
||||
struct VariableParsers *vp;
|
||||
char *val;
|
||||
|
||||
/* Make a modifiable copy for convenience of get_token */
|
||||
val = value ? pstrdup(value) : ((char *) NULL);
|
||||
|
||||
for (vp = VariableParsers; vp->name; vp++)
|
||||
{
|
||||
if (!strcasecmp(vp->name, name))
|
||||
return (vp->parser) (val);
|
||||
}
|
||||
|
||||
elog(NOTICE, "Unrecognized variable %s", name);
|
||||
|
||||
return TRUE;
|
||||
/*
|
||||
* Special cases ought to be removed are handled separately
|
||||
* by TCOP
|
||||
*/
|
||||
if (strcasecmp(name, "datestyle")==0)
|
||||
parse_date(pstrdup(value));
|
||||
else if (strcasecmp(name, "timezone")==0)
|
||||
parse_timezone(pstrdup(value));
|
||||
else if (strcasecmp(name, "XactIsoLevel")==0)
|
||||
parse_XactIsoLevel(pstrdup(value));
|
||||
#ifdef MULTIBYTE
|
||||
else if (strcasecmp(name, "client_encoding")==0)
|
||||
parse_client_encoding(pstrdup(value));
|
||||
else if (strcasecmp(name, "server_encoding")==0)
|
||||
parse_server_encoding(pstrdup(value));
|
||||
#endif
|
||||
else if (strcasecmp(name, "random_seed")==0)
|
||||
parse_random_seed(pstrdup(value));
|
||||
else
|
||||
SetConfigOption(name, value, superuser() ? PGC_SUSET : PGC_USERSET);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
bool
|
||||
|
||||
void
|
||||
GetPGVariable(const char *name)
|
||||
{
|
||||
struct VariableParsers *vp;
|
||||
if (strcasecmp(name, "datestyle")==0)
|
||||
show_date();
|
||||
else if (strcasecmp(name, "timezone")==0)
|
||||
show_timezone();
|
||||
else if (strcasecmp(name, "XactIsoLevel")==0)
|
||||
show_XactIsoLevel();
|
||||
#ifdef MULTIBYTE
|
||||
else if (strcasecmp(name, "client_encoding")==0)
|
||||
show_client_encoding();
|
||||
else if (strcasecmp(name, "server_encoding")==0)
|
||||
show_server_encoding();
|
||||
#endif
|
||||
else if (strcasecmp(name, "random_seed")==0)
|
||||
show_random_seed();
|
||||
else
|
||||
{
|
||||
const char * val = GetConfigOption(name, superuser());
|
||||
elog(NOTICE, "%s = %s", name, val);
|
||||
}
|
||||
}
|
||||
|
||||
for (vp = VariableParsers; vp->name; vp++)
|
||||
{
|
||||
if (!strcasecmp(vp->name, name))
|
||||
return (vp->show) ();
|
||||
}
|
||||
|
||||
elog(NOTICE, "Unrecognized variable %s", name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
bool
|
||||
void
|
||||
ResetPGVariable(const char *name)
|
||||
{
|
||||
struct VariableParsers *vp;
|
||||
|
||||
for (vp = VariableParsers; vp->name; vp++)
|
||||
{
|
||||
if (!strcasecmp(vp->name, name))
|
||||
return (vp->reset) ();
|
||||
}
|
||||
|
||||
elog(NOTICE, "Unrecognized variable %s", name);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
if (strcasecmp(name, "datestyle")==0)
|
||||
reset_date();
|
||||
else if (strcasecmp(name, "timezone")==0)
|
||||
reset_timezone();
|
||||
else if (strcasecmp(name, "XactIsoLevel")==0)
|
||||
reset_XactIsoLevel();
|
||||
#ifdef MULTIBYTE
|
||||
else if (strcasecmp(name, "client_encoding")==0)
|
||||
reset_client_encoding();
|
||||
else if (strcasecmp(name, "server_encoding")==0)
|
||||
reset_server_encoding();
|
||||
#endif
|
||||
else if (strcasecmp(name, "random_seed")==0)
|
||||
reset_random_seed();
|
||||
else
|
||||
SetConfigOption(name, NULL, superuser() ? PGC_SUSET : PGC_USERSET);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* $Id: nodeHash.c,v 1.45 2000/04/18 05:43:01 tgl Exp $
|
||||
* $Id: nodeHash.c,v 1.46 2000/05/31 00:28:17 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -27,10 +27,9 @@
|
||||
#include "executor/executor.h"
|
||||
#include "executor/nodeHash.h"
|
||||
#include "executor/nodeHashjoin.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/portal.h"
|
||||
|
||||
extern int SortMem;
|
||||
|
||||
static int hashFunc(Datum key, int len, bool byVal);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
|
@ -29,7 +29,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pqcomm.c,v 1.92 2000/05/26 01:26:19 tgl Exp $
|
||||
* $Id: pqcomm.c,v 1.93 2000/05/31 00:28:18 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -75,7 +75,6 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "libpq/libpq.h"
|
||||
#include "utils/trace.h" /* needed for HAVE_FCNTL_SETLK */
|
||||
#include "miscadmin.h"
|
||||
|
||||
|
||||
@ -130,7 +129,7 @@ pq_getport(void)
|
||||
|
||||
if (envport)
|
||||
return atoi(envport);
|
||||
return atoi(DEF_PGPORT);
|
||||
return DEF_PGPORT;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
@ -246,13 +245,8 @@ StreamServerPort(char *hostName, unsigned short portName, int *fdP)
|
||||
lck.l_whence = SEEK_SET;
|
||||
lck.l_start = lck.l_len = 0;
|
||||
lck.l_type = F_WRLCK;
|
||||
if (fcntl(lock_fd, F_SETLK, &lck) == 0)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE, "flock on %s, deleting", sock_path);
|
||||
if (fcntl(lock_fd, F_SETLK, &lck) != -1)
|
||||
unlink(sock_path);
|
||||
}
|
||||
else
|
||||
TPRINTF(TRACE_VERBOSE, "flock failed for %s", sock_path);
|
||||
close(lock_fd);
|
||||
}
|
||||
#endif /* HAVE_FCNTL_SETLK */
|
||||
@ -305,7 +299,7 @@ StreamServerPort(char *hostName, unsigned short portName, int *fdP)
|
||||
lck.l_start = lck.l_len = 0;
|
||||
lck.l_type = F_WRLCK;
|
||||
if (fcntl(lock_fd, F_SETLK, &lck) != 0)
|
||||
TPRINTF(TRACE_VERBOSE, "flock error for %s", sock_path);
|
||||
elog(DEBUG, "flock error on %s: %s", sock_path, strerror(errno));
|
||||
}
|
||||
#endif /* HAVE_FCNTL_SETLK */
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# $Id: Makefile,v 1.14 2000/05/29 05:44:48 tgl Exp $
|
||||
# $Id: Makefile,v 1.15 2000/05/31 00:28:19 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -17,7 +17,7 @@ CFLAGS+= -Wno-error
|
||||
endif
|
||||
|
||||
OBJS = geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \
|
||||
geqo_params.o geqo_pool.o geqo_recombination.o \
|
||||
geqo_pool.o geqo_recombination.o \
|
||||
geqo_selection.o \
|
||||
geqo_erx.o geqo_pmx.o geqo_cx.o geqo_px.o geqo_ox1.o geqo_ox2.o
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: geqo_main.c,v 1.20 2000/01/26 05:56:33 momjian Exp $
|
||||
* $Id: geqo_main.c,v 1.21 2000/05/31 00:28:19 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -23,12 +23,30 @@
|
||||
/* -- parts of this are adapted from D. Whitley's Genitor algorithm -- */
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "optimizer/geqo.h"
|
||||
#include "optimizer/geqo_misc.h"
|
||||
#include "optimizer/geqo_pool.h"
|
||||
#include "optimizer/geqo_selection.h"
|
||||
|
||||
|
||||
/*
|
||||
* Configuration options
|
||||
*/
|
||||
int Geqo_pool_size;
|
||||
int Geqo_effort;
|
||||
int Geqo_generations;
|
||||
double Geqo_selection_bias;
|
||||
int Geqo_random_seed;
|
||||
|
||||
|
||||
static int gimme_pool_size(int nr_rel);
|
||||
static int gimme_number_generations(int pool_size, int effort);
|
||||
|
||||
|
||||
/* define edge recombination crossover [ERX] per default */
|
||||
#if !defined(ERX) && \
|
||||
!defined(PMX) && \
|
||||
@ -81,13 +99,16 @@ geqo(Query *root)
|
||||
number_of_rels = length(root->base_rel_list);
|
||||
|
||||
/* set GA parameters */
|
||||
geqo_params(number_of_rels);/* read "$PGDATA/pg_geqo" file */
|
||||
pool_size = PoolSize;
|
||||
number_generations = Generations;
|
||||
pool_size = gimme_pool_size(number_of_rels);
|
||||
number_generations = gimme_number_generations(pool_size, Geqo_effort);
|
||||
status_interval = 10;
|
||||
|
||||
/* seed random number generator */
|
||||
srandom(RandomSeed);
|
||||
/* XXX why is this done every time around? */
|
||||
if (Geqo_random_seed >= 0)
|
||||
srandom(Geqo_random_seed);
|
||||
else
|
||||
srandom(time(NULL));
|
||||
|
||||
/* initialize plan evaluator */
|
||||
geqo_eval_startup();
|
||||
@ -146,7 +167,7 @@ geqo(Query *root)
|
||||
{
|
||||
|
||||
/* SELECTION */
|
||||
geqo_selection(momma, daddy, pool, SelectionBias); /* using linear bias
|
||||
geqo_selection(momma, daddy, pool, Geqo_selection_bias);/* using linear bias
|
||||
* function */
|
||||
|
||||
|
||||
@ -263,3 +284,52 @@ print_plan(best_plan, root);
|
||||
|
||||
return best_rel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return either configured pool size or
|
||||
* a good default based on query size (no. of relations)
|
||||
* = 2^(QS+1)
|
||||
* also constrain between 128 and 1024
|
||||
*/
|
||||
static int
|
||||
gimme_pool_size(int nr_rel)
|
||||
{
|
||||
double size;
|
||||
|
||||
if (Geqo_pool_size != 0)
|
||||
{
|
||||
if (Geqo_pool_size < MIN_GEQO_POOL_SIZE)
|
||||
return MIN_GEQO_POOL_SIZE;
|
||||
else if (Geqo_pool_size > MAX_GEQO_POOL_SIZE)
|
||||
return MAX_GEQO_POOL_SIZE;
|
||||
else
|
||||
return Geqo_pool_size;
|
||||
}
|
||||
|
||||
size = pow(2.0, nr_rel + 1.0);
|
||||
|
||||
if (size < MIN_GEQO_POOL_SIZE)
|
||||
return MIN_GEQO_POOL_SIZE;
|
||||
else if (size > MAX_GEQO_POOL_SIZE)
|
||||
return MAX_GEQO_POOL_SIZE;
|
||||
else
|
||||
return (int) ceil(size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return either configured number of generations or
|
||||
* some reasonable default calculated on the fly.
|
||||
* = Effort * Log2(PoolSize)
|
||||
*/
|
||||
static int
|
||||
gimme_number_generations(int pool_size, int effort)
|
||||
{
|
||||
if (Geqo_generations <= 0)
|
||||
return effort * (int) ceil(log((double) pool_size) / log(2.0));
|
||||
else
|
||||
return Geqo_generations;
|
||||
}
|
||||
|
@ -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
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.61 2000/05/30 00:49:46 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.62 2000/05/31 00:28:22 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -21,15 +21,8 @@
|
||||
#include "optimizer/paths.h"
|
||||
|
||||
|
||||
#ifdef GEQO
|
||||
bool enable_geqo = true;
|
||||
|
||||
#else
|
||||
bool enable_geqo = false;
|
||||
|
||||
#endif
|
||||
|
||||
int geqo_rels = GEQO_RELS;
|
||||
int geqo_rels = DEFAULT_GEQO_RELS;
|
||||
|
||||
|
||||
static void set_base_rel_pathlist(Query *root);
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.60 2000/05/30 04:24:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.61 2000/05/31 00:28:22 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -63,11 +63,11 @@
|
||||
#define LOG6(x) (log(x) / 1.79175946922805)
|
||||
|
||||
|
||||
double effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
|
||||
Cost random_page_cost = DEFAULT_RANDOM_PAGE_COST;
|
||||
Cost cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST;
|
||||
Cost cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST;
|
||||
Cost cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST;
|
||||
double effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
|
||||
double random_page_cost = DEFAULT_RANDOM_PAGE_COST;
|
||||
double cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST;
|
||||
double cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST;
|
||||
double cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST;
|
||||
|
||||
Cost disable_cost = 100000000.0;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.168 2000/05/25 22:42:17 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.169 2000/05/31 00:28:24 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -323,7 +323,8 @@ static void doNegateFloat(Value *v);
|
||||
IMMEDIATE, INITIALLY,
|
||||
PENDANT,
|
||||
RESTRICT,
|
||||
TRIGGER
|
||||
TRIGGER,
|
||||
OFF
|
||||
|
||||
/* Keywords (in SQL92 non-reserved words) */
|
||||
%token COMMITTED, SERIALIZABLE, TYPE_P
|
||||
@ -715,67 +716,63 @@ opt_level: READ COMMITTED { $$ = "committed"; }
|
||||
| SERIALIZABLE { $$ = "serializable"; }
|
||||
;
|
||||
|
||||
var_value: Sconst
|
||||
{
|
||||
/* Plain old string (pointer to char) */
|
||||
$$ = $1;
|
||||
}
|
||||
| FCONST
|
||||
{
|
||||
/* Floating numeric argument.
|
||||
* This recently changed to preserve "stringiness",
|
||||
* so we don't have any work to do at all. Nice.
|
||||
* - thomas 2000-03-29
|
||||
*/
|
||||
$$ = $1;
|
||||
}
|
||||
| Iconst
|
||||
{
|
||||
char buf[64];
|
||||
var_value: SCONST { $$ = $1; }
|
||||
| ICONST
|
||||
{
|
||||
char buf[64];
|
||||
sprintf(buf, "%d", $1);
|
||||
$$ = pstrdup(buf);
|
||||
}
|
||||
| '-' ICONST
|
||||
{
|
||||
char buf[64];
|
||||
sprintf(buf, "%d", -($2));
|
||||
$$ = pstrdup(buf);
|
||||
}
|
||||
| FCONST { $$ = $1; }
|
||||
| '-' FCONST
|
||||
{
|
||||
char * s = palloc(strlen($2)+2);
|
||||
s[0] = '-';
|
||||
strcpy(s + 1, $2);
|
||||
$$ = s;
|
||||
}
|
||||
| TRUE_P { $$ = "true"; }
|
||||
| FALSE_P { $$ = "false"; }
|
||||
| ON { $$ = "on"; }
|
||||
| OFF { $$ = "off"; }
|
||||
|
||||
/* Integer numeric argument.
|
||||
*/
|
||||
sprintf(buf, "%d", $1);
|
||||
$$ = pstrdup(buf);
|
||||
}
|
||||
| name_list
|
||||
{
|
||||
List *n;
|
||||
int slen = 0;
|
||||
char *result;
|
||||
| name_list
|
||||
{
|
||||
List *n;
|
||||
int slen = 0;
|
||||
char *result;
|
||||
|
||||
/* List of words? Then concatenate together */
|
||||
if ($1 == NIL)
|
||||
elog(ERROR, "SET must have at least one argument");
|
||||
/* List of words? Then concatenate together */
|
||||
if ($1 == NIL)
|
||||
elog(ERROR, "SET must have at least one argument");
|
||||
|
||||
foreach (n, $1)
|
||||
{
|
||||
Value *p = (Value *) lfirst(n);
|
||||
Assert(IsA(p, String));
|
||||
/* keep track of room for string and trailing comma */
|
||||
slen += (strlen(p->val.str) + 1);
|
||||
}
|
||||
result = palloc(slen + 1);
|
||||
*result = '\0';
|
||||
foreach (n, $1)
|
||||
{
|
||||
Value *p = (Value *) lfirst(n);
|
||||
strcat(result, p->val.str);
|
||||
strcat(result, ",");
|
||||
}
|
||||
/* remove the trailing comma from the last element */
|
||||
*(result+strlen(result)-1) = '\0';
|
||||
$$ = result;
|
||||
}
|
||||
/* "OFF" is not a token, so it is handled by the name_list production */
|
||||
| ON
|
||||
{
|
||||
$$ = "on";
|
||||
}
|
||||
| DEFAULT
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
foreach (n, $1)
|
||||
{
|
||||
Value *p = (Value *) lfirst(n);
|
||||
Assert(IsA(p, String));
|
||||
/* keep track of room for string and trailing comma */
|
||||
slen += (strlen(p->val.str) + 1);
|
||||
}
|
||||
result = palloc(slen + 1);
|
||||
*result = '\0';
|
||||
foreach (n, $1)
|
||||
{
|
||||
Value *p = (Value *) lfirst(n);
|
||||
strcat(result, p->val.str);
|
||||
strcat(result, ",");
|
||||
}
|
||||
/* remove the trailing comma from the last element */
|
||||
*(result+strlen(result)-1) = '\0';
|
||||
$$ = result;
|
||||
}
|
||||
|
||||
| DEFAULT { $$ = NULL; }
|
||||
;
|
||||
|
||||
zone_value: Sconst { $$ = $1; }
|
||||
@ -5534,6 +5531,7 @@ ColLabel: ColId { $$ = $1; }
|
||||
| NULLIF { $$ = "nullif"; }
|
||||
| NULL_P { $$ = "null"; }
|
||||
| NUMERIC { $$ = "numeric"; }
|
||||
| OFF { $$ = "off"; }
|
||||
| OFFSET { $$ = "offset"; }
|
||||
| ON { $$ = "on"; }
|
||||
| OR { $$ = "or"; }
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.72 2000/05/29 05:44:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.73 2000/05/31 00:28:24 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -176,6 +176,7 @@ static ScanKeyword ScanKeywords[] = {
|
||||
{"nullif", NULLIF},
|
||||
{"numeric", NUMERIC},
|
||||
{"of", OF},
|
||||
{"off", OFF},
|
||||
{"offset", OFFSET},
|
||||
{"oids", OIDS},
|
||||
{"old", CURRENT},
|
||||
|
@ -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
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.143 2000/05/26 01:38:08 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.144 2000/05/31 00:28:25 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@ -90,7 +90,7 @@
|
||||
#include "storage/proc.h"
|
||||
#include "access/xlog.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/trace.h"
|
||||
#include "utils/guc.h"
|
||||
#include "version.h"
|
||||
|
||||
/*
|
||||
@ -136,7 +136,7 @@ static Dllist *BackendList;
|
||||
/* list of ports associated with still open, but incomplete connections */
|
||||
static Dllist *PortList;
|
||||
|
||||
static unsigned short PostPortName = 0;
|
||||
int PostPortName = DEF_PGPORT;
|
||||
|
||||
/*
|
||||
* This is a boolean indicating that there is at least one backend that
|
||||
@ -167,7 +167,7 @@ static IpcMemoryKey ipc_key;
|
||||
* adding to this.
|
||||
*/
|
||||
|
||||
static int MaxBackends = DEF_MAXBACKENDS;
|
||||
int MaxBackends = DEF_MAXBACKENDS;
|
||||
|
||||
/*
|
||||
* MaxBackends is the actual limit on the number of backends we will
|
||||
@ -185,6 +185,9 @@ static int real_argc;
|
||||
|
||||
static time_t tnow;
|
||||
|
||||
/* flag to indicate that SIGHUP arrived during server loop */
|
||||
static volatile bool got_SIGHUP = false;
|
||||
|
||||
/*
|
||||
* Default Values
|
||||
*/
|
||||
@ -217,8 +220,7 @@ static char ExtraOptions[MAXPGPATH];
|
||||
static bool Reinit = true;
|
||||
static int SendStop = false;
|
||||
|
||||
static bool NetServer = false; /* if not zero, postmaster listen for
|
||||
* non-local connections */
|
||||
bool NetServer = false; /* listen on TCP/IP */
|
||||
|
||||
#ifdef USE_SSL
|
||||
static bool SecureNetServer = false; /* if not zero, postmaster listens
|
||||
@ -256,7 +258,8 @@ extern int optind,
|
||||
static void pmdaemonize(char *extraoptions);
|
||||
static Port *ConnCreate(int serverFd);
|
||||
static void ConnFree(Port *port);
|
||||
static void reset_shared(unsigned short port);
|
||||
static void reset_shared(int port);
|
||||
static void SIGHUP_handler(SIGNAL_ARGS);
|
||||
static void pmdie(SIGNAL_ARGS);
|
||||
static void reaper(SIGNAL_ARGS);
|
||||
static void dumpstatus(SIGNAL_ARGS);
|
||||
@ -368,7 +371,6 @@ checkDataDir(const char *DataDir, bool *DataDirOK)
|
||||
int
|
||||
PostmasterMain(int argc, char *argv[])
|
||||
{
|
||||
extern int NBuffers; /* from buffer/bufmgr.c */
|
||||
int opt;
|
||||
char *hostName;
|
||||
int status;
|
||||
@ -431,6 +433,8 @@ PostmasterMain(int argc, char *argv[])
|
||||
*/
|
||||
umask((mode_t) 0077);
|
||||
|
||||
ResetAllOptions();
|
||||
|
||||
if (!(hostName = getenv("PGHOST")))
|
||||
{
|
||||
if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0)
|
||||
@ -441,9 +445,38 @@ PostmasterMain(int argc, char *argv[])
|
||||
MyProcPid = getpid();
|
||||
DataDir = getenv("PGDATA"); /* default value */
|
||||
|
||||
opterr = 0;
|
||||
/*
|
||||
* First we must scan for a -D argument to get the data dir. Then
|
||||
* read the config file. Finally, scan all the other arguments.
|
||||
* (Command line switches override config file.)
|
||||
*
|
||||
* Note: The two lists of options must be exactly the same, even
|
||||
* though perhaps the first one would only have to be "D:" with
|
||||
* opterr turned off. But some versions of getopt (notably GNU)
|
||||
* are going to arbitrarily permute some "non-options" (according
|
||||
* to the local world view) which will result in some switches
|
||||
* being associated with the wrong argument. Death and destruction
|
||||
* will occur.
|
||||
*/
|
||||
opterr = 1;
|
||||
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:Film:MN:no:p:Ss-:")) != EOF)
|
||||
{
|
||||
if (opt == 'D')
|
||||
DataDir = optarg;
|
||||
}
|
||||
|
||||
optind = 1; /* start over */
|
||||
checkDataDir(DataDir, &DataDirOK); /* issues error messages */
|
||||
if (!DataDirOK)
|
||||
{
|
||||
fprintf(stderr, "No data directory -- can't proceed.\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
ProcessConfigFile(PGC_POSTMASTER);
|
||||
|
||||
IgnoreSystemIndexes(false);
|
||||
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:ilm:MN:no:p:Ss")) != EOF)
|
||||
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:Film:MN:no:p:Ss-:")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@ -464,15 +497,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
/* Can no longer set authentication method. */
|
||||
break;
|
||||
case 'B':
|
||||
|
||||
/*
|
||||
* The number of buffers to create. Setting this option
|
||||
* means we have to start each backend with a -B # to make
|
||||
* sure they know how many buffers were allocated.
|
||||
*/
|
||||
NBuffers = atoi(optarg);
|
||||
strcat(ExtraOptions, " -B ");
|
||||
strcat(ExtraOptions, optarg);
|
||||
break;
|
||||
case 'b':
|
||||
/* Set the backend executable file to use. */
|
||||
@ -486,8 +511,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
/* Set PGDATA from the command line. */
|
||||
DataDir = optarg;
|
||||
/* already done above */
|
||||
break;
|
||||
case 'd':
|
||||
|
||||
@ -496,8 +520,10 @@ PostmasterMain(int argc, char *argv[])
|
||||
* servers descended from it.
|
||||
*/
|
||||
DebugLvl = atoi(optarg);
|
||||
pg_options[TRACE_VERBOSE] = DebugLvl;
|
||||
break;
|
||||
case 'F':
|
||||
enableFsync = false;
|
||||
break;
|
||||
case 'i':
|
||||
NetServer = true;
|
||||
break;
|
||||
@ -545,7 +571,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
break;
|
||||
case 'p':
|
||||
/* Set PGPORT by hand. */
|
||||
PostPortName = (unsigned short) atoi(optarg);
|
||||
PostPortName = atoi(optarg);
|
||||
break;
|
||||
case 'S':
|
||||
|
||||
@ -567,6 +593,21 @@ PostmasterMain(int argc, char *argv[])
|
||||
*/
|
||||
SendStop = true;
|
||||
break;
|
||||
case '-':
|
||||
{
|
||||
/* A little 'long argument' simulation */
|
||||
size_t equal_pos = strcspn(optarg, "=");
|
||||
char *cp;
|
||||
|
||||
if (optarg[equal_pos] != '=')
|
||||
elog(ERROR, "--%s requires argument", optarg);
|
||||
optarg[equal_pos] = '\0';
|
||||
for(cp = optarg; *cp; cp++)
|
||||
if (*cp == '-')
|
||||
*cp = '_';
|
||||
SetConfigOption(optarg, optarg + equal_pos + 1, PGC_POSTMASTER);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* usage() never returns */
|
||||
usage(progname);
|
||||
@ -574,11 +615,8 @@ PostmasterMain(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Select default values for switches where needed
|
||||
*/
|
||||
if (PostPortName == 0)
|
||||
PostPortName = (unsigned short) pq_getport();
|
||||
PostPortName = pq_getport();
|
||||
|
||||
/*
|
||||
* Check for invalid combinations of switches
|
||||
@ -596,13 +634,6 @@ PostmasterMain(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkDataDir(DataDir, &DataDirOK); /* issues error messages */
|
||||
if (!DataDirOK)
|
||||
{
|
||||
fprintf(stderr, "No data directory -- can't proceed.\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!Execfile[0] && FindExec(Execfile, argv[0], "postgres") < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: could not find backend to execute...\n",
|
||||
@ -622,7 +653,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
|
||||
if (NetServer)
|
||||
{
|
||||
status = StreamServerPort(hostName, PostPortName, &ServerSock_INET);
|
||||
status = StreamServerPort(hostName, (unsigned short)PostPortName, &ServerSock_INET);
|
||||
if (status != STATUS_OK)
|
||||
{
|
||||
fprintf(stderr, "%s: cannot create INET stream port\n",
|
||||
@ -632,7 +663,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
}
|
||||
|
||||
#if !defined(__CYGWIN32__) && !defined(__QNX__)
|
||||
status = StreamServerPort(NULL, PostPortName, &ServerSock_UNIX);
|
||||
status = StreamServerPort(NULL, (unsigned short)PostPortName, &ServerSock_UNIX);
|
||||
if (status != STATUS_OK)
|
||||
{
|
||||
fprintf(stderr, "%s: cannot create UNIX stream port\n",
|
||||
@ -707,7 +738,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
PG_INITMASK();
|
||||
PG_SETMASK(&BlockSig);
|
||||
|
||||
pqsignal(SIGHUP, pmdie); /* send SIGHUP, don't die */
|
||||
pqsignal(SIGHUP, SIGHUP_handler); /* reread config file and have children do same */
|
||||
pqsignal(SIGINT, pmdie); /* send SIGTERM and ShutdownDataBase */
|
||||
pqsignal(SIGQUIT, pmdie); /* send SIGUSR1 and die */
|
||||
pqsignal(SIGTERM, pmdie); /* wait for children and ShutdownDataBase */
|
||||
@ -1066,6 +1097,12 @@ ServerLoop(void)
|
||||
|
||||
curr = next;
|
||||
}
|
||||
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
got_SIGHUP = false;
|
||||
ProcessConfigFile(PGC_SIGHUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1321,7 +1358,7 @@ ConnFree(Port *conn)
|
||||
* reset_shared -- reset shared memory and semaphores
|
||||
*/
|
||||
static void
|
||||
reset_shared(unsigned short port)
|
||||
reset_shared(int port)
|
||||
{
|
||||
ipc_key = port * 1000 + shmem_seq * 100;
|
||||
CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends);
|
||||
@ -1330,6 +1367,23 @@ reset_shared(unsigned short port)
|
||||
shmem_seq -= 10;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set flag is SIGHUP was detected so config file can be reread in
|
||||
* main loop
|
||||
*/
|
||||
static void
|
||||
SIGHUP_handler(SIGNAL_ARGS)
|
||||
{
|
||||
got_SIGHUP = true;
|
||||
if (Shutdown > SmartShutdown)
|
||||
return;
|
||||
got_SIGHUP = true;
|
||||
SignalChildren(SIGHUP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* pmdie -- signal handler for cleaning up after a kill signal.
|
||||
*/
|
||||
@ -1338,19 +1392,11 @@ pmdie(SIGNAL_ARGS)
|
||||
{
|
||||
PG_SETMASK(&BlockSig);
|
||||
|
||||
TPRINTF(TRACE_VERBOSE, "pmdie %d", postgres_signal_arg);
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "pmdie %d", postgres_signal_arg);
|
||||
|
||||
switch (postgres_signal_arg)
|
||||
{
|
||||
case SIGHUP:
|
||||
|
||||
/*
|
||||
* Send SIGHUP to all children (update options flags)
|
||||
*/
|
||||
if (Shutdown > SmartShutdown)
|
||||
return;
|
||||
SignalChildren(SIGHUP);
|
||||
return;
|
||||
case SIGUSR2:
|
||||
|
||||
/*
|
||||
@ -1679,9 +1725,10 @@ SignalChildren(int signal)
|
||||
|
||||
if (bp->pid != mypid)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE,
|
||||
"SignalChildren: sending signal %d to process %d",
|
||||
signal, bp->pid);
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "SignalChildren: sending signal %d to process %d",
|
||||
signal, bp->pid);
|
||||
|
||||
kill(bp->pid, signal);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.34 2000/04/12 17:15:33 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.35 2000/05/31 00:28:26 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -48,7 +48,6 @@ long *CurTraceBuf;
|
||||
#endif /* BMTRACE */
|
||||
int ShowPinTrace = 0;
|
||||
|
||||
int NBuffers = DEF_NBUFFERS; /* default is set in config.h */
|
||||
int Data_Descriptors;
|
||||
int Free_List_Descriptor;
|
||||
int Lookup_List_Descriptor;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.56 2000/04/12 17:15:35 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.57 2000/05/31 00:28:27 petere Exp $
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
@ -196,7 +196,10 @@ static long pg_nofile(void);
|
||||
int
|
||||
pg_fsync(int fd)
|
||||
{
|
||||
return disableFsync ? 0 : fsync(fd);
|
||||
if (enableFsync)
|
||||
return fsync(fd);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -916,7 +919,7 @@ FileSync(File file)
|
||||
/* Need not sync if file is not dirty. */
|
||||
returnCode = 0;
|
||||
}
|
||||
else if (disableFsync)
|
||||
else if (!enableFsync)
|
||||
{
|
||||
/* Don't force the file open if pg_fsync isn't gonna sync it. */
|
||||
returnCode = 0;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.47 2000/05/16 20:48:48 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.48 2000/05/31 00:28:29 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@ -36,9 +36,9 @@
|
||||
/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
|
||||
#include <sys/sem.h>
|
||||
#include <sys/shm.h>
|
||||
#include "miscadmin.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "libpq/libpq.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
#if defined(solaris_sparc)
|
||||
#include <sys/ipc.h>
|
||||
@ -124,7 +124,8 @@ proc_exit(int code)
|
||||
*/
|
||||
proc_exit_inprogress = true;
|
||||
|
||||
TPRINTF(TRACE_VERBOSE, "proc_exit(%d)", code);
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "proc_exit(%d)", code);
|
||||
|
||||
/* do our shared memory exits first */
|
||||
shmem_exit(code);
|
||||
@ -143,7 +144,8 @@ proc_exit(int code)
|
||||
(*on_proc_exit_list[on_proc_exit_index].function) (code,
|
||||
on_proc_exit_list[on_proc_exit_index].arg);
|
||||
|
||||
TPRINTF(TRACE_VERBOSE, "exit(%d)", code);
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "exit(%d)", code);
|
||||
exit(code);
|
||||
}
|
||||
|
||||
@ -156,7 +158,8 @@ proc_exit(int code)
|
||||
void
|
||||
shmem_exit(int code)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE, "shmem_exit(%d)", code);
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "shmem_exit(%d)", code);
|
||||
|
||||
/* ----------------
|
||||
* call all the registered callbacks.
|
||||
@ -297,18 +300,16 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
|
||||
if (semId == -1)
|
||||
{
|
||||
#ifdef DEBUG_IPC
|
||||
EPRINTF("calling semget with %d, %d , %d\n",
|
||||
semKey,
|
||||
semNum,
|
||||
IPC_CREAT | permission);
|
||||
fprintf(stderr, "calling semget(%d, %d, 0%o)\n",
|
||||
semKey, semNum, (unsigned)(IPC_CREAT|permission));
|
||||
#endif
|
||||
semId = semget(semKey, semNum, IPC_CREAT | permission);
|
||||
|
||||
if (semId < 0)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreCreate: semget failed (%s) "
|
||||
"key=%d, num=%d, permission=%o",
|
||||
strerror(errno), semKey, semNum, permission);
|
||||
fprintf(stderr, "IpcSemaphoreCreate: semget(%d, %d, 0%o) failed: %s\n",
|
||||
semKey, semNum, (unsigned)(permission|IPC_CREAT),
|
||||
strerror(errno));
|
||||
IpcConfigTip();
|
||||
return (-1);
|
||||
}
|
||||
@ -318,8 +319,8 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
|
||||
errStatus = semctl(semId, 0, SETALL, semun);
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreCreate: semctl failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
fprintf(stderr, "IpcSemaphoreCreate: semctl(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
semctl(semId, 0, IPC_RMID, semun);
|
||||
IpcConfigTip();
|
||||
return (-1);
|
||||
@ -330,10 +331,11 @@ IpcSemaphoreCreate(IpcSemaphoreKey semKey,
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IPC
|
||||
EPRINTF("\nIpcSemaphoreCreate, returns %d\n", semId);
|
||||
fprintf(stderr, "IpcSemaphoreCreate returns %d\n", semId);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
return semId;
|
||||
}
|
||||
|
||||
@ -357,13 +359,11 @@ IpcSemaphoreSet(int semId, int semno, int value)
|
||||
IpcSemaphoreSet_return = errStatus;
|
||||
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreSet: semctl failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
}
|
||||
fprintf(stderr, "IpcSemaphoreSet: semctl(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* NOT_USED */
|
||||
|
||||
/****************************************************************************/
|
||||
/* IpcSemaphoreKill(key) - removes a semaphore */
|
||||
@ -421,8 +421,8 @@ IpcSemaphoreLock(IpcSemaphoreId semId, int sem, int lock)
|
||||
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreLock: semop failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
fprintf(stderr, "IpcSemaphoreLock: semop(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
proc_exit(255);
|
||||
}
|
||||
}
|
||||
@ -466,8 +466,8 @@ IpcSemaphoreUnlock(IpcSemaphoreId semId, int sem, int lock)
|
||||
|
||||
if (errStatus == -1)
|
||||
{
|
||||
EPRINTF("IpcSemaphoreUnlock: semop failed (%s) id=%d",
|
||||
strerror(errno), semId);
|
||||
fprintf(stderr, "IpcSemaphoreUnlock: semop(id=%d) failed: %s\n",
|
||||
semId, strerror(errno));
|
||||
proc_exit(255);
|
||||
}
|
||||
}
|
||||
@ -516,9 +516,8 @@ IpcMemoryCreate(IpcMemoryKey memKey, uint32 size, int permission)
|
||||
|
||||
if (shmid < 0)
|
||||
{
|
||||
EPRINTF("IpcMemoryCreate: shmget failed (%s) "
|
||||
"key=%d, size=%d, permission=%o",
|
||||
strerror(errno), memKey, size, permission);
|
||||
fprintf(stderr, "IpcMemoryCreate: shmget(%d, %d, 0%o) failed: %s\n",
|
||||
memKey, size, (unsigned)(IPC_CREAT|permission), strerror(errno));
|
||||
IpcConfigTip();
|
||||
return IpcMemCreationFailed;
|
||||
}
|
||||
@ -542,9 +541,8 @@ IpcMemoryIdGet(IpcMemoryKey memKey, uint32 size)
|
||||
|
||||
if (shmid < 0)
|
||||
{
|
||||
EPRINTF("IpcMemoryIdGet: shmget failed (%s) "
|
||||
"key=%d, size=%d, permission=%o",
|
||||
strerror(errno), memKey, size, 0);
|
||||
fprintf(stderr, "IpcMemoryIdGet: shmget(%d, %d, 0) failed: %s\n",
|
||||
memKey, size, strerror(errno));
|
||||
return IpcMemIdGetFailed;
|
||||
}
|
||||
|
||||
@ -583,8 +581,8 @@ IpcMemoryAttach(IpcMemoryId memId)
|
||||
/* if ( *memAddress == -1) { XXX ??? */
|
||||
if (memAddress == (char *) -1)
|
||||
{
|
||||
EPRINTF("IpcMemoryAttach: shmat failed (%s) id=%d",
|
||||
strerror(errno), memId);
|
||||
fprintf(stderr, "IpcMemoryAttach: shmat(id=%d) failed: %s\n",
|
||||
memId, strerror(errno));
|
||||
return IpcMemAttachFailed;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.31 2000/05/30 00:49:52 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.32 2000/05/31 00:28:29 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -268,8 +268,8 @@ SIInsertDataEntry(SISeg *segP, SharedInvalidData *data)
|
||||
if (numMsgs == (MAXNUMMESSAGES * 70 / 100) &&
|
||||
IsUnderPostmaster)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE,
|
||||
"SIInsertDataEntry: table is 70%% full, signaling postmaster");
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "SIInsertDataEntry: table is 70%% full, signaling postmaster");
|
||||
kill(getppid(), SIGUSR2);
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.24 2000/04/12 17:15:37 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.25 2000/05/31 00:28:29 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -35,6 +35,7 @@
|
||||
#include "storage/proc.h"
|
||||
#include "storage/s_lock.h"
|
||||
|
||||
|
||||
/* globals used in this file */
|
||||
IpcSemaphoreId SpinLockId;
|
||||
|
||||
@ -84,14 +85,23 @@ InitSpinLocks(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOCKDEBUG
|
||||
#define PRINT_LOCK(LOCK) \
|
||||
TPRINTF(TRACE_SPINLOCKS, \
|
||||
"(locklock = %d, flag = %d, nshlocks = %d, shlock = %d, " \
|
||||
"exlock =%d)\n", LOCK->locklock, \
|
||||
LOCK->flag, LOCK->nshlocks, LOCK->shlock, \
|
||||
LOCK->exlock)
|
||||
#endif
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
bool Trace_spinlocks = false;
|
||||
|
||||
inline static void
|
||||
PRINT_SLDEBUG(const char * where, SPINLOCK lockid, const SLock * lock)
|
||||
{
|
||||
if (Trace_spinlocks)
|
||||
elog(DEBUG,
|
||||
"%s: id=%d (locklock=%d, flag=%d, nshlocks=%d, shlock=%d, exlock=%d)",
|
||||
where, lockid,
|
||||
lock->locklock, lock->flag, lock->nshlocks, lock->shlock, lock->exlock);
|
||||
}
|
||||
#else /* not LOCK_DEBUG */
|
||||
#define PRINT_SLDEBUG(a,b,c)
|
||||
#endif /* not LOCK_DEBUG */
|
||||
|
||||
|
||||
/* from ipc.c */
|
||||
extern SLock *SLockArray;
|
||||
@ -103,10 +113,7 @@ SpinAcquire(SPINLOCK lockid)
|
||||
|
||||
/* This used to be in ipc.c, but move here to reduce function calls */
|
||||
slckP = &(SLockArray[lockid]);
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "SpinAcquire: %d", lockid);
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinAcquire", lockid, slckP);
|
||||
ex_try_again:
|
||||
S_LOCK(&(slckP->locklock));
|
||||
switch (slckP->flag)
|
||||
@ -116,10 +123,7 @@ ex_try_again:
|
||||
S_LOCK(&(slckP->exlock));
|
||||
S_LOCK(&(slckP->shlock));
|
||||
S_UNLOCK(&(slckP->locklock));
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "OUT: ");
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("OUT", lockid, slckP);
|
||||
break;
|
||||
case SHAREDLOCK:
|
||||
case EXCLUSIVELOCK:
|
||||
@ -129,9 +133,7 @@ ex_try_again:
|
||||
goto ex_try_again;
|
||||
}
|
||||
PROC_INCR_SLOCK(lockid);
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "SpinAcquire: got %d", lockid);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinAcquire/success", lockid, slckP);
|
||||
}
|
||||
|
||||
void
|
||||
@ -142,23 +144,16 @@ SpinRelease(SPINLOCK lockid)
|
||||
/* This used to be in ipc.c, but move here to reduce function calls */
|
||||
slckP = &(SLockArray[lockid]);
|
||||
|
||||
#ifdef USE_ASSERT_CHECKING
|
||||
|
||||
/*
|
||||
* Check that we are actually holding the lock we are releasing. This
|
||||
* can be done only after MyProc has been initialized.
|
||||
*/
|
||||
if (MyProc)
|
||||
Assert(MyProc->sLocks[lockid] > 0);
|
||||
Assert(!MyProc || MyProc->sLocks[lockid] > 0);
|
||||
Assert(slckP->flag != NOLOCK);
|
||||
#endif
|
||||
|
||||
|
||||
PROC_DECR_SLOCK(lockid);
|
||||
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF("SpinRelease: %d\n", lockid);
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinRelease", lockid, slckP);
|
||||
S_LOCK(&(slckP->locklock));
|
||||
/* -------------
|
||||
* give favor to read processes
|
||||
@ -178,13 +173,10 @@ SpinRelease(SPINLOCK lockid)
|
||||
S_UNLOCK(&(slckP->shlock));
|
||||
S_UNLOCK(&(slckP->exlock));
|
||||
S_UNLOCK(&(slckP->locklock));
|
||||
#ifdef LOCKDEBUG
|
||||
TPRINTF(TRACE_SPINLOCKS, "SpinRelease: released %d", lockid);
|
||||
PRINT_LOCK(slckP);
|
||||
#endif
|
||||
PRINT_SLDEBUG("SpinRelease/released", lockid, slckP);
|
||||
}
|
||||
|
||||
#else /* HAS_TEST_AND_SET */
|
||||
#else /* !HAS_TEST_AND_SET */
|
||||
/* Spinlocks are implemented using SysV semaphores */
|
||||
|
||||
static bool AttachSpinLocks(IPCKey key);
|
||||
@ -290,4 +282,4 @@ InitSpinLocks(void)
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* HAS_TEST_AND_SET */
|
||||
#endif /* !HAS_TEST_AND_SET */
|
||||
|
@ -8,17 +8,10 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.39 2000/04/12 17:15:38 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.40 2000/05/31 00:28:30 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/* #define LOCKDEBUGALL 1 */
|
||||
/* #define LOCKDEBUG 1 */
|
||||
|
||||
#ifdef LOCKDEBUGALL
|
||||
#define LOCKDEBUG 1
|
||||
#endif /* LOCKDEBUGALL */
|
||||
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.67 2000/04/30 21:23:31 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.68 2000/05/31 00:28:30 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@ -39,106 +39,11 @@
|
||||
#include "miscadmin.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode);
|
||||
|
||||
/*
|
||||
* lockDebugRelation can be used to trace unconditionally a single relation,
|
||||
* for example pg_listener, if you suspect there are locking problems.
|
||||
*
|
||||
* lockDebugOidMin is is used to avoid tracing postgres relations, which
|
||||
* would produce a lot of output. Unfortunately most system relations are
|
||||
* created after bootstrap and have oid greater than BootstrapObjectIdData.
|
||||
* If you are using tprintf you should specify a value greater than the max
|
||||
* 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 use the following pg_options:
|
||||
*
|
||||
* -T "verbose,query,locks,userlocks,lock_debug_oidmin=17500"
|
||||
*/
|
||||
#define LOCKDEBUG(lockmethod) (pg_options[TRACE_SHORTLOCKS+lockmethod])
|
||||
#define lockDebugRelation (pg_options[TRACE_LOCKRELATION])
|
||||
#define lockDebugOidMin (pg_options[TRACE_LOCKOIDMIN])
|
||||
#define lockReadPriority (pg_options[OPT_LOCKREADPRIORITY])
|
||||
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
#define LOCK_PRINT(where,lock,type) \
|
||||
if (((LOCKDEBUG(LOCK_LOCKMETHOD(*(lock))) >= 1) \
|
||||
&& (lock->tag.relId >= lockDebugOidMin)) \
|
||||
|| \
|
||||
(lockDebugRelation && (lock->tag.relId == lockDebugRelation))) \
|
||||
LOCK_PRINT_AUX(where,lock,type)
|
||||
|
||||
#define LOCK_PRINT_AUX(where,lock,type) \
|
||||
TPRINTF(TRACE_ALL, \
|
||||
"%s: lock(%x) tbl(%d) rel(%u) db(%u) obj(%u) mask(%x) " \
|
||||
"hold(%d,%d,%d,%d,%d,%d,%d)=%d " \
|
||||
"act(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", \
|
||||
where, \
|
||||
MAKE_OFFSET(lock), \
|
||||
lock->tag.lockmethod, \
|
||||
lock->tag.relId, \
|
||||
lock->tag.dbId, \
|
||||
lock->tag.objId.blkno, \
|
||||
lock->mask, \
|
||||
lock->holders[1], \
|
||||
lock->holders[2], \
|
||||
lock->holders[3], \
|
||||
lock->holders[4], \
|
||||
lock->holders[5], \
|
||||
lock->holders[6], \
|
||||
lock->holders[7], \
|
||||
lock->nHolding, \
|
||||
lock->activeHolders[1], \
|
||||
lock->activeHolders[2], \
|
||||
lock->activeHolders[3], \
|
||||
lock->activeHolders[4], \
|
||||
lock->activeHolders[5], \
|
||||
lock->activeHolders[6], \
|
||||
lock->activeHolders[7], \
|
||||
lock->nActive, \
|
||||
lock->waitProcs.size, \
|
||||
lock_types[type])
|
||||
|
||||
#define XID_PRINT(where,xidentP) \
|
||||
if (((LOCKDEBUG(XIDENT_LOCKMETHOD(*(xidentP))) >= 1) \
|
||||
&& (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId \
|
||||
>= lockDebugOidMin)) \
|
||||
|| (lockDebugRelation && \
|
||||
(((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId \
|
||||
== lockDebugRelation))) \
|
||||
XID_PRINT_AUX(where,xidentP)
|
||||
|
||||
#define XID_PRINT_AUX(where,xidentP) \
|
||||
TPRINTF(TRACE_ALL, \
|
||||
"%s: xid(%x) lock(%x) tbl(%d) pid(%d) xid(%u) " \
|
||||
"hold(%d,%d,%d,%d,%d,%d,%d)=%d", \
|
||||
where, \
|
||||
MAKE_OFFSET(xidentP), \
|
||||
xidentP->tag.lock, \
|
||||
XIDENT_LOCKMETHOD(*(xidentP)), \
|
||||
xidentP->tag.pid, \
|
||||
xidentP->tag.xid, \
|
||||
xidentP->holders[1], \
|
||||
xidentP->holders[2], \
|
||||
xidentP->holders[3], \
|
||||
xidentP->holders[4], \
|
||||
xidentP->holders[5], \
|
||||
xidentP->holders[6], \
|
||||
xidentP->holders[7], \
|
||||
xidentP->nHolding)
|
||||
|
||||
#else /* !LOCK_MGR_DEBUG */
|
||||
#define LOCK_PRINT(where,lock,type)
|
||||
#define LOCK_PRINT_AUX(where,lock,type)
|
||||
#define XID_PRINT(where,xidentP)
|
||||
#define XID_PRINT_AUX(where,xidentP)
|
||||
#endif /* !LOCK_MGR_DEBUG */
|
||||
|
||||
static char *lock_types[] = {
|
||||
static char *lock_types[] =
|
||||
{
|
||||
"INVALID",
|
||||
"AccessShareLock",
|
||||
"RowShareLock",
|
||||
@ -149,6 +54,89 @@ static char *lock_types[] = {
|
||||
"AccessExclusiveLock"
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
|
||||
/*------
|
||||
* The following configuration options are available for lock debugging:
|
||||
*
|
||||
* trace_locks -- give a bunch of output what's going on in this file
|
||||
* trace_userlocks -- same but for user locks
|
||||
* trace_lock_oidmin-- do not trace locks for tables below this oid
|
||||
* (use to avoid output on system tables)
|
||||
* trace_lock_table -- trace locks on this table (oid) unconditionally
|
||||
* debug_deadlocks -- currently dumps locks at untimely occasions ;)
|
||||
* Furthermore, but in storage/ipc/spin.c:
|
||||
* trace_spinlocks -- trace spinlocks (pretty useless)
|
||||
*
|
||||
* Define LOCK_DEBUG at compile time to get all this enabled.
|
||||
*/
|
||||
|
||||
int Trace_lock_oidmin = BootstrapObjectIdData;
|
||||
bool Trace_locks = false;
|
||||
bool Trace_userlocks = false;
|
||||
int Trace_lock_table = 0;
|
||||
bool Debug_deadlocks = false;
|
||||
|
||||
|
||||
inline static bool
|
||||
LOCK_DEBUG_ENABLED(const LOCK * lock)
|
||||
{
|
||||
return
|
||||
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|
||||
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
|
||||
&& (lock->tag.relId >= Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
|
||||
}
|
||||
|
||||
|
||||
inline static void
|
||||
LOCK_PRINT(const char * where, const LOCK * lock, LOCKMODE type)
|
||||
{
|
||||
if (LOCK_DEBUG_ENABLED(lock))
|
||||
elog(DEBUG,
|
||||
"%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) mask(%x) "
|
||||
"hold(%d,%d,%d,%d,%d,%d,%d)=%d "
|
||||
"act(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
|
||||
where, MAKE_OFFSET(lock),
|
||||
lock->tag.lockmethod, lock->tag.relId, lock->tag.dbId,
|
||||
lock->tag.objId.blkno, lock->mask,
|
||||
lock->holders[1], lock->holders[2], lock->holders[3], lock->holders[4],
|
||||
lock->holders[5], lock->holders[6], lock->holders[7], lock->nHolding,
|
||||
lock->activeHolders[1], lock->activeHolders[2], lock->activeHolders[3],
|
||||
lock->activeHolders[4], lock->activeHolders[5], lock->activeHolders[6],
|
||||
lock->activeHolders[7], lock->nActive,
|
||||
lock->waitProcs.size, lock_types[type]);
|
||||
}
|
||||
|
||||
|
||||
inline static void
|
||||
XID_PRINT(const char * where, const XIDLookupEnt * xidentP)
|
||||
{
|
||||
if (
|
||||
(((XIDENT_LOCKMETHOD(*xidentP) == DEFAULT_LOCKMETHOD && Trace_locks)
|
||||
|| (XIDENT_LOCKMETHOD(*xidentP) == USER_LOCKMETHOD && Trace_userlocks))
|
||||
&& (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId >= Trace_lock_oidmin))
|
||||
|| (Trace_lock_table && (((LOCK *)MAKE_PTR(xidentP->tag.lock))->tag.relId == Trace_lock_table))
|
||||
)
|
||||
elog(DEBUG,
|
||||
"%s: xid(%lx) lock(%lx) tbl(%d) pid(%d) xid(%u) hold(%d,%d,%d,%d,%d,%d,%d)=%d",
|
||||
where, MAKE_OFFSET(xidentP), xidentP->tag.lock, XIDENT_LOCKMETHOD(*(xidentP)),
|
||||
xidentP->tag.pid, xidentP->tag.xid,
|
||||
xidentP->holders[1], xidentP->holders[2], xidentP->holders[3], xidentP->holders[4],
|
||||
xidentP->holders[5], xidentP->holders[6], xidentP->holders[7], xidentP->nHolding);
|
||||
}
|
||||
|
||||
#else /* not LOCK_DEBUG */
|
||||
|
||||
#define LOCK_PRINT(where, lock, type)
|
||||
#define XID_PRINT(where, xidentP)
|
||||
|
||||
#endif /* not LOCK_DEBUG */
|
||||
|
||||
|
||||
|
||||
SPINLOCK LockMgrLock; /* in Shmem or created in
|
||||
* CreateSpinlocks() */
|
||||
|
||||
@ -192,16 +180,6 @@ InitLocks()
|
||||
BITS_ON[i] = bit;
|
||||
BITS_OFF[i] = ~bit;
|
||||
}
|
||||
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
|
||||
/*
|
||||
* If lockDebugOidMin value has not been specified in pg_options set a
|
||||
* default value.
|
||||
*/
|
||||
if (!lockDebugOidMin)
|
||||
lockDebugOidMin = BootstrapObjectIdData;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -------------------
|
||||
@ -488,18 +466,9 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
int status;
|
||||
TransactionId xid;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||
#ifdef USER_LOCKS_DEBUG
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u] %s",
|
||||
locktag->objId.blkno,
|
||||
lock_types[lockmode]);
|
||||
}
|
||||
#endif
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(DEBUG, "LockAcquire: user lock [%u] %s", locktag->objId.blkno, lock_types[lockmode]);
|
||||
#endif
|
||||
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
@ -573,8 +542,9 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
#ifdef USE_XIDTAG_LOCKMETHOD
|
||||
item.tag.lockmethod = lockmethod;
|
||||
#endif
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
item.tag.pid = MyProcPid;
|
||||
item.tag.xid = xid = 0;
|
||||
@ -584,10 +554,10 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
xid = GetCurrentTransactionId();
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
}
|
||||
#else
|
||||
#else /* not USER_LOCKS */
|
||||
xid = GetCurrentTransactionId();
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
#endif
|
||||
#endif /* not USER_LOCKS */
|
||||
|
||||
/*
|
||||
* Find or create an xid entry with this tag
|
||||
@ -688,7 +658,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
* User locks are non blocking. If we can't acquire a lock we must
|
||||
* remove the xid entry and return FALSE without waiting.
|
||||
*/
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
if (!result->nHolding)
|
||||
{
|
||||
@ -700,7 +670,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
elog(NOTICE, "LockAcquire: remove xid, table corrupted");
|
||||
}
|
||||
else
|
||||
XID_PRINT_AUX("LockAcquire: NHOLDING", result);
|
||||
XID_PRINT("LockAcquire: NHOLDING", result);
|
||||
lock->nHolding--;
|
||||
lock->holders[lockmode]--;
|
||||
LOCK_PRINT("LockAcquire: user lock failed", lock, lockmode);
|
||||
@ -709,7 +679,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
SpinRelease(masterLock);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
#endif /* USER_LOCKS */
|
||||
|
||||
/*
|
||||
* Construct bitmask of locks we hold before going to sleep.
|
||||
@ -737,8 +707,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
*/
|
||||
if (!((result->nHolding > 0) && (result->holders[lockmode] > 0)))
|
||||
{
|
||||
XID_PRINT_AUX("LockAcquire: INCONSISTENT ", result);
|
||||
LOCK_PRINT_AUX("LockAcquire: INCONSISTENT ", lock, lockmode);
|
||||
XID_PRINT("LockAcquire: INCONSISTENT", result);
|
||||
LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
|
||||
/* Should we retry ? */
|
||||
SpinRelease(masterLock);
|
||||
return FALSE;
|
||||
@ -781,11 +751,6 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
|
||||
int i,
|
||||
tmpMask;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
#endif
|
||||
|
||||
numLockModes = LockMethodTable[lockmethod]->ctl->numLockModes;
|
||||
xidTable = LockMethodTable[lockmethod]->xidHash;
|
||||
|
||||
@ -814,17 +779,14 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
|
||||
item.tag.lockmethod = lockmethod;
|
||||
#endif
|
||||
#ifdef USER_LOCKS
|
||||
is_user_lock = (lockmethod == 2);
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
item.tag.pid = MyProcPid;
|
||||
item.tag.xid = 0;
|
||||
}
|
||||
else
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
#else
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
#endif
|
||||
TransactionIdStore(xid, &item.tag.xid);
|
||||
|
||||
/*
|
||||
* Find or create an xid entry with this tag
|
||||
@ -851,7 +813,7 @@ LockResolveConflicts(LOCKMETHOD lockmethod,
|
||||
*/
|
||||
MemSet(result->holders, 0, numLockModes * sizeof(*(lock->holders)));
|
||||
result->nHolding = 0;
|
||||
XID_PRINT_AUX("LockResolveConflicts: NOT FOUND", result);
|
||||
XID_PRINT("LockResolveConflicts: NOT FOUND", result);
|
||||
}
|
||||
else
|
||||
XID_PRINT("LockResolveConflicts: found", result);
|
||||
@ -946,7 +908,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
|
||||
* synchronization for this queue. That will not be true if/when
|
||||
* people can be deleted from the queue by a SIGINT or something.
|
||||
*/
|
||||
LOCK_PRINT_AUX("WaitOnLock: sleeping on lock", lock, lockmode);
|
||||
LOCK_PRINT("WaitOnLock: sleeping on lock", lock, lockmode);
|
||||
strcpy(old_status, PS_STATUS);
|
||||
strcpy(new_status, PS_STATUS);
|
||||
strcat(new_status, " waiting");
|
||||
@ -965,7 +927,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
|
||||
*/
|
||||
lock->nHolding--;
|
||||
lock->holders[lockmode]--;
|
||||
LOCK_PRINT_AUX("WaitOnLock: aborting on lock", lock, lockmode);
|
||||
LOCK_PRINT("WaitOnLock: aborting on lock", lock, lockmode);
|
||||
Assert((lock->nHolding >= 0) && (lock->holders[lockmode] >= 0));
|
||||
Assert(lock->nActive <= lock->nHolding);
|
||||
if (lock->activeHolders[lockmode] == lock->holders[lockmode])
|
||||
@ -979,7 +941,7 @@ WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode)
|
||||
if (lock->activeHolders[lockmode] == lock->holders[lockmode])
|
||||
lock->waitMask &= BITS_OFF[lockmode];
|
||||
PS_SET_STATUS(old_status);
|
||||
LOCK_PRINT_AUX("WaitOnLock: wakeup on lock", lock, lockmode);
|
||||
LOCK_PRINT("WaitOnLock: wakeup on lock", lock, lockmode);
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
@ -1005,30 +967,15 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
HTAB *xidTable;
|
||||
TransactionId xid;
|
||||
bool wakeupNeeded = true;
|
||||
int trace_flag;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u] %d",
|
||||
locktag->objId.blkno,
|
||||
lockmode);
|
||||
}
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(DEBUG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
|
||||
#endif
|
||||
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
locktag->lockmethod = lockmethod;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
trace_flag = \
|
||||
(lockmethod == USER_LOCKMETHOD) ? TRACE_USERLOCKS : TRACE_LOCKS;
|
||||
#else
|
||||
trace_flag = TRACE_LOCKS;
|
||||
#endif
|
||||
|
||||
Assert(lockmethod < NumLockMethods);
|
||||
lockMethodTable = LockMethodTable[lockmethod];
|
||||
if (!lockMethodTable)
|
||||
@ -1064,14 +1011,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
if (!found)
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
elog(NOTICE, "LockRelease: locktable lookup failed, no lock");
|
||||
elog(NOTICE, "LockRelease: no such lock");
|
||||
return FALSE;
|
||||
}
|
||||
LOCK_PRINT("LockRelease: found", lock, lockmode);
|
||||
@ -1091,7 +1031,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
item.tag.lockmethod = lockmethod;
|
||||
#endif
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
item.tag.pid = MyProcPid;
|
||||
item.tag.xid = xid = 0;
|
||||
@ -1116,8 +1056,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
#ifdef USER_LOCKS
|
||||
if (!found && is_user_lock)
|
||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
|
||||
if (!found && lockmethod == USER_LOCKMETHOD)
|
||||
elog(NOTICE, "LockRelease: no lock with this tag");
|
||||
else
|
||||
#endif
|
||||
elog(NOTICE, "LockRelease: xid table corrupted");
|
||||
@ -1133,7 +1073,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
if (!(result->holders[lockmode] > 0))
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
XID_PRINT_AUX("LockAcquire: WRONGTYPE", result);
|
||||
XID_PRINT("LockAcquire: WRONGTYPE", result);
|
||||
elog(NOTICE, "LockRelease: you don't own a lock of type %s",
|
||||
lock_types[lockmode]);
|
||||
Assert(result->holders[lockmode] >= 0);
|
||||
@ -1234,14 +1174,10 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
||||
|
||||
if (wakeupNeeded)
|
||||
ProcLockWakeup(&(lock->waitProcs), lockmethod, lock);
|
||||
else
|
||||
{
|
||||
if (((LOCKDEBUG(LOCK_LOCKMETHOD(*(lock))) >= 1) \
|
||||
&&(lock->tag.relId >= lockDebugOidMin)) \
|
||||
||\
|
||||
(lockDebugRelation && (lock->tag.relId == lockDebugRelation)))
|
||||
TPRINTF(TRACE_ALL, "LockRelease: no wakeup needed");
|
||||
}
|
||||
#ifdef LOCK_DEBUG
|
||||
else if (LOCK_DEBUG_ENABLED(lock))
|
||||
elog(DEBUG, "LockRelease: no wakeup needed");
|
||||
#endif
|
||||
|
||||
SpinRelease(masterLock);
|
||||
return TRUE;
|
||||
@ -1265,20 +1201,13 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
numLockModes;
|
||||
LOCK *lock;
|
||||
bool found;
|
||||
int trace_flag;
|
||||
int xidtag_lockmethod,
|
||||
nleft;
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock_table;
|
||||
|
||||
is_user_lock_table = (lockmethod == USER_LOCKMETHOD);
|
||||
trace_flag = (lockmethod == 2) ? TRACE_USERLOCKS : TRACE_LOCKS;
|
||||
#else
|
||||
trace_flag = TRACE_LOCKS;
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
elog(DEBUG, "LockReleaseAll: lockmethod=%d, pid=%d", lockmethod, MyProcPid);
|
||||
#endif
|
||||
TPRINTF(trace_flag, "LockReleaseAll: lockmethod=%d, pid=%d",
|
||||
lockmethod, MyProcPid);
|
||||
|
||||
nleft = 0;
|
||||
|
||||
@ -1313,7 +1242,7 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
|
||||
|
||||
xidtag_lockmethod = XIDENT_LOCKMETHOD(*xidLook);
|
||||
if ((xidtag_lockmethod == lockmethod) && pg_options[trace_flag])
|
||||
if (xidtag_lockmethod == lockmethod)
|
||||
{
|
||||
XID_PRINT("LockReleaseAll", xidLook);
|
||||
LOCK_PRINT("LockReleaseAll", lock, 0);
|
||||
@ -1324,9 +1253,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
elog(NOTICE, "LockReleaseAll: xid/lock method mismatch: %d != %d",
|
||||
xidtag_lockmethod, lock->tag.lockmethod);
|
||||
#endif
|
||||
if ((xidtag_lockmethod != lockmethod) && (trace_flag >= 2))
|
||||
if (xidtag_lockmethod != lockmethod)
|
||||
{
|
||||
TPRINTF(trace_flag, "LockReleaseAll: skipping other table");
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
@ -1338,13 +1266,15 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
Assert(xidLook->nHolding <= lock->nHolding);
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock_table)
|
||||
if (lockmethod == USER_LOCKMETHOD)
|
||||
{
|
||||
if ((xidLook->tag.pid == 0) || (xidLook->tag.xid != 0))
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS,
|
||||
"LockReleaseAll: skiping normal lock [%d,%d,%d]",
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Trace_userlocks)
|
||||
elog(DEBUG, "LockReleaseAll: skiping normal lock [%ld,%d,%d]",
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#endif /* LOCK_DEBUG */
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
@ -1358,29 +1288,29 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
TPRINTF(TRACE_USERLOCKS,
|
||||
"LockReleaseAll: releasing user lock [%u] [%d,%d,%d]",
|
||||
lock->tag.objId.blkno,
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Trace_userlocks)
|
||||
elog(DEBUG, "LockReleaseAll: releasing user lock [%u] [%ld,%d,%d]",
|
||||
lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#endif /* LOCK_DEBUG */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* Can't check xidLook->tag.xid, can be 0 also for normal
|
||||
* locks
|
||||
* Can't check xidLook->tag.xid, can be 0 also for normal locks
|
||||
*/
|
||||
if (xidLook->tag.pid != 0)
|
||||
{
|
||||
TPRINTF(TRACE_LOCKS,
|
||||
"LockReleaseAll: skiping user lock [%u] [%d,%d,%d]",
|
||||
lock->tag.objId.blkno,
|
||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Trace_userlocks)
|
||||
elog(DEBUG, "LockReleaseAll: skiping user lock [%u] [%ld,%d,%d]",
|
||||
lock->tag.objId.blkno, xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||
#endif /* LOCK_DEBUG */
|
||||
nleft++;
|
||||
goto next_item;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* USER_LOCKS */
|
||||
|
||||
/* ------------------
|
||||
* fix the general lock stats
|
||||
@ -1486,12 +1416,18 @@ next_item:
|
||||
*/
|
||||
if (nleft == 0)
|
||||
{
|
||||
TPRINTF(trace_flag, "LockReleaseAll: reinitializing lockQueue");
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
elog(DEBUG, "LockReleaseAll: reinitializing lockQueue");
|
||||
#endif
|
||||
SHMQueueInit(lockQueue);
|
||||
}
|
||||
|
||||
SpinRelease(masterLock);
|
||||
TPRINTF(trace_flag, "LockReleaseAll: done");
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
elog(DEBUG, "LockReleaseAll: done");
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1753,10 +1689,7 @@ DeadLockCheck(void *proc, LOCK *findlock)
|
||||
/*
|
||||
* Blocked by others - no deadlock...
|
||||
*/
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
LOCK_PRINT("DeadLockCheck: blocked by others",
|
||||
lock, waitProc->token);
|
||||
#endif
|
||||
LOCK_PRINT("DeadLockCheck: blocked by others", lock, waitProc->token);
|
||||
waitProc = (PROC *) MAKE_PTR(waitProc->links.prev);
|
||||
continue;
|
||||
}
|
||||
@ -1817,15 +1750,9 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
||||
/* Assume that no one will modify the result */
|
||||
static int empty_array[] = {20, 1, 0, 0, 0};
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
int is_user_lock;
|
||||
|
||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u]",
|
||||
locktag->objId.blkno);
|
||||
}
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
|
||||
elog(DEBUG, "LockOwners: user lock tag [%u]", locktag->objId.blkno);
|
||||
#endif
|
||||
|
||||
/* This must be changed when short term locks will be used */
|
||||
@ -1865,14 +1792,7 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
||||
if (!found)
|
||||
{
|
||||
SpinRelease(masterLock);
|
||||
#ifdef USER_LOCKS
|
||||
if (is_user_lock)
|
||||
{
|
||||
TPRINTF(TRACE_USERLOCKS, "LockOwners: no lock with this tag");
|
||||
return (ArrayType *) &empty_array;
|
||||
}
|
||||
#endif
|
||||
elog(NOTICE, "LockOwners: locktable lookup failed, no lock");
|
||||
elog(NOTICE, "LockOwners: no such lock");
|
||||
return (ArrayType *) &empty_array;
|
||||
}
|
||||
LOCK_PRINT("LockOwners: found", lock, 0);
|
||||
@ -1974,9 +1894,9 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
||||
return array;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* NOT_USED */
|
||||
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
#ifdef LOCK_DEBUG
|
||||
/*
|
||||
* Dump all locks in the proc->lockQueue. Must have already acquired
|
||||
* the masterLock.
|
||||
@ -2016,7 +1936,7 @@ DumpLocks()
|
||||
end = MAKE_OFFSET(lockQueue);
|
||||
|
||||
if (MyProc->waitLock)
|
||||
LOCK_PRINT_AUX("DumpLocks: waiting on", MyProc->waitLock, 0);
|
||||
LOCK_PRINT("DumpLocks: waiting on", MyProc->waitLock, 0);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -2035,8 +1955,8 @@ DumpLocks()
|
||||
done = (xidLook->queue.next == end);
|
||||
lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
|
||||
|
||||
XID_PRINT_AUX("DumpLocks", xidLook);
|
||||
LOCK_PRINT_AUX("DumpLocks", lock, 0);
|
||||
XID_PRINT("DumpLocks", xidLook);
|
||||
LOCK_PRINT("DumpLocks", lock, 0);
|
||||
|
||||
if (done)
|
||||
break;
|
||||
@ -2078,18 +1998,18 @@ DumpAllLocks()
|
||||
xidTable = lockMethodTable->xidHash;
|
||||
|
||||
if (MyProc->waitLock)
|
||||
LOCK_PRINT_AUX("DumpAllLocks: waiting on", MyProc->waitLock, 0);
|
||||
LOCK_PRINT("DumpAllLocks: waiting on", MyProc->waitLock, 0);
|
||||
|
||||
hash_seq(NULL);
|
||||
while ((xidLook = (XIDLookupEnt *) hash_seq(xidTable)) &&
|
||||
(xidLook != (XIDLookupEnt *) TRUE))
|
||||
{
|
||||
XID_PRINT_AUX("DumpAllLocks", xidLook);
|
||||
XID_PRINT("DumpAllLocks", xidLook);
|
||||
|
||||
if (xidLook->tag.lock)
|
||||
{
|
||||
lock = (LOCK *) MAKE_PTR(xidLook->tag.lock);
|
||||
LOCK_PRINT_AUX("DumpAllLocks", lock, 0);
|
||||
LOCK_PRINT("DumpAllLocks", lock, 0);
|
||||
}
|
||||
else
|
||||
elog(DEBUG, "DumpAllLocks: xidLook->tag.lock = NULL");
|
||||
@ -2102,4 +2022,4 @@ DumpAllLocks()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* LOCK_DEBUG */
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.73 2000/05/30 00:49:52 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.74 2000/05/31 00:28:30 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -47,7 +47,7 @@
|
||||
* This is so that we can support more backends. (system-wide semaphore
|
||||
* sets run out pretty fast.) -ay 4/95
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.73 2000/05/30 00:49:52 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.74 2000/05/31 00:28:30 petere Exp $
|
||||
*/
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
@ -66,13 +66,14 @@
|
||||
/* In Ultrix and QNX, sem.h must be included after ipc.h */
|
||||
#include <sys/sem.h>
|
||||
|
||||
#include "storage/lock.h"
|
||||
#include "storage/proc.h"
|
||||
|
||||
void HandleDeadLock(SIGNAL_ARGS);
|
||||
static void ProcFreeAllSemaphores(void);
|
||||
static bool GetOffWaitqueue(PROC *);
|
||||
|
||||
#define DeadlockCheckTimer pg_options[OPT_DEADLOCKTIMEOUT]
|
||||
int DeadlockTimeout = 1000;
|
||||
|
||||
/* --------------------
|
||||
* Spin lock for manipulating the shared process data structure:
|
||||
@ -633,8 +634,8 @@ ins:;
|
||||
* --------------
|
||||
*/
|
||||
MemSet(&timeval, 0, sizeof(struct itimerval));
|
||||
timeval.it_value.tv_sec = \
|
||||
(DeadlockCheckTimer ? DeadlockCheckTimer : DEADLOCK_CHECK_TIMER);
|
||||
timeval.it_value.tv_sec = DeadlockTimeout / 1000;
|
||||
timeval.it_value.tv_usec = (DeadlockTimeout % 1000) * 1000;
|
||||
|
||||
SetWaitingForLock(true);
|
||||
do
|
||||
@ -663,6 +664,7 @@ ins:;
|
||||
* ---------------
|
||||
*/
|
||||
timeval.it_value.tv_sec = 0;
|
||||
timeval.it_value.tv_usec = 0;
|
||||
if (setitimer(ITIMER_REAL, &timeval, &dummy))
|
||||
elog(FATAL, "ProcSleep: Unable to diable timer for process wakeup");
|
||||
|
||||
@ -675,7 +677,7 @@ ins:;
|
||||
|
||||
rt:;
|
||||
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
#ifdef LOCK_DEBUG
|
||||
/* Just to get meaningful debug messages from DumpLocks() */
|
||||
MyProc->waitLock = (LOCK *) NULL;
|
||||
#endif
|
||||
@ -723,7 +725,6 @@ ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod, LOCK *lock)
|
||||
{
|
||||
PROC *proc;
|
||||
int count = 0;
|
||||
int trace_flag;
|
||||
int last_locktype = 0;
|
||||
int queue_size = queue->size;
|
||||
|
||||
@ -783,14 +784,13 @@ ProcLockWakeup(PROC_QUEUE *queue, LOCKMETHOD lockmethod, LOCK *lock)
|
||||
else
|
||||
{
|
||||
/* Something is still blocking us. May have deadlocked. */
|
||||
trace_flag = (lock->tag.lockmethod == USER_LOCKMETHOD) ? \
|
||||
TRACE_USERLOCKS : TRACE_LOCKS;
|
||||
TPRINTF(trace_flag,
|
||||
"ProcLockWakeup: lock(%x) can't wake up any process",
|
||||
MAKE_OFFSET(lock));
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
if (pg_options[trace_flag] >= 2)
|
||||
#ifdef LOCK_DEBUG
|
||||
if (lock->tag.lockmethod == USER_LOCKMETHOD ? Trace_userlocks : Trace_locks)
|
||||
{
|
||||
elog(DEBUG, "ProcLockWakeup: lock(%lx) can't wake up any process", MAKE_OFFSET(lock));
|
||||
if (Debug_deadlocks)
|
||||
DumpAllLocks();
|
||||
}
|
||||
#endif
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
@ -803,7 +803,7 @@ ProcAddLock(SHM_QUEUE *elem)
|
||||
}
|
||||
|
||||
/* --------------------
|
||||
* We only get to this routine if we got SIGALRM after DEADLOCK_CHECK_TIMER
|
||||
* We only get to this routine if we got SIGALRM after DeadlockTimeout
|
||||
* while waiting for a lock to be released by some other process. If we have
|
||||
* a real deadlock, we must also indicate that I'm no longer waiting
|
||||
* on a lock so that other processes don't try to wake me up and screw
|
||||
@ -852,8 +852,9 @@ HandleDeadLock(SIGNAL_ARGS)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
DumpAllLocks();
|
||||
#ifdef LOCK_DEBUG
|
||||
if (Debug_deadlocks)
|
||||
DumpAllLocks();
|
||||
#endif
|
||||
|
||||
MyProc->errType = STATUS_NOT_FOUND;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.156 2000/05/29 05:45:16 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.157 2000/05/31 00:28:31 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -58,40 +58,25 @@
|
||||
#include "storage/proc.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/temprel.h"
|
||||
#include "utils/trace.h"
|
||||
#include "utils/guc.h"
|
||||
#ifdef MULTIBYTE
|
||||
#include "mb/pg_wchar.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Trace flags, see backend/utils/misc/trace.c
|
||||
*/
|
||||
#define Verbose pg_options[TRACE_VERBOSE]
|
||||
#define DebugPrintQuery pg_options[TRACE_QUERY]
|
||||
#define DebugPrintPlan pg_options[TRACE_PLAN]
|
||||
#define DebugPrintParse pg_options[TRACE_PARSE]
|
||||
#define DebugPrintRewrittenParsetree \
|
||||
pg_options[TRACE_REWRITTEN]
|
||||
#define DebugPPrintPlan pg_options[TRACE_PRETTY_PLAN]
|
||||
#define DebugPPrintParse pg_options[TRACE_PRETTY_PARSE]
|
||||
#define DebugPPrintRewrittenParsetree \
|
||||
pg_options[TRACE_PRETTY_REWRITTEN]
|
||||
#define ShowParserStats pg_options[TRACE_PARSERSTATS]
|
||||
#define ShowPlannerStats pg_options[TRACE_PLANNERSTATS]
|
||||
#define ShowExecutorStats pg_options[TRACE_EXECUTORSTATS]
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
#define LockDebug pg_options[TRACE_LOCKS]
|
||||
#endif
|
||||
|
||||
#define DeadlockCheckTimer pg_options[OPT_DEADLOCKTIMEOUT]
|
||||
#define HostnameLookup pg_options[OPT_HOSTLOOKUP]
|
||||
#define ShowPortNumber pg_options[OPT_SHOWPORTNUMBER]
|
||||
|
||||
/* ----------------
|
||||
* global variables
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX For ps display. That stuff needs to be cleaned up.
|
||||
*/
|
||||
bool HostnameLookup;
|
||||
bool ShowPortNumber;
|
||||
|
||||
bool Log_connections = false;
|
||||
|
||||
CommandDest whereToSendOutput = Debug;
|
||||
|
||||
/* Define status buffer needed by PS_SET_STATUS */
|
||||
@ -112,7 +97,6 @@ extern int lockingOff;
|
||||
extern int NBuffers;
|
||||
|
||||
int dontExecute = 0;
|
||||
static int ShowStats;
|
||||
static bool IsEmptyQuery = false;
|
||||
|
||||
/* note: these declarations had better match tcopprot.h */
|
||||
@ -155,6 +139,14 @@ static int InteractiveBackend(StringInfo inBuf);
|
||||
static int SocketBackend(StringInfo inBuf);
|
||||
static int ReadCommand(StringInfo inBuf);
|
||||
static void pg_exec_query(char *query_string);
|
||||
static void SigHupHandler(SIGNAL_ARGS);
|
||||
|
||||
/*
|
||||
* Flag to mark SIGHUP. Whenever the main loop comes around it
|
||||
* will reread the configuration file. (Better than doing the
|
||||
* reading in the signal handler, ey?)
|
||||
*/
|
||||
static volatile bool got_SIGHUP = false;
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@ -240,11 +232,7 @@ InteractiveBackend(StringInfo inBuf)
|
||||
}
|
||||
|
||||
if (end)
|
||||
{
|
||||
if (Verbose)
|
||||
puts("EOF");
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* otherwise we have a user query so process it.
|
||||
@ -380,21 +368,21 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
|
||||
Query *querytree;
|
||||
List *new_list;
|
||||
|
||||
if (DebugPrintQuery)
|
||||
TPRINTF(TRACE_QUERY, "query: %s", query_string);
|
||||
if (Debug_print_query)
|
||||
elog(DEBUG, "query: %s", query_string);
|
||||
|
||||
/* ----------------
|
||||
* (1) parse the request string into a list of parse trees
|
||||
* ----------------
|
||||
*/
|
||||
if (ShowParserStats)
|
||||
if (Show_parser_stats)
|
||||
ResetUsage();
|
||||
|
||||
querytree_list = parser(query_string, typev, nargs);
|
||||
|
||||
if (ShowParserStats)
|
||||
if (Show_parser_stats)
|
||||
{
|
||||
fprintf(stderr, "! Parser Stats:\n");
|
||||
fprintf(StatFp, "PARSER STATISTICS\n");
|
||||
ShowUsage();
|
||||
}
|
||||
|
||||
@ -410,18 +398,15 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
|
||||
{
|
||||
querytree = (Query *) lfirst(querytree_list_item);
|
||||
|
||||
if (DebugPrintParse || DebugPPrintParse)
|
||||
if (Debug_print_parse)
|
||||
{
|
||||
if (DebugPPrintParse)
|
||||
if (Debug_pretty_print)
|
||||
{
|
||||
TPRINTF(TRACE_PRETTY_PARSE, "parser outputs:");
|
||||
elog(DEBUG, "parse tree:");
|
||||
nodeDisplay(querytree);
|
||||
}
|
||||
else
|
||||
{
|
||||
TPRINTF(TRACE_PARSE, "parser outputs:");
|
||||
printf("\n%s\n\n", nodeToString(querytree));
|
||||
}
|
||||
elog(DEBUG, "parse tree: %s", nodeToString(querytree));
|
||||
}
|
||||
|
||||
if (querytree->commandType == CMD_UTILITY)
|
||||
@ -464,12 +449,11 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
|
||||
}
|
||||
}
|
||||
|
||||
if (DebugPrintRewrittenParsetree || DebugPPrintRewrittenParsetree)
|
||||
if (Debug_print_rewritten)
|
||||
{
|
||||
if (DebugPPrintRewrittenParsetree)
|
||||
if (Debug_pretty_print)
|
||||
{
|
||||
TPRINTF(TRACE_PRETTY_REWRITTEN, "after rewriting:");
|
||||
|
||||
elog(DEBUG, "rewritten parse tree:");
|
||||
foreach(querytree_list_item, querytree_list)
|
||||
{
|
||||
querytree = (Query *) lfirst(querytree_list_item);
|
||||
@ -479,12 +463,12 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
|
||||
}
|
||||
else
|
||||
{
|
||||
TPRINTF(TRACE_REWRITTEN, "after rewriting:");
|
||||
elog(DEBUG, "rewritten parse tree:");
|
||||
|
||||
foreach(querytree_list_item, querytree_list)
|
||||
{
|
||||
querytree = (Query *) lfirst(querytree_list_item);
|
||||
printf("\n%s\n\n", nodeToString(querytree));
|
||||
elog(DEBUG, "%s", nodeToString(querytree));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -503,15 +487,15 @@ pg_plan_query(Query *querytree)
|
||||
if (querytree->commandType == CMD_UTILITY)
|
||||
return NULL;
|
||||
|
||||
if (ShowPlannerStats)
|
||||
if (Show_planner_stats)
|
||||
ResetUsage();
|
||||
|
||||
/* call that optimizer */
|
||||
plan = planner(querytree);
|
||||
|
||||
if (ShowPlannerStats)
|
||||
if (Show_planner_stats)
|
||||
{
|
||||
fprintf(stderr, "! Planner Stats:\n");
|
||||
fprintf(stderr, "PLANNER STATISTICS\n");
|
||||
ShowUsage();
|
||||
}
|
||||
|
||||
@ -519,18 +503,15 @@ pg_plan_query(Query *querytree)
|
||||
* Print plan if debugging.
|
||||
* ----------------
|
||||
*/
|
||||
if (DebugPrintPlan || DebugPPrintPlan)
|
||||
if (Debug_print_plan)
|
||||
{
|
||||
if (DebugPPrintPlan)
|
||||
if (Debug_pretty_print)
|
||||
{
|
||||
TPRINTF(TRACE_PRETTY_PLAN, "plan:");
|
||||
elog(DEBUG, "plan:");
|
||||
nodeDisplay(plan);
|
||||
}
|
||||
else
|
||||
{
|
||||
TPRINTF(TRACE_PLAN, "plan:");
|
||||
printf("\n%s\n\n", nodeToString(plan));
|
||||
}
|
||||
elog(DEBUG, "plan: %s", nodeToString(plan));
|
||||
}
|
||||
|
||||
return plan;
|
||||
@ -607,10 +588,10 @@ pg_exec_query_dest(char *query_string, /* string to execute */
|
||||
* because that is done in ProcessUtility.
|
||||
* ----------------
|
||||
*/
|
||||
if (DebugPrintQuery)
|
||||
TPRINTF(TRACE_QUERY, "ProcessUtility: %s", query_string);
|
||||
else if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "ProcessUtility");
|
||||
if (Debug_print_query)
|
||||
elog(DEBUG, "ProcessUtility: %s", query_string);
|
||||
else if (DebugLvl > 1)
|
||||
elog(DEBUG, "ProcessUtility");
|
||||
|
||||
ProcessUtility(querytree->utilityStmt, dest);
|
||||
}
|
||||
@ -653,16 +634,16 @@ pg_exec_query_dest(char *query_string, /* string to execute */
|
||||
/*
|
||||
* execute the plan
|
||||
*/
|
||||
if (ShowExecutorStats)
|
||||
if (Show_executor_stats)
|
||||
ResetUsage();
|
||||
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "ProcessQuery");
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "ProcessQuery");
|
||||
ProcessQuery(querytree, plan, dest);
|
||||
|
||||
if (ShowExecutorStats)
|
||||
if (Show_executor_stats)
|
||||
{
|
||||
fprintf(stderr, "! Executor Stats:\n");
|
||||
fprintf(stderr, "EXECUTOR STATISTICS\n");
|
||||
ShowUsage();
|
||||
}
|
||||
}
|
||||
@ -772,6 +753,12 @@ CancelQuery(void)
|
||||
elog(ERROR, "Query was cancelled.");
|
||||
}
|
||||
|
||||
static void
|
||||
SigHupHandler(SIGNAL_ARGS)
|
||||
{
|
||||
got_SIGHUP = true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
usage(char *progname)
|
||||
@ -785,10 +772,7 @@ usage(char *progname)
|
||||
fprintf(stderr, "\t-C \t\tsuppress version info\n");
|
||||
fprintf(stderr, "\t-D dir\t\tdata directory\n");
|
||||
fprintf(stderr, "\t-E \t\techo query before execution\n");
|
||||
fprintf(stderr, "\t-F \t\tturn off fsync\n");
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
fprintf(stderr, "\t-K lev\t\tset locking debug level [0|1|2]\n");
|
||||
#endif
|
||||
fprintf(stderr, "\t-F \t\tturn fsync off\n");
|
||||
fprintf(stderr, "\t-L \t\tturn off locking\n");
|
||||
fprintf(stderr, "\t-N \t\tdon't use newline as interactive query delimiter\n");
|
||||
fprintf(stderr, "\t-O \t\tallow system table structure changes\n");
|
||||
@ -844,27 +828,19 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
* Set default values for command-line options.
|
||||
*/
|
||||
IsUnderPostmaster = false;
|
||||
ShowStats = 0;
|
||||
ShowParserStats = ShowPlannerStats = ShowExecutorStats = 0;
|
||||
DeadlockCheckTimer = DEADLOCK_CHECK_TIMER;
|
||||
Noversion = false;
|
||||
EchoQuery = false;
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
LockDebug = 0;
|
||||
#endif
|
||||
DataDir = getenv("PGDATA");
|
||||
StatFp = stderr;
|
||||
|
||||
SetProcessingMode(InitProcessing);
|
||||
|
||||
/* Check for PGDATESTYLE environment variable */
|
||||
set_default_datestyle();
|
||||
|
||||
/*
|
||||
* Read default pg_options from file $DATADIR/pg_options.
|
||||
*/
|
||||
if (DataDir)
|
||||
read_pg_options(0);
|
||||
|
||||
/* ----------------
|
||||
* parse command line arguments
|
||||
*
|
||||
@ -884,9 +860,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
|
||||
optind = 1; /* reset after postmaster's usage */
|
||||
|
||||
while ((flag = getopt(argc, argv,
|
||||
"A:B:CD:d:EeFf:iK:LNOPo:p:QS:sT:t:v:W:x:"))
|
||||
!= EOF)
|
||||
while ((flag = getopt(argc, argv, "A:B:CD:d:Eef:FiLNOPo:p:S:st:v:W:x:-:")) != EOF)
|
||||
switch (flag)
|
||||
{
|
||||
case 'A':
|
||||
@ -920,29 +894,21 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
|
||||
case 'D': /* PGDATA directory */
|
||||
if (secure)
|
||||
{
|
||||
if (!DataDir)
|
||||
{
|
||||
DataDir = optarg;
|
||||
/* must be done after DataDir is defined */
|
||||
read_pg_options(0);
|
||||
}
|
||||
DataDir = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': /* debug level */
|
||||
DebugLvl = atoi(optarg);
|
||||
if (DebugLvl >= 1)
|
||||
Verbose = true;
|
||||
if (DebugLvl >= 1);
|
||||
Log_connections = true;
|
||||
if (DebugLvl >= 2)
|
||||
DebugPrintQuery = true;
|
||||
Debug_print_query = true;
|
||||
if (DebugLvl >= 3)
|
||||
DebugPrintParse = true;
|
||||
Debug_print_parse = true;
|
||||
if (DebugLvl >= 4)
|
||||
DebugPrintPlan = true;
|
||||
Debug_print_plan = true;
|
||||
if (DebugLvl >= 5)
|
||||
DebugPPrintRewrittenParsetree = true;
|
||||
Debug_print_rewritten = true;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
@ -970,7 +936,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
* to be "if (secure)".
|
||||
* --------------------
|
||||
*/
|
||||
disableFsync = true;
|
||||
enableFsync = false;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
@ -1007,14 +973,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
dontExecute = 1;
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
#ifdef LOCK_MGR_DEBUG
|
||||
LockDebug = atoi(optarg);
|
||||
#else
|
||||
fprintf(stderr, "Lock debug not compiled in\n");
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
/* --------------------
|
||||
* turn off locking
|
||||
@ -1074,14 +1032,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Q':
|
||||
/* ----------------
|
||||
* Q - set Quiet mode (reduce debugging output)
|
||||
* ----------------
|
||||
*/
|
||||
Verbose = false;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
/* ----------------
|
||||
* S - amount of sort memory to use in 1k bytes
|
||||
@ -1101,15 +1051,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
* s - report usage statistics (timings) after each query
|
||||
* ----------------
|
||||
*/
|
||||
ShowStats = 1;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
/* ----------------
|
||||
* T - tracing options
|
||||
* ----------------
|
||||
*/
|
||||
parse_options(optarg, secure);
|
||||
Show_query_stats = 1;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
@ -1127,14 +1069,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
{
|
||||
case 'p':
|
||||
if (optarg[1] == 'a')
|
||||
ShowParserStats = 1;
|
||||
Show_parser_stats = 1;
|
||||
else if (optarg[1] == 'l')
|
||||
ShowPlannerStats = 1;
|
||||
Show_planner_stats = 1;
|
||||
else
|
||||
errs++;
|
||||
break;
|
||||
case 'e':
|
||||
ShowExecutorStats = 1;
|
||||
Show_executor_stats = 1;
|
||||
break;
|
||||
default:
|
||||
errs++;
|
||||
@ -1188,6 +1130,23 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
#endif
|
||||
break;
|
||||
|
||||
case '-':
|
||||
{
|
||||
/* A little 'long argument' simulation */
|
||||
/* (copy&pasted from PostmasterMain() */
|
||||
size_t equal_pos = strcspn(optarg, "=");
|
||||
char *cp;
|
||||
|
||||
if (optarg[equal_pos] != '=')
|
||||
elog(ERROR, "--%s requires argument", optarg);
|
||||
optarg[equal_pos] = '\0';
|
||||
for(cp = optarg; *cp; cp++)
|
||||
if (*cp == '-')
|
||||
*cp = '_';
|
||||
SetConfigOption(optarg, optarg + equal_pos + 1, PGC_BACKEND);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* ----------------
|
||||
* default: bad command line option
|
||||
@ -1197,11 +1156,11 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
if (ShowStats &&
|
||||
(ShowParserStats || ShowPlannerStats || ShowExecutorStats))
|
||||
if (Show_query_stats &&
|
||||
(Show_parser_stats || Show_planner_stats || Show_executor_stats))
|
||||
{
|
||||
fprintf(stderr, "-s can not be used together with -t.\n");
|
||||
proc_exit(0);
|
||||
elog(NOTICE, "Query statistics are disabled because parser, planner, or executor statistics are on.");
|
||||
Show_query_stats = false;
|
||||
}
|
||||
|
||||
if (!DataDir)
|
||||
@ -1233,7 +1192,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
BlockSig &= ~(sigmask(SIGUSR1));
|
||||
#endif
|
||||
|
||||
pqsignal(SIGHUP, read_pg_options); /* update pg_options from file */
|
||||
pqsignal(SIGHUP, SigHupHandler); /* set flag to read config file */
|
||||
pqsignal(SIGINT, QueryCancelHandler); /* cancel current query */
|
||||
pqsignal(SIGQUIT, handle_warn); /* handle error */
|
||||
pqsignal(SIGTERM, die);
|
||||
@ -1373,53 +1332,22 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
PS_SET_STATUS("startup");
|
||||
}
|
||||
|
||||
|
||||
/* ----------------
|
||||
* print flags
|
||||
* ----------------
|
||||
*/
|
||||
if (Verbose)
|
||||
{
|
||||
if (Verbose)
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE, "started: host=%s user=%s database=%s",
|
||||
remote_host, userName, DBName);
|
||||
}
|
||||
else
|
||||
{
|
||||
TPRINTF(TRACE_VERBOSE, "debug info:");
|
||||
TPRINTF(TRACE_VERBOSE, "\tUser = %s", userName);
|
||||
TPRINTF(TRACE_VERBOSE, "\tRemoteHost = %s", remote_host);
|
||||
TPRINTF(TRACE_VERBOSE, "\tRemotePort = %d", remote_port);
|
||||
TPRINTF(TRACE_VERBOSE, "\tDatabaseName = %s", DBName);
|
||||
TPRINTF(TRACE_VERBOSE, "\tDebug Level = %d", DebugLvl);
|
||||
TPRINTF(TRACE_VERBOSE, "\tNoversion = %c", Noversion ? 't' : 'f');
|
||||
TPRINTF(TRACE_VERBOSE, "\ttimings = %c", ShowStats ? 't' : 'f');
|
||||
TPRINTF(TRACE_VERBOSE, "\tdates = %s",
|
||||
EuroDates ? "European" : "Normal");
|
||||
TPRINTF(TRACE_VERBOSE, "\tbufsize = %d", NBuffers);
|
||||
TPRINTF(TRACE_VERBOSE, "\tsortmem = %d", SortMem);
|
||||
TPRINTF(TRACE_VERBOSE, "\tquery echo = %c", EchoQuery ? 't' : 'f');
|
||||
}
|
||||
}
|
||||
|
||||
if (Log_connections)
|
||||
elog(DEBUG, "connection: host=%s user=%s database=%s",
|
||||
remote_host, userName, DBName);
|
||||
|
||||
/*
|
||||
* general initialization
|
||||
*/
|
||||
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "InitPostgres");
|
||||
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "InitPostgres");
|
||||
InitPostgres(DBName);
|
||||
|
||||
#ifdef MULTIBYTE
|
||||
/* set default client encoding */
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "reset_client_encoding()..");
|
||||
if (DebugLvl > 1)
|
||||
elog(DEBUG, "reset_client_encoding");
|
||||
reset_client_encoding();
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "reset_client_encoding() done.");
|
||||
#endif
|
||||
|
||||
on_shmem_exit(remove_all_temp_relations, NULL);
|
||||
@ -1450,7 +1378,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.156 $ $Date: 2000/05/29 05:45:16 $\n");
|
||||
puts("$Revision: 1.157 $ $Date: 2000/05/31 00:28:31 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1473,9 +1401,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
/* Make sure we are in a valid memory context */
|
||||
MemoryContextSwitchTo(TopMemoryContext);
|
||||
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "AbortCurrentTransaction");
|
||||
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "AbortCurrentTransaction");
|
||||
AbortCurrentTransaction();
|
||||
InError = false;
|
||||
if (ExitAfterAbort)
|
||||
@ -1497,6 +1424,14 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
{
|
||||
PS_SET_STATUS("idle");
|
||||
|
||||
/* XXX this could be moved after ReadCommand below to get more
|
||||
* sensical behaviour */
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
got_SIGHUP = false;
|
||||
ProcessConfigFile(PGC_SIGHUP);
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* (1) tell the frontend we're ready for a new query.
|
||||
*
|
||||
@ -1516,7 +1451,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
EnableNotifyInterrupt();
|
||||
|
||||
/* ----------------
|
||||
* (3) read a command.
|
||||
* (3) read a command (loop blocks here)
|
||||
* ----------------
|
||||
*/
|
||||
firstchar = ReadCommand(parser_input);
|
||||
@ -1544,8 +1479,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
IsEmptyQuery = false;
|
||||
|
||||
/* start an xact for this function invocation */
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "StartTransactionCommand");
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "StartTransactionCommand");
|
||||
StartTransactionCommand();
|
||||
|
||||
if (HandleFunctionRequest() == EOF)
|
||||
@ -1577,12 +1512,12 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
* ----------------
|
||||
*/
|
||||
IsEmptyQuery = false;
|
||||
if (ShowStats)
|
||||
if (Show_query_stats)
|
||||
ResetUsage();
|
||||
|
||||
/* start an xact for this query */
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "StartTransactionCommand");
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "StartTransactionCommand");
|
||||
StartTransactionCommand();
|
||||
|
||||
pg_exec_query(parser_input->data);
|
||||
@ -1593,8 +1528,11 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
*/
|
||||
DeferredTriggerEndQuery();
|
||||
|
||||
if (ShowStats)
|
||||
if (Show_query_stats)
|
||||
{
|
||||
fprintf(StatFp, "QUERY STATISTICS\n");
|
||||
ShowUsage();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1625,8 +1563,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
*/
|
||||
if (!IsEmptyQuery)
|
||||
{
|
||||
if (Verbose)
|
||||
TPRINTF(TRACE_VERBOSE, "CommitTransactionCommand");
|
||||
if (DebugLvl >= 1)
|
||||
elog(DEBUG, "CommitTransactionCommand");
|
||||
PS_SET_STATUS("commit");
|
||||
CommitTransactionCommand();
|
||||
#ifdef SHOW_MEMORY_STATS
|
||||
|
@ -8,19 +8,19 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/error/assert.c,v 1.17 2000/01/26 05:57:20 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/error/assert.c,v 1.18 2000/05/31 00:28:31 petere Exp $
|
||||
*
|
||||
* NOTE
|
||||
* This should eventually work with elog(), dlog(), etc.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils/exc.h"
|
||||
#include "utils/trace.h"
|
||||
|
||||
int
|
||||
ExceptionalCondition(char *conditionName,
|
||||
@ -39,7 +39,7 @@ ExceptionalCondition(char *conditionName,
|
||||
|| !PointerIsValid(fileName)
|
||||
|| !PointerIsValid(exceptionP))
|
||||
{
|
||||
EPRINTF("TRAP: ExceptionalCondition: bad arguments\n");
|
||||
fprintf(stderr, "TRAP: ExceptionalCondition: bad arguments\n");
|
||||
|
||||
ExcAbort(exceptionP,
|
||||
(ExcDetail) detail,
|
||||
@ -48,7 +48,7 @@ ExceptionalCondition(char *conditionName,
|
||||
}
|
||||
else
|
||||
{
|
||||
EPRINTF("TRAP: %s(\"%s:%s\", File: \"%s\", Line: %d)\n",
|
||||
fprintf(stderr, "TRAP: %s(\"%s:%s\", File: \"%s\", Line: %d)\n",
|
||||
exceptionP->message, conditionName,
|
||||
(detail == NULL ? "" : detail),
|
||||
fileName, lineNumber);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.58 2000/05/30 00:49:55 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.59 2000/05/31 00:28:32 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,8 +24,10 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#ifdef USE_SYSLOG
|
||||
#include <syslog.h>
|
||||
#include <sys/time.h>
|
||||
#include <ctype.h>
|
||||
#ifdef ENABLE_SYSLOG
|
||||
# include <syslog.h>
|
||||
#endif
|
||||
|
||||
#include "libpq/libpq.h"
|
||||
@ -40,20 +42,31 @@ extern int sys_nerr;
|
||||
|
||||
extern CommandDest whereToSendOutput;
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
#ifdef ENABLE_SYSLOG
|
||||
/*
|
||||
* Global option to control the use of syslog(3) for logging:
|
||||
*
|
||||
* 0 stdout/stderr only
|
||||
* 1 stdout/stderr + syslog
|
||||
* 2 syslog only
|
||||
* 0 = only stdout/stderr
|
||||
* 1 = stdout+stderr and syslog
|
||||
* 2 = syslog only
|
||||
* ... in theory anyway
|
||||
*/
|
||||
#define UseSyslog pg_options[OPT_SYSLOG]
|
||||
#define PG_LOG_FACILITY LOG_LOCAL0
|
||||
int Use_syslog = 0;
|
||||
|
||||
static void write_syslog(int level, const char *line);
|
||||
|
||||
#else
|
||||
#define UseSyslog 0
|
||||
# define Use_syslog 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ELOG_TIMESTAMPS
|
||||
static const char * print_timestamp(void);
|
||||
# define TIMESTAMP_SIZE 28
|
||||
#else
|
||||
# define TIMESTAMP_SIZE 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int Debugfile = -1;
|
||||
static int Err_file = -1;
|
||||
static int ElogDebugIndentLevel = 0;
|
||||
@ -182,7 +195,7 @@ elog(int lev, const char *fmt,...)
|
||||
}
|
||||
}
|
||||
#ifdef ELOG_TIMESTAMPS
|
||||
strcpy(fmt_buf, tprintf_timestamp());
|
||||
strcpy(fmt_buf, print_timestamp());
|
||||
strcat(fmt_buf, prefix);
|
||||
#else
|
||||
strcpy(fmt_buf, prefix);
|
||||
@ -265,7 +278,7 @@ elog(int lev, const char *fmt,...)
|
||||
msg_buf = msg_fixedbuf;
|
||||
lev = REALLYFATAL;
|
||||
#ifdef ELOG_TIMESTAMPS
|
||||
strcpy(msg_buf, tprintf_timestamp());
|
||||
strcpy(msg_buf, print_timestamp());
|
||||
strcat(msg_buf, "FATAL: elog: out of memory");
|
||||
#else
|
||||
strcpy(msg_buf, "FATAL: elog: out of memory");
|
||||
@ -278,35 +291,43 @@ elog(int lev, const char *fmt,...)
|
||||
* Message prepared; send it where it should go
|
||||
*/
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
switch (lev)
|
||||
#ifdef ENABLE_SYSLOG
|
||||
if (Use_syslog >= 1)
|
||||
{
|
||||
case NOIND:
|
||||
log_level = LOG_DEBUG;
|
||||
break;
|
||||
case DEBUG:
|
||||
log_level = LOG_DEBUG;
|
||||
break;
|
||||
case NOTICE:
|
||||
log_level = LOG_NOTICE;
|
||||
break;
|
||||
case ERROR:
|
||||
log_level = LOG_WARNING;
|
||||
break;
|
||||
case FATAL:
|
||||
default:
|
||||
log_level = LOG_ERR;
|
||||
break;
|
||||
int syslog_level;
|
||||
|
||||
switch (lev)
|
||||
{
|
||||
case NOIND:
|
||||
syslog_level = LOG_DEBUG;
|
||||
break;
|
||||
case DEBUG:
|
||||
syslog_level = LOG_DEBUG;
|
||||
break;
|
||||
case NOTICE:
|
||||
syslog_level = LOG_NOTICE;
|
||||
break;
|
||||
case ERROR:
|
||||
syslog_level = LOG_WARNING;
|
||||
break;
|
||||
case FATAL:
|
||||
syslog_level = LOG_ERR;
|
||||
break;
|
||||
case REALLYFATAL:
|
||||
default:
|
||||
syslog_level = LOG_CRIT;
|
||||
}
|
||||
|
||||
write_syslog(syslog_level, msg_buf + TIMESTAMP_SIZE);
|
||||
}
|
||||
write_syslog(log_level, msg_buf + TIMESTAMP_SIZE);
|
||||
#endif
|
||||
#endif /* ENABLE_SYSLOG */
|
||||
|
||||
/* syslog doesn't want a trailing newline, but other destinations do */
|
||||
strcat(msg_buf, "\n");
|
||||
|
||||
len = strlen(msg_buf);
|
||||
|
||||
if (Debugfile >= 0 && UseSyslog <= 1)
|
||||
if (Debugfile >= 0 && Use_syslog <= 1)
|
||||
write(Debugfile, msg_buf, len);
|
||||
|
||||
/*
|
||||
@ -321,7 +342,7 @@ elog(int lev, const char *fmt,...)
|
||||
* does anyone still use ultrix?)
|
||||
*/
|
||||
if (lev > DEBUG && Err_file >= 0 &&
|
||||
Debugfile != Err_file && UseSyslog <= 1)
|
||||
Debugfile != Err_file && Use_syslog <= 1)
|
||||
{
|
||||
if (write(Err_file, msg_buf, len) < 0)
|
||||
{
|
||||
@ -502,3 +523,124 @@ DebugFileOpen(void)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ELOG_TIMESTAMPS
|
||||
/*
|
||||
* Return a timestamp string like "980119.17:25:59.902 [21974] "
|
||||
*/
|
||||
static const char *
|
||||
print_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 ENABLE_SYSLOG
|
||||
|
||||
/*
|
||||
* Write a message line to syslog if the syslog option is set.
|
||||
*
|
||||
* Our problem here is that many syslog implementations don't handle
|
||||
* long messages in an acceptable manner. While this function doesn't
|
||||
* help that fact, it does work around by splitting up messages into
|
||||
* smaller pieces.
|
||||
*/
|
||||
static void
|
||||
write_syslog(int level, const char *line)
|
||||
{
|
||||
#ifndef PG_SYSLOG_LIMIT
|
||||
# define PG_SYSLOG_LIMIT 128
|
||||
#endif
|
||||
|
||||
static bool openlog_done = false;
|
||||
static unsigned long seq = 0;
|
||||
int len = strlen(line);
|
||||
|
||||
if (Use_syslog == 0)
|
||||
return;
|
||||
|
||||
if (!openlog_done)
|
||||
{
|
||||
openlog("postgres", LOG_PID | LOG_NDELAY, LOG_LOCAL0);
|
||||
openlog_done = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We add a sequence number to each log message to suppress "same"
|
||||
* messages.
|
||||
*/
|
||||
seq++;
|
||||
|
||||
/* divide into multiple syslog() calls if message is too long */
|
||||
if (len > PG_SYSLOG_LIMIT)
|
||||
{
|
||||
static char buf[PG_SYSLOG_LIMIT+1];
|
||||
int chunk_nr = 0;
|
||||
int buflen;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
int l;
|
||||
int i;
|
||||
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
chunk_nr++;
|
||||
|
||||
syslog(level, "[%lu-%d] %s", seq, chunk_nr, buf);
|
||||
line += buflen;
|
||||
len -= buflen;
|
||||
}
|
||||
}
|
||||
/* message short enough */
|
||||
else
|
||||
syslog(level, "[%lu] %s", seq, line);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_SYSLOG */
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.44 2000/05/30 00:49:56 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.45 2000/05/31 00:28:32 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Globals used all over the place should be declared here and not
|
||||
@ -77,8 +77,11 @@ char DateFormat[20] = "%d-%m-%Y"; /* mjl: sizes! or better
|
||||
* malloc? XXX */
|
||||
char FloatFormat[20] = "%f";
|
||||
|
||||
bool enableFsync = true;
|
||||
bool allowSystemTableMods = false;
|
||||
int SortMem = 512;
|
||||
int NBuffers = DEF_NBUFFERS;
|
||||
|
||||
|
||||
char *IndexedCatalogNames[] = {
|
||||
AttributeRelationName,
|
||||
|
@ -4,27 +4,38 @@
|
||||
# Makefile for utils/misc
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/misc/Makefile,v 1.13 2000/05/29 05:45:37 tgl Exp $
|
||||
# $Header: /cvsroot/pgsql/src/backend/utils/misc/Makefile,v 1.14 2000/05/31 00:28:34 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
SRCDIR = ../../..
|
||||
include ../../../Makefile.global
|
||||
|
||||
OBJS = database.o superuser.o trace.o
|
||||
OBJS = database.o superuser.o guc.o guc-file.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
SUBSYS.o: $(OBJS)
|
||||
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
|
||||
|
||||
.SECONDARY: guc-file.c
|
||||
.INTERMEDIATE: lex.yy.c
|
||||
|
||||
guc-file.c: lex.yy.c
|
||||
sed -e 's/lex\.yy\.c/guc-file\.c/g' \
|
||||
-e 's/^yy/GUC_yy/g' \
|
||||
-e 's/\([^a-zA-Z0-9_]\)yy/\1GUC_yy/g' < $< > $@
|
||||
|
||||
lex.yy.c: guc-file.l
|
||||
$(LEX) $(LFLAGS) $<
|
||||
|
||||
|
||||
depend dep:
|
||||
$(CC) -MM $(CFLAGS) *.c >depend
|
||||
|
||||
clean:
|
||||
rm -f SUBSYS.o $(OBJS)
|
||||
rm -f SUBSYS.o $(OBJS) lex.yy.c
|
||||
|
||||
ifeq (depend,$(wildcard depend))
|
||||
include depend
|
||||
endif
|
||||
|
||||
|
282
src/backend/utils/misc/guc-file.l
Normal file
282
src/backend/utils/misc/guc-file.l
Normal file
@ -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;
|
||||
}
|
692
src/backend/utils/misc/guc.c
Normal file
692
src/backend/utils/misc/guc.c
Normal file
@ -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:
|
||||
*/
|
@ -26,7 +26,7 @@
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.91 2000/04/25 08:29:02 petere Exp $
|
||||
# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.92 2000/05/31 00:28:35 petere Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@ -321,7 +321,6 @@ PG_HBA_SAMPLE="$PGLIB"/pg_hba.conf.sample
|
||||
|
||||
TEMPLATE_DESCR="$PGLIB"/local1_template1.description
|
||||
GLOBAL_DESCR="$PGLIB"/global1.description
|
||||
PG_GEQO_SAMPLE="$PGLIB"/pg_geqo.sample
|
||||
PG_POSTMASTER_OPTS_DEFAULT_SAMPLE="$PGLIB"/postmaster.opts.default.sample
|
||||
|
||||
if [ "$show_setting" -eq 1 ]
|
||||
@ -342,7 +341,6 @@ then
|
||||
echo " PG_HBA_SAMPLE: $PG_HBA_SAMPLE"
|
||||
echo " TEMPLATE_DESCR: $TEMPLATE_DESCR"
|
||||
echo " GLOBAL_DESCR: $GLOBAL_DESCR"
|
||||
echo " PG_GEQO_SAMPLE: $PG_GEQO_SAMPLE"
|
||||
echo " PG_POSTMASTER_OPTS_DEFAULT_SAMPLE: $PG_POSTMASTER_OPTS_DEFAULT_SAMPLE"
|
||||
echo
|
||||
exit 0
|
||||
@ -461,7 +459,6 @@ then
|
||||
"$PGPATH"/pg_version "$PGDATA" || exit_nicely
|
||||
|
||||
cp "$PG_HBA_SAMPLE" "$PGDATA"/pg_hba.conf || exit_nicely
|
||||
cp "$PG_GEQO_SAMPLE" "$PGDATA"/pg_geqo.sample || exit_nicely
|
||||
cp "$PG_POSTMASTER_OPTS_DEFAULT_SAMPLE" "$PGDATA"/postmaster.opts.default || exit_nicely
|
||||
|
||||
echo "Adding template1 database to pg_database"
|
||||
@ -482,7 +479,7 @@ fi
|
||||
|
||||
echo
|
||||
|
||||
PGSQL_OPT="-o /dev/null -O -F -Q -D$PGDATA"
|
||||
PGSQL_OPT="-o /dev/null -O -F -D$PGDATA"
|
||||
|
||||
# Create a trigger so that direct updates to pg_shadow will be written
|
||||
# to the flat password file pg_pwd
|
||||
|
952
src/configure
vendored
952
src/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -279,9 +279,14 @@ AC_MSG_CHECKING(setting DEF_PGPORT)
|
||||
AC_ARG_WITH(
|
||||
pgport,
|
||||
[ --with-pgport=PORTNUM change default postmaster port ],
|
||||
AC_DEFINE_UNQUOTED(DEF_PGPORT, "${withval}") AC_MSG_RESULT($with_pgport),
|
||||
AC_DEFINE_UNQUOTED(DEF_PGPORT, "5432") AC_MSG_RESULT(5432)
|
||||
[default_port="$withval"],
|
||||
[default_port=5432]
|
||||
)
|
||||
dnl Need to do this twice because backend wants an integer and frontend a string
|
||||
AC_DEFINE_UNQUOTED(DEF_PGPORT, ${default_port})
|
||||
AC_DEFINE_UNQUOTED(DEF_PGPORT_STR, "${default_port}")
|
||||
AC_MSG_RESULT(${default_port})
|
||||
|
||||
|
||||
dnl DEF_MAXBACKENDS can be set by --with-maxbackends. Default value is 32.
|
||||
AC_MSG_CHECKING(setting DEF_MAXBACKENDS)
|
||||
@ -944,6 +949,13 @@ AC_TRY_LINK([#include <setjmp.h>],
|
||||
[AC_DEFINE(HAVE_SIGSETJMP) AC_MSG_RESULT(yes)],
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_ARG_ENABLE(syslog, [ --enable-syslog enable logging to syslog],
|
||||
[case $enableval in y|ye|yes)
|
||||
AC_CHECK_FUNC(syslog, [AC_DEFINE(ENABLE_SYSLOG)], [AC_MSG_ERROR([no syslog interface found])])
|
||||
;;
|
||||
esac]
|
||||
)
|
||||
|
||||
dnl Check to see if we have a working 64-bit integer type.
|
||||
dnl This breaks down into two steps:
|
||||
dnl (1) figure out if the compiler has a 64-bit int type with working
|
||||
|
@ -6,13 +6,15 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: async.h,v 1.13 2000/01/26 05:58:00 momjian Exp $
|
||||
* $Id: async.h,v 1.14 2000/05/31 00:28:37 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef ASYNC_H
|
||||
#define ASYNC_H
|
||||
|
||||
extern bool Trace_notify;
|
||||
|
||||
/* notify-related SQL statements */
|
||||
extern void Async_Notify(char *relname);
|
||||
extern void Async_Listen(char *relname, int pid);
|
||||
|
@ -2,15 +2,15 @@
|
||||
* Headers for handling of 'SET var TO', 'SHOW var' and 'RESET var'
|
||||
* statements
|
||||
*
|
||||
* $Id: variable.h,v 1.9 2000/02/19 22:10:43 tgl Exp $
|
||||
* $Id: variable.h,v 1.10 2000/05/31 00:28:37 petere Exp $
|
||||
*
|
||||
*/
|
||||
#ifndef VARIABLE_H
|
||||
#define VARIABLE_H 1
|
||||
#define VARIABLE_H
|
||||
|
||||
extern bool SetPGVariable(const char *name, const char *value);
|
||||
extern bool GetPGVariable(const char *name);
|
||||
extern bool ResetPGVariable(const char *name);
|
||||
extern void SetPGVariable(const char *name, const char *value);
|
||||
extern void GetPGVariable(const char *name);
|
||||
extern void ResetPGVariable(const char *name);
|
||||
|
||||
extern void set_default_datestyle(void);
|
||||
|
||||
|
@ -8,12 +8,13 @@
|
||||
* or in config.h afterwards. Of course, if you edit config.h, then your
|
||||
* changes will be overwritten the next time you run configure.
|
||||
*
|
||||
* $Id: config.h.in,v 1.113 2000/05/12 13:58:25 scrappy Exp $
|
||||
* $Id: config.h.in,v 1.114 2000/05/31 00:28:36 petere Exp $
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
/*
|
||||
* Default runtime limit on number of backend server processes per postmaster;
|
||||
* this is just the default setting for the postmaster's -N switch.
|
||||
@ -61,14 +62,6 @@
|
||||
*/
|
||||
#define RELSEG_SIZE (0x40000000 / BLCKSZ)
|
||||
|
||||
/*
|
||||
* As soon as the backend blocks on a lock, it waits this number of seconds
|
||||
* before checking for a deadlock.
|
||||
* We don't check for deadlocks just before sleeping because a deadlock is
|
||||
* a rare event, and checking is an expensive operation.
|
||||
*/
|
||||
#define DEADLOCK_CHECK_TIMER 1
|
||||
|
||||
/*
|
||||
* Maximum number of columns in an index and maximum number of arguments
|
||||
* to a function. They must be the same value.
|
||||
@ -113,16 +106,6 @@
|
||||
*/
|
||||
#define USER_LOCKS
|
||||
|
||||
/* Genetic Query Optimization (GEQO):
|
||||
*
|
||||
* The GEQO module in PostgreSQL is intended for the solution of the
|
||||
* query optimization problem by means of a Genetic Algorithm (GA).
|
||||
* It allows the handling of large JOIN queries through non-exhaustive
|
||||
* search.
|
||||
* For further information see README.GEQO <utesch@aut.tu-freiberg.de>.
|
||||
*/
|
||||
#define GEQO
|
||||
|
||||
/*
|
||||
* Define this if you want psql to _always_ ask for a username and a password
|
||||
* for password authentication.
|
||||
@ -163,13 +146,7 @@
|
||||
*/
|
||||
/* #define ELOG_TIMESTAMPS */
|
||||
|
||||
/*
|
||||
* USE_SYSLOG: use syslog for elog and error messages printed by tprintf
|
||||
* and eprintf. This must be activated with the syslog flag in pg_options
|
||||
* (syslog=0 for stdio, syslog=1 for stdio+syslog, syslog=2 for syslog).
|
||||
* For information see backend/utils/misc/trace.c (Massimo Dal Zotto).
|
||||
*/
|
||||
/* #define USE_SYSLOG */
|
||||
#undef ENABLE_SYSLOG
|
||||
|
||||
/* Debug #defines */
|
||||
/* #define IPORTAL_DEBUG */
|
||||
@ -183,6 +160,7 @@
|
||||
/* #define NO_BUFFERISVALID */
|
||||
/* #define NO_SECURITY */
|
||||
/* #define OLD_REWRITE */
|
||||
/* #define LOCK_DEBUG */
|
||||
|
||||
/*
|
||||
* MAXPGPATH: standard size of a pathname buffer in Postgres (hence,
|
||||
@ -225,7 +203,9 @@
|
||||
* default. This can be overriden by command options, environment variables,
|
||||
* and the postconfig hook. (now set by configure script)
|
||||
*/
|
||||
#undef DEF_PGPORT
|
||||
#undef DEF_PGPORT
|
||||
/* ... and once more as a string constant instead */
|
||||
#undef DEF_PGPORT_STR
|
||||
|
||||
/* Define const as empty if your compiler doesn't grok const. */
|
||||
#undef const
|
||||
|
@ -12,7 +12,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: miscadmin.h,v 1.56 2000/05/29 19:16:55 tgl Exp $
|
||||
* $Id: miscadmin.h,v 1.57 2000/05/31 00:28:36 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* some of the information in this file will be moved to
|
||||
@ -27,7 +27,6 @@
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "utils/trace.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* globals.h -- *
|
||||
@ -102,12 +101,20 @@ extern char CTZName[];
|
||||
extern char FloatFormat[];
|
||||
extern char DateFormat[];
|
||||
|
||||
#define disableFsync pg_options[OPT_NOFSYNC]
|
||||
extern bool enableFsync;
|
||||
extern bool allowSystemTableMods;
|
||||
extern int SortMem;
|
||||
|
||||
extern Oid LastOidProcessed; /* for query rewrite */
|
||||
|
||||
/* a few postmaster startup options are exported here so the
|
||||
configuration file processor has access to them */
|
||||
|
||||
extern bool NetServer;
|
||||
extern int MaxBackends;
|
||||
extern int NBuffers;
|
||||
extern int PostPortName;
|
||||
|
||||
/*****************************************************************************
|
||||
* pdir.h -- *
|
||||
* POSTGRES directory path definitions. *
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: cost.h,v 1.32 2000/04/12 17:16:42 momjian Exp $
|
||||
* $Id: cost.h,v 1.33 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -38,10 +38,10 @@
|
||||
|
||||
/* parameter variables and flags */
|
||||
extern double effective_cache_size;
|
||||
extern Cost random_page_cost;
|
||||
extern Cost cpu_tuple_cost;
|
||||
extern Cost cpu_index_tuple_cost;
|
||||
extern Cost cpu_operator_cost;
|
||||
extern double random_page_cost;
|
||||
extern double cpu_tuple_cost;
|
||||
extern double cpu_index_tuple_cost;
|
||||
extern double cpu_operator_cost;
|
||||
extern Cost disable_cost;
|
||||
extern bool enable_seqscan;
|
||||
extern bool enable_indexscan;
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: geqo.h,v 1.18 2000/01/26 05:58:20 momjian Exp $
|
||||
* $Id: geqo.h,v 1.19 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -41,32 +41,29 @@
|
||||
*/
|
||||
#define ERX
|
||||
|
||||
/* genetic algorithm parameters */
|
||||
|
||||
#define GEQO_FILE "pg_geqo" /* Name of the ga config file */
|
||||
/*
|
||||
* Configuration options
|
||||
*/
|
||||
extern int Geqo_pool_size;
|
||||
#define DEFAULT_GEQO_POOL_SIZE 0 /* = default based on no. of relations. */
|
||||
#define MIN_GEQO_POOL_SIZE 128
|
||||
#define MAX_GEQO_POOL_SIZE 1024
|
||||
|
||||
#define MIN_POOL 128 /* minimum number of individuals */
|
||||
#define MAX_POOL 1024 /* maximum number of individuals */
|
||||
extern int Geqo_effort; /* 1 .. inf, only used to calculate generations default */
|
||||
extern int Geqo_generations; /* 1 .. inf, or 0 to use default based on pool size */
|
||||
|
||||
#define LOW_EFFORT 1 /* optimization effort values */
|
||||
#define MEDIUM_EFFORT 40 /* are multipliers for computed */
|
||||
#define HIGH_EFFORT 80 /* number of generations */
|
||||
extern double Geqo_selection_bias;
|
||||
#define DEFAULT_GEQO_SELECTION_BIAS 2.0
|
||||
#define MIN_GEQO_SELECTION_BIAS 1.5
|
||||
#define MAX_GEQO_SELECTION_BIAS 2.0
|
||||
|
||||
#define SELECTION_BIAS 2.0 /* selective pressure within population */
|
||||
/* should be 1.5 <= SELECTION_BIAS <= 2.0 */
|
||||
extern int Geqo_random_seed; /* or negative to use current time */
|
||||
|
||||
/* parameter values set in geqo_params.c */
|
||||
extern int PoolSize;
|
||||
extern int Generations;
|
||||
extern long RandomSeed;
|
||||
extern double SelectionBias;
|
||||
|
||||
/* routines in geqo_main.c */
|
||||
extern RelOptInfo *geqo(Query *root);
|
||||
|
||||
/* routines in geqo_params.c */
|
||||
extern void geqo_params(int string_length);
|
||||
|
||||
/* routines in geqo_eval.c */
|
||||
extern void geqo_eval_startup(void);
|
||||
extern Cost geqo_eval(Query *root, Gene *tour, int num_gene);
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: paths.h,v 1.44 2000/04/12 17:16:42 momjian Exp $
|
||||
* $Id: paths.h,v 1.45 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,7 +18,7 @@
|
||||
#include "nodes/relation.h"
|
||||
|
||||
/* default GEQO threshold (default value for geqo_rels) */
|
||||
#define GEQO_RELS 11
|
||||
#define DEFAULT_GEQO_RELS 11
|
||||
|
||||
|
||||
/*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: planmain.h,v 1.39 2000/04/12 17:16:42 momjian Exp $
|
||||
* $Id: planmain.h,v 1.40 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -55,6 +55,7 @@ extern void fix_opids(Node *node);
|
||||
/*
|
||||
* prep/prepkeyset.c
|
||||
*/
|
||||
extern bool _use_keyset_query_optimizer;
|
||||
extern void transformKeySetQuery(Query *origNode);
|
||||
|
||||
#endif /* PLANMAIN_H */
|
||||
|
@ -7,13 +7,14 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: lock.h,v 1.37 2000/04/12 17:16:51 momjian Exp $
|
||||
* $Id: lock.h,v 1.38 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef LOCK_H_
|
||||
#define LOCK_H_
|
||||
|
||||
#include "postgres.h"
|
||||
#include "storage/ipc.h"
|
||||
#include "storage/itemptr.h"
|
||||
#include "storage/shmem.h"
|
||||
@ -26,6 +27,15 @@ typedef int LOCKMASK;
|
||||
#define MAX_TABLE_SIZE 1000
|
||||
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
extern int Trace_lock_oidmin;
|
||||
extern bool Trace_locks;
|
||||
extern bool Trace_userlocks;
|
||||
extern int Trace_lock_table;
|
||||
extern bool Debug_deadlocks;
|
||||
#endif /* LOCK_DEBUG */
|
||||
|
||||
|
||||
/* ----------------------
|
||||
* The following defines are used to estimate how much shared
|
||||
* memory the lock manager is going to require.
|
||||
@ -259,10 +269,9 @@ extern int LockShmemSize(int maxBackends);
|
||||
extern bool LockingDisabled(void);
|
||||
extern bool DeadLockCheck(void *proc, LOCK *findlock);
|
||||
|
||||
#ifdef DEADLOCK_DEBUG
|
||||
#ifdef LOCK_DEBUG
|
||||
extern void DumpLocks(void);
|
||||
extern void DumpAllLocks(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* LOCK_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: proc.h,v 1.30 2000/04/12 17:16:51 momjian Exp $
|
||||
* $Id: proc.h,v 1.31 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -17,6 +17,9 @@
|
||||
#include "access/xlog.h"
|
||||
#include "storage/lock.h"
|
||||
|
||||
/* configurable option */
|
||||
extern int DeadlockTimeout;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int sleeplock;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: spin.h,v 1.11 2000/01/26 05:58:33 momjian Exp $
|
||||
* $Id: spin.h,v 1.12 2000/05/31 00:28:38 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -28,6 +28,10 @@
|
||||
|
||||
typedef int SPINLOCK;
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
extern bool Trace_spinlocks;
|
||||
#endif
|
||||
|
||||
extern void CreateSpinlocks(IPCKey key);
|
||||
extern void InitSpinLocks(void);
|
||||
extern void SpinAcquire(SPINLOCK lockid);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: tcopprot.h,v 1.27 2000/04/12 17:16:53 momjian Exp $
|
||||
* $Id: tcopprot.h,v 1.28 2000/05/31 00:28:39 petere Exp $
|
||||
*
|
||||
* OLD COMMENTS
|
||||
* This file was created so that other c files could get the two
|
||||
@ -28,6 +28,9 @@ extern bool Warn_restart_ready;
|
||||
extern bool InError;
|
||||
extern bool ExitAfterAbort;
|
||||
|
||||
extern bool HostnameLookup;
|
||||
extern bool ShowPortNumber;
|
||||
|
||||
#ifndef BOOTSTRAP_INCLUDE
|
||||
|
||||
extern List *pg_parse_and_rewrite(char *query_string,
|
||||
@ -50,5 +53,6 @@ extern int PostgresMain(int argc, char *argv[],
|
||||
int real_argc, char *real_argv[]);
|
||||
extern void ResetUsage(void);
|
||||
extern void ShowUsage(void);
|
||||
extern FILE * StatFp;
|
||||
|
||||
#endif /* TCOPPROT_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: elog.h,v 1.16 2000/04/12 17:16:54 momjian Exp $
|
||||
* $Id: elog.h,v 1.17 2000/05/31 00:28:40 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -23,6 +23,10 @@
|
||||
#define LOG DEBUG
|
||||
#define NOIND (-3) /* debug message, don't indent as far */
|
||||
|
||||
#ifdef ENABLE_SYSLOG
|
||||
extern int Use_syslog;
|
||||
#endif
|
||||
|
||||
#ifndef __GNUC__
|
||||
extern void elog(int lev, const char *fmt,...);
|
||||
|
||||
|
47
src/include/utils/guc.h
Normal file
47
src/include/utils/guc.h
Normal file
@ -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:
|
||||
*/
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.127 2000/05/21 21:19:53 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.128 2000/05/31 00:28:41 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -122,7 +122,7 @@ static const PQconninfoOption PQconninfoOptions[] = {
|
||||
"Database-Host-IPv4-Address", "", 15}, /* Room for
|
||||
* abc.def.ghi.jkl */
|
||||
|
||||
{"port", "PGPORT", DEF_PGPORT, NULL,
|
||||
{"port", "PGPORT", DEF_PGPORT_STR, NULL,
|
||||
"Database-Port", "", 6},
|
||||
|
||||
{"tty", "PGTTY", DefaultTty, NULL,
|
||||
@ -416,7 +416,7 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
|
||||
if ((pgport == NULL) || pgport[0] == '\0')
|
||||
{
|
||||
if ((tmp = getenv("PGPORT")) == NULL)
|
||||
tmp = DEF_PGPORT;
|
||||
tmp = DEF_PGPORT_STR;
|
||||
conn->pgport = strdup(tmp);
|
||||
}
|
||||
else
|
||||
|
@ -45,6 +45,13 @@ rm -f bootstrap_tokens.h bootparse.c bootscanner.c
|
||||
$MAKE bootstrap_tokens.h bootparse.c bootscanner.c
|
||||
cd ../..
|
||||
|
||||
# Generate configuration file scanner
|
||||
|
||||
cd backend/utils/misc
|
||||
rm -f guc-file.c lex.yy.c
|
||||
$MAKE guc-file.c
|
||||
cd ../../..
|
||||
|
||||
# Generate ecpg preprocessor's yacc and lex files
|
||||
|
||||
cd interfaces/ecpg/preproc
|
||||
|
Loading…
x
Reference in New Issue
Block a user