aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-08-15 18:26:59 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-08-15 18:26:59 +0000
commitabc3120e9b2055f0934f60ad3e3040db548df8d3 (patch)
tree2e47098790253c6ecbcbb8b99e3c5e5b5551c9d2 /src
parent66541c5aa51bf6128afa8ebb4bb90959b596705f (diff)
downloadpostgresql-abc3120e9b2055f0934f60ad3e3040db548df8d3.tar.gz
postgresql-abc3120e9b2055f0934f60ad3e3040db548df8d3.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/postmaster/postmaster.c4
-rw-r--r--src/backend/tcop/postgres.c8
-rw-r--r--src/backend/tcop/utility.c9
-rw-r--r--src/backend/utils/fmgr/dfmgr.c270
-rw-r--r--src/backend/utils/init/miscinit.c65
-rw-r--r--src/backend/utils/misc/guc.c16
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample3
-rw-r--r--src/include/fmgr.h5
-rw-r--r--src/include/miscadmin.h8
9 files changed, 280 insertions, 108 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eefa974dee9..130415c74cb 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -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
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 9cb61c16cb5..af9578b15ac 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -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
@@ -3001,6 +3001,12 @@ PostgresMain(int argc, char *argv[], const char *username)
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.
*/
if (whereToSendOutput == DestRemote &&
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7d6941ddcef..ce86a90ba3f 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -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;
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index fd2c54c2118..3c2b34e3e63 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.87 2006/08/08 19:15:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.88 2006/08/15 18:26:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,12 +23,20 @@
#endif
#include "miscadmin.h"
#include "utils/dynamic_loader.h"
+#include "utils/hsearch.h"
/* signatures for PostgreSQL-specific library init/fini functions */
typedef void (*PG_init_t)(void);
typedef void (*PG_fini_t)(void);
+/* hashtable entry for rendezvous variables */
+typedef struct
+{
+ char varName[NAMEDATALEN]; /* hash key (must be first) */
+ void *varValue;
+} rendezvousHashEntry;
+
/*
* List of dynamically loaded files (kept in malloc'd memory).
*/
@@ -62,10 +70,13 @@ static DynamicFileList *file_tail = NULL;
char *Dynamic_library_path;
+static void *internal_load_library(const char *libname);
+static void internal_unload_library(const char *libname);
static bool file_exists(const char *name);
-static char *find_in_dynamic_libpath(const char *basename);
static char *expand_dynamic_library_name(const char *name);
+static void check_restricted_library_name(const char *name);
static char *substitute_libpath_macro(const char *name);
+static char *find_in_dynamic_libpath(const char *basename);
/* Magic structure that module needs to match to be accepted */
static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
@@ -73,7 +84,7 @@ static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
/*
* Load the specified dynamic-link library file, and look for a function
- * named funcname in it. (funcname can be NULL to just load the file.)
+ * named funcname in it.
*
* If the function is not found, we raise an error if signalNotFound is true,
* else return (PGFunction) NULL. Note that errors in loading the library
@@ -88,37 +99,107 @@ PGFunction
load_external_function(char *filename, char *funcname,
bool signalNotFound, void **filehandle)
{
- DynamicFileList *file_scanner;
+ char *fullname;
+ void *lib_handle;
PGFunction retval;
+
+ /* Expand the possibly-abbreviated filename to an exact path name */
+ fullname = expand_dynamic_library_name(filename);
+
+ /* Load the shared library, unless we already did */
+ lib_handle = internal_load_library(fullname);
+
+ /* Return handle if caller wants it */
+ if (filehandle)
+ *filehandle = lib_handle;
+
+ /* Look up the function within the library */
+ retval = pg_dlsym(lib_handle, funcname);
+
+ if (retval == NULL && signalNotFound)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not find function \"%s\" in file \"%s\"",
+ funcname, fullname)));
+
+ pfree(fullname);
+ return retval;
+}
+
+/*
+ * This function loads a shlib file without looking up any particular
+ * function in it. If the same shlib has previously been loaded,
+ * unload and reload it.
+ *
+ * When 'restrict' is true, only libraries in the presumed-secure
+ * directory $libdir/plugins may be referenced.
+ */
+void
+load_file(const char *filename, bool restrict)
+{
+ char *fullname;
+
+ /* Apply security restriction if requested */
+ if (restrict)
+ check_restricted_library_name(filename);
+
+ /* Expand the possibly-abbreviated filename to an exact path name */
+ fullname = expand_dynamic_library_name(filename);
+
+ /* Unload the library if currently loaded */
+ internal_unload_library(fullname);
+
+ /* Load the shared library */
+ (void) internal_load_library(fullname);
+
+ pfree(fullname);
+}
+
+/*
+ * Lookup a function whose library file is already loaded.
+ * Return (PGFunction) NULL if not found.
+ */
+PGFunction
+lookup_external_function(void *filehandle, char *funcname)
+{
+ return pg_dlsym(filehandle, funcname);
+}
+
+
+/*
+ * Load the specified dynamic-link library file, unless it already is
+ * loaded. Return the pg_dl* handle for the file.
+ *
+ * Note: libname is expected to be an exact name for the library file.
+ */
+static void *
+internal_load_library(const char *libname)
+{
+ DynamicFileList *file_scanner;
PGModuleMagicFunction magic_func;
char *load_error;
struct stat stat_buf;
- char *fullname;
PG_init_t PG_init;
- fullname = expand_dynamic_library_name(filename);
- if (!fullname)
- fullname = pstrdup(filename);
- /* at this point fullname is always freshly palloc'd */
-
/*
* Scan the list of loaded FILES to see if the file has been loaded.
*/
for (file_scanner = file_list;
file_scanner != NULL &&
- strcmp(fullname, file_scanner->filename) != 0;
+ strcmp(libname, file_scanner->filename) != 0;
file_scanner = file_scanner->next)
;
+
if (file_scanner == NULL)
{
/*
* Check for same files - different paths (ie, symlink or link)
*/
- if (stat(fullname, &stat_buf) == -1)
+ if (stat(libname, &stat_buf) == -1)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not access file \"%s\": %m",
- fullname)));
+ libname)));
for (file_scanner = file_list;
file_scanner != NULL &&
@@ -133,21 +214,21 @@ load_external_function(char *filename, char *funcname,
* File not loaded yet.
*/
file_scanner = (DynamicFileList *)
- malloc(sizeof(DynamicFileList) + strlen(fullname));
+ malloc(sizeof(DynamicFileList) + strlen(libname));
if (file_scanner == NULL)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
MemSet(file_scanner, 0, sizeof(DynamicFileList));
- strcpy(file_scanner->filename, fullname);
+ strcpy(file_scanner->filename, libname);
file_scanner->device = stat_buf.st_dev;
#ifndef WIN32
file_scanner->inode = stat_buf.st_ino;
#endif
file_scanner->next = NULL;
- file_scanner->handle = pg_dlopen(fullname);
+ file_scanner->handle = pg_dlopen(file_scanner->filename);
if (file_scanner->handle == NULL)
{
load_error = (char *) pg_dlerror();
@@ -156,7 +237,7 @@ load_external_function(char *filename, char *funcname,
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not load library \"%s\": %s",
- fullname, load_error)));
+ libname, load_error)));
}
/* Check the magic function to determine compatibility */
@@ -184,7 +265,7 @@ load_external_function(char *filename, char *funcname,
if (module_magic_data.version != magic_data.version)
ereport(ERROR,
(errmsg("incompatible library \"%s\": version mismatch",
- fullname),
+ libname),
errdetail("Server is version %d.%d, library is version %d.%d.",
magic_data.version/100,
magic_data.version % 100,
@@ -192,7 +273,7 @@ load_external_function(char *filename, char *funcname,
module_magic_data.version % 100)));
ereport(ERROR,
(errmsg("incompatible library \"%s\": magic block mismatch",
- fullname)));
+ libname)));
}
}
else
@@ -203,7 +284,7 @@ load_external_function(char *filename, char *funcname,
/* complain */
ereport(ERROR,
(errmsg("incompatible library \"%s\": missing magic block",
- fullname),
+ libname),
errhint("Extension libraries are now required to use the PG_MODULE_MAGIC macro.")));
}
@@ -222,77 +303,48 @@ load_external_function(char *filename, char *funcname,
file_tail = file_scanner;
}
- /* Return handle if caller wants it. */
- if (filehandle)
- *filehandle = file_scanner->handle;
-
- /*
- * If funcname is NULL, we only wanted to load the file.
- */
- if (funcname == NULL)
- {
- pfree(fullname);
- return NULL;
- }
-
- retval = pg_dlsym(file_scanner->handle, funcname);
-
- if (retval == NULL && signalNotFound)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_FUNCTION),
- errmsg("could not find function \"%s\" in file \"%s\"",
- funcname, fullname)));
-
- pfree(fullname);
- return retval;
+ return file_scanner->handle;
}
/*
- * This function loads a shlib file without looking up any particular
- * function in it. If the same shlib has previously been loaded,
- * unload and reload it.
+ * Unload the specified dynamic-link library file, if it is loaded.
+ *
+ * Note: libname is expected to be an exact name for the library file.
*/
-void
-load_file(char *filename)
+static void
+internal_unload_library(const char *libname)
{
DynamicFileList *file_scanner,
*prv,
*nxt;
struct stat stat_buf;
- char *fullname;
PG_fini_t PG_fini;
- fullname = expand_dynamic_library_name(filename);
- if (!fullname)
- fullname = pstrdup(filename);
- /* at this point fullname is always freshly palloc'd */
-
/*
* We need to do stat() in order to determine whether this is the same
* file as a previously loaded file; it's also handy so as to give a good
* error message if bogus file name given.
*/
- if (stat(fullname, &stat_buf) == -1)
+ if (stat(libname, &stat_buf) == -1)
ereport(ERROR,
(errcode_for_file_access(),
- errmsg("could not access file \"%s\": %m", fullname)));
+ errmsg("could not access file \"%s\": %m", libname)));
/*
* We have to zap all entries in the list that match on either filename or
- * inode, else load_external_function() won't do anything.
+ * inode, else internal_load_library() will still think it's present.
*/
prv = NULL;
for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt)
{
nxt = file_scanner->next;
- if (strcmp(fullname, file_scanner->filename) == 0 ||
+ if (strcmp(libname, file_scanner->filename) == 0 ||
SAME_INODE(stat_buf, *file_scanner))
{
if (prv)
prv->next = nxt;
else
file_list = nxt;
- clear_external_function_hash(file_scanner->handle);
/*
* If the library has a _PG_fini() function, call it.
@@ -301,6 +353,7 @@ load_file(char *filename)
if (PG_fini)
(*PG_fini)();
+ clear_external_function_hash(file_scanner->handle);
pg_dlclose(file_scanner->handle);
free((char *) file_scanner);
/* prv does not change */
@@ -308,23 +361,8 @@ load_file(char *filename)
else
prv = file_scanner;
}
-
- load_external_function(fullname, NULL, false, NULL);
-
- pfree(fullname);
-}
-
-/*
- * Lookup a function whose library file is already loaded.
- * Return (PGFunction) NULL if not found.
- */
-PGFunction
-lookup_external_function(void *filehandle, char *funcname)
-{
- return pg_dlsym(filehandle, funcname);
}
-
static bool
file_exists(const char *name)
{
@@ -353,9 +391,9 @@ file_exists(const char *name)
* the name. Else (no slash) try to expand using search path (see
* find_in_dynamic_libpath below); if that works, return the fully
* expanded file name. If the previous failed, append DLSUFFIX and
- * try again. If all fails, return NULL.
+ * try again. If all fails, just return the original name.
*
- * A non-NULL result will always be freshly palloc'd.
+ * The result will always be freshly palloc'd.
*/
static char *
expand_dynamic_library_name(const char *name)
@@ -402,9 +440,28 @@ expand_dynamic_library_name(const char *name)
pfree(full);
}
- return NULL;
+ /*
+ * If we can't find the file, just return the string as-is.
+ * The ensuing load attempt will fail and report a suitable message.
+ */
+ return pstrdup(name);
}
+/*
+ * Check a restricted library name. It must begin with "$libdir/plugins/"
+ * and there must not be any directory separators after that (this is
+ * sufficient to prevent ".." style attacks).
+ */
+static void
+check_restricted_library_name(const char *name)
+{
+ if (strncmp(name, "$libdir/plugins/", 16) != 0 ||
+ first_dir_separator(name + 16) != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("access to library \"%s\" is not allowed",
+ name)));
+}
/*
* Substitute for any macros appearing in the given string.
@@ -418,6 +475,7 @@ substitute_libpath_macro(const char *name)
AssertArg(name != NULL);
+ /* Currently, we only recognize $libdir at the start of the string */
if (name[0] != '$')
return pstrdup(name);
@@ -428,7 +486,8 @@ substitute_libpath_macro(const char *name)
strncmp(name, "$libdir", strlen("$libdir")) != 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME),
- errmsg("invalid macro name in dynamic library path: %s", name)));
+ errmsg("invalid macro name in dynamic library path: %s",
+ name)));
ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);
@@ -513,3 +572,58 @@ find_in_dynamic_libpath(const char *basename)
return NULL;
}
+
+
+/*
+ * Find (or create) a rendezvous variable that one dynamically
+ * loaded library can use to meet up with another.
+ *
+ * On the first call of this function for a particular varName,
+ * a "rendezvous variable" is created with the given name.
+ * The value of the variable is a void pointer (initially set to NULL).
+ * Subsequent calls with the same varName just return the address of
+ * the existing variable. Once created, a rendezvous variable lasts
+ * for the life of the process.
+ *
+ * Dynamically loaded libraries can use rendezvous variables
+ * to find each other and share information: they just need to agree
+ * on the variable name and the data it will point to.
+ */
+void **
+find_rendezvous_variable(const char *varName)
+{
+ static HTAB *rendezvousHash = NULL;
+
+ char key[NAMEDATALEN];
+ rendezvousHashEntry *hentry;
+ bool found;
+
+ /* Create a hashtable if we haven't already done so in this process */
+ if (rendezvousHash == NULL)
+ {
+ HASHCTL ctl;
+
+ MemSet(&ctl, 0, sizeof(ctl));
+ ctl.keysize = NAMEDATALEN;
+ ctl.entrysize = sizeof(rendezvousHashEntry);
+ rendezvousHash = hash_create("Rendezvous variable hash",
+ 16,
+ &ctl,
+ HASH_ELEM);
+ }
+
+ /* Turn the varName into a fixed-size string */
+ StrNCpy(key, varName, sizeof(key));
+
+ /* Find or create the hashtable entry for this varName */
+ hentry = (rendezvousHashEntry *) hash_search(rendezvousHash,
+ key,
+ HASH_ENTER,
+ &found);
+
+ /* Initialize to NULL if first time */
+ if (!found)
+ hentry->varValue = NULL;
+
+ return &hentry->varValue;
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index b238aaec5ce..3b2cb2f9c89 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -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);
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0e16035ef6a..69c67471fc0 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.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
},
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index edecda549ee..b0c6cdf7634 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -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 = ''
#---------------------------------------------------------------------------
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 5b904cbad42..2e9e3f71820 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -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);
/*
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 07590c92942..8a050f5b7dc 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -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 */