Commit abc3120e authored by Tom Lane's avatar Tom Lane

Add server support for "plugin" libraries that can be used for add-on tasks

such as debugging and performance measurement.  This consists of two features:
a table of "rendezvous variables" that allows separately-loaded shared
libraries to communicate, and a new GUC setting "local_preload_libraries"
that allows libraries to be loaded into specific sessions without explicit
cooperation from the client application.  To make local_preload_libraries
as flexible as possible, we do not restrict its use to superusers; instead,
it is restricted to load only libraries stored in $libdir/plugins/.  The
existing LOAD command has also been modified to allow non-superusers to
LOAD libraries stored in this directory.

This patch also renames the existing GUC variable preload_libraries to
shared_preload_libraries (after a suggestion by Simon Riggs) and does some
code refactoring in dfmgr.c to improve clarity.

Korry Douglas, with a little help from Tom Lane.
parent 66541c5a
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.73 2006/08/08 19:15:07 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.74 2006/08/15 18:26:58 tgl Exp $ -->
<chapter Id="runtime-config">
<title>Server Configuration</title>
......@@ -949,10 +949,10 @@ SET ENABLE_SEQSCAN TO OFF;
</listitem>
</varlistentry>
<varlistentry id="guc-preload-libraries" xreflabel="preload_libraries">
<term><varname>preload_libraries</varname> (<type>string</type>)</term>
<varlistentry id="guc-shared-preload-libraries" xreflabel="shared_preload_libraries">
<term><varname>shared_preload_libraries</varname> (<type>string</type>)</term>
<indexterm>
<primary><varname>preload_libraries</> configuration parameter</primary>
<primary><varname>shared_preload_libraries</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
......@@ -963,6 +963,7 @@ SET ENABLE_SEQSCAN TO OFF;
<literal>mylib.so</> (or on some platforms,
<literal>mylib.sl</>) to be preloaded from the installation's
standard library directory.
This parameter can only be set at server start.
</para>
<para>
......@@ -3643,6 +3644,60 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem>
</varlistentry>
<varlistentry id="guc-local-preload-libraries" xreflabel="local_preload_libraries">
<term><varname>local_preload_libraries</varname> (<type>string</type>)</term>
<indexterm>
<primary><varname>local_preload_libraries</> configuration parameter</primary>
</indexterm>
<indexterm>
<primary><filename>$libdir/plugins</></primary>
</indexterm>
<listitem>
<para>
This variable specifies one or more shared libraries that are
to be preloaded at connection start. If more than one library
is to be loaded, separate their names with commas.
This parameter cannot be changed after the start of a particular
session.
</para>
<para>
Because this is not a superuser-only option, the libraries
that can be loaded are restricted to those appearing in the
<filename>plugins</> subdirectory of the installation's
standard library directory. (It is the database administrator's
responsibility to ensure that only <quote>safe</> libraries
are installed there.) Entries in <varname>local_preload_libraries</>
can specify this directory explicitly, for example
<literal>$libdir/plugins/mylib</literal>, or just specify
the library name &mdash; <literal>mylib</literal> would have
the same effect as <literal>$libdir/plugins/mylib</literal>.
</para>
<para>
There is no performance advantage to loading a library at session
start rather than when it is first used. Rather, the intent of
this feature is to allow debugging or performance-measurement
libraries to be loaded into specific sessions without an explicit
<command>LOAD</> command being given. For example, debugging could
be enabled for all sessions under a given user name by setting
this parameter with <command>ALTER USER SET</>.
</para>
<para>
If a specified library is not found,
the connection attempt will fail.
</para>
<para>
Every PostgreSQL-supported library has a <quote>magic
block</> that is checked to guarantee compatibility.
For this reason, non-PostgreSQL libraries cannot be
loaded in this way.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>
......
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/load.sgml,v 1.21 2005/01/04 00:39:53 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/load.sgml,v 1.22 2006/08/15 18:26:58 tgl Exp $
-->
<refentry id="SQL-LOAD">
......@@ -44,6 +44,19 @@ LOAD '<replaceable class="PARAMETER">filename</replaceable>'
shared library file name extension. See <xref linkend="xfunc-c"> for
more information on this topic.
</para>
<indexterm>
<primary><filename>$libdir/plugins</></primary>
</indexterm>
<para>
Non-superusers may only apply <command>LOAD</> to library files
located in <filename>$libdir/plugins/</> &mdash; the specified
<replaceable class="PARAMETER">filename</replaceable> must begin
with exactly that string. (It is the database administrator's
responsibility to ensure that only <quote>safe</> libraries
are installed there.)
</para>
</refsect1>
<refsect1 id="sql-load-compat">
......
......@@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.498 2006/08/08 19:15:07 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.499 2006/08/15 18:26:58 tgl Exp $
*
* NOTES
*
......@@ -709,7 +709,7 @@ PostmasterMain(int argc, char *argv[])
/*
* process any libraries that should be preloaded at postmaster start
*/
process_preload_libraries();
process_shared_preload_libraries();
/*
* Remove old temporary files. At this point there can be no other
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.498 2006/08/13 22:18:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.499 2006/08/15 18:26:58 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
......@@ -3000,6 +3000,12 @@ PostgresMain(int argc, char *argv[], const char *username)
if (IsUnderPostmaster && Log_disconnections)
on_proc_exit(log_disconnections, 0);
/*
* process any libraries that should be preloaded at backend start
* (this likewise can't be done until GUC settings are complete)
*/
process_local_preload_libraries();
/*
* Send this backend's cancellation info to the frontend.
*/
......
......@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.265 2006/08/12 20:05:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.266 2006/08/15 18:26:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -886,12 +886,9 @@ ProcessUtility(Node *parsetree,
{
LoadStmt *stmt = (LoadStmt *) parsetree;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to do LOAD")));
closeAllVfds(); /* probably not necessary... */
load_file(stmt->filename);
/* Allowed names are restricted if you're not superuser */
load_file(stmt->filename, !superuser());
}
break;
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.156 2006/08/08 19:15:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.157 2006/08/15 18:26:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1097,24 +1097,31 @@ ValidatePgVersion(const char *path)
*-------------------------------------------------------------------------
*/
/* GUC variable: list of library names to be preloaded */
char *preload_libraries_string = NULL;
/*
* GUC variables: lists of library names to be preloaded at postmaster
* start and at backend start
*/
char *shared_preload_libraries_string = NULL;
char *local_preload_libraries_string = NULL;
/*
* process any libraries that should be preloaded at postmaster start
* load the shared libraries listed in 'libraries'
*
* 'gucname': name of GUC variable, for error reports
* 'restrict': if true, force libraries to be in $libdir/plugins/
*/
void
process_preload_libraries(void)
static void
load_libraries(const char *libraries, const char *gucname, bool restrict)
{
char *rawstring;
List *elemlist;
ListCell *l;
if (preload_libraries_string == NULL)
return;
if (libraries == NULL || libraries[0] == '\0')
return; /* nothing to do */
/* Need a modifiable copy of string */
rawstring = pstrdup(preload_libraries_string);
rawstring = pstrdup(libraries);
/* Parse string into list of identifiers */
if (!SplitIdentifierString(rawstring, ',', &elemlist))
......@@ -1124,7 +1131,8 @@ process_preload_libraries(void)
list_free(elemlist);
ereport(LOG,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid list syntax for parameter \"preload_libraries\"")));
errmsg("invalid list syntax in parameter \"%s\"",
gucname)));
return;
}
......@@ -1135,12 +1143,45 @@ process_preload_libraries(void)
filename = pstrdup(tok);
canonicalize_path(filename);
(void) load_external_function(filename, NULL, true, NULL);
/* If restricting, insert $libdir/plugins if not mentioned already */
if (restrict && first_dir_separator(filename) == NULL)
{
char *expanded;
expanded = palloc(strlen("$libdir/plugins/") + strlen(filename) + 1);
strcpy(expanded, "$libdir/plugins/");
strcat(expanded, filename);
pfree(filename);
filename = expanded;
}
load_file(filename, restrict);
ereport(LOG,
(errmsg("preloaded library \"%s\"", filename)));
(errmsg("loaded library \"%s\"", filename)));
pfree(filename);
}
pfree(rawstring);
list_free(elemlist);
}
/*
* process any libraries that should be preloaded at postmaster start
*/
void
process_shared_preload_libraries(void)
{
load_libraries(shared_preload_libraries_string,
"shared_preload_libraries",
false);
}
/*
* process any libraries that should be preloaded at backend start
*/
void
process_local_preload_libraries(void)
{
load_libraries(local_preload_libraries_string,
"local_preload_libraries",
true);
}
......@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.341 2006/08/14 02:27:26 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.342 2006/08/15 18:26:59 tgl Exp $
*
*--------------------------------------------------------------------
*/
......@@ -1964,12 +1964,22 @@ static struct config_string ConfigureNamesString[] =
},
{
{"preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
{"shared_preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
gettext_noop("Lists shared libraries to preload into server."),
NULL,
GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
},
&preload_libraries_string,
&shared_preload_libraries_string,
"", NULL, NULL
},
{
{"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_OTHER,
gettext_noop("Lists shared libraries to preload into each backend."),
NULL,
GUC_LIST_INPUT | GUC_LIST_QUOTE
},
&local_preload_libraries_string,
"", NULL, NULL
},
......
......@@ -120,7 +120,7 @@
#max_files_per_process = 1000 # min 25
# (change requires restart)
#preload_libraries = '' # (change requires restart)
#shared_preload_libraries = '' # (change requires restart)
# - Cost-Based Vacuum Delay -
......@@ -419,6 +419,7 @@
#explain_pretty_print = on
#dynamic_library_path = '$libdir'
#local_preload_libraries = ''
#---------------------------------------------------------------------------
......
......@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.45 2006/05/31 20:58:09 tgl Exp $
* $PostgreSQL: pgsql/src/include/fmgr.h,v 1.46 2006/08/15 18:26:59 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -488,7 +488,8 @@ extern char *Dynamic_library_path;
extern PGFunction load_external_function(char *filename, char *funcname,
bool signalNotFound, void **filehandle);
extern PGFunction lookup_external_function(void *filehandle, char *funcname);
extern void load_file(char *filename);
extern void load_file(const char *filename, bool restrict);
extern void **find_rendezvous_variable(const char *varName);
/*
......
......@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.187 2006/08/08 19:15:08 tgl Exp $
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.188 2006/08/15 18:26:59 tgl Exp $
*
* NOTES
* some of the information in this file should be moved to other files.
......@@ -307,7 +307,8 @@ extern void BaseInit(void);
/* in utils/init/miscinit.c */
extern bool IgnoreSystemIndexes;
extern char *preload_libraries_string;
extern char *shared_preload_libraries_string;
extern char *local_preload_libraries_string;
extern void SetReindexProcessing(Oid heapOid, Oid indexOid);
extern void ResetReindexProcessing(void);
......@@ -319,6 +320,7 @@ extern void TouchSocketLockFile(void);
extern void RecordSharedMemoryInLockFile(unsigned long id1,
unsigned long id2);
extern void ValidatePgVersion(const char *path);
extern void process_preload_libraries(void);
extern void process_shared_preload_libraries(void);
extern void process_local_preload_libraries(void);
#endif /* MISCADMIN_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment