aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-07-31 18:36:46 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-07-31 18:36:46 +0000
commit8b1ea2f58b5f6c65a06781250ef38418c20796a1 (patch)
tree7ecf8db773370daad151a5b977b2210755db3204
parent8488f25425fa9edb4d1264224c43053680232d47 (diff)
downloadpostgresql-8b1ea2f58b5f6c65a06781250ef38418c20796a1.tar.gz
postgresql-8b1ea2f58b5f6c65a06781250ef38418c20796a1.zip
Cause library-preload feature to report error if specified initialization
function is not found. Also, make all the PL libraries have initialization functions with standard names. Patch from Joe Conway.
-rw-r--r--doc/src/sgml/runtime.sgml36
-rw-r--r--src/backend/utils/init/miscinit.c4
-rw-r--r--src/pl/plperl/plperl.c39
-rw-r--r--src/pl/plpgsql/src/pl_comp.c6
-rw-r--r--src/pl/plpgsql/src/pl_handler.c44
-rw-r--r--src/pl/plpgsql/src/plpgsql.h3
-rw-r--r--src/pl/plpython/plpython.c38
-rw-r--r--src/pl/tcl/pltcl.c63
8 files changed, 176 insertions, 57 deletions
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 43b82043890..a44ccfde88a 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.197 2003/07/29 00:03:17 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.198 2003/07/31 18:36:17 tgl Exp $
-->
<Chapter Id="runtime">
@@ -1004,29 +1004,35 @@ SET ENABLE_SEQSCAN TO OFF;
<listitem>
<para>
This variable specifies one or more shared libraries that are
- to be preloaded at server start. An initialization function
- can also be optionally specified by adding a colon followed by
- the name of the initialization function after the library
- name. For example
- <literal>'$libdir/mylib:init_mylib'</literal> would cause
- <literal>mylib</> to be preloaded and <literal>init_mylib</>
- to be executed. If more than one library is to be loaded, they
- must be delimited with a comma.
+ to be preloaded at server start. A parameterless initialization
+ function can optionally be called for each library. To specify
+ that, add a colon and the name of the initialization function after
+ the library name. For example
+ <literal>'$libdir/mylib:mylib_init'</literal> would cause
+ <literal>mylib</> to be preloaded and <literal>mylib_init</>
+ to be executed. If more than one library is to be loaded, separate
+ their names with commas.
</para>
<para>
- If <literal>mylib</> is not found, the server will fail to
- start. However, if <literal>init_mylib</> is not found,
- <literal>mylib</> will still be preloaded without executing
- the initialization function.
+ If <literal>mylib</> or <literal>mylib_init</> are not found, the
+ server will fail to start.
+ </para>
+
+ <para>
+ PostgreSQL procedural language libraries may be preloaded in this way,
+ typically by using the syntax
+ <literal>'$libdir/plXXX:plXXX_init'</literal>
+ where <literal>XXX</literal> is <literal>pgsql</>,
+ <literal>perl</>, <literal>tcl</>, or <literal>python</>.
</para>
<para>
By preloading a shared library (and initializing it if
applicable), the library startup time is avoided when the
library is first used. However, the time to start each new
- server process may increase, even if that process never
- uses the library.
+ server process may increase, even if that process never
+ uses the library.
</para>
</listitem>
</varlistentry>
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 8f20f25dc19..4c4a7f61dff 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.108 2003/07/28 00:09:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.109 2003/07/31 18:36:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1165,7 +1165,7 @@ process_preload_libraries(char *preload_libraries_string)
}
initfunc = (func_ptr) load_external_function(filename, funcname,
- false, NULL);
+ true, NULL);
if (initfunc)
(*initfunc)();
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index fcbe55c9c2e..7edcac6c68b 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.37 2003/07/25 23:37:28 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.38 2003/07/31 18:36:28 tgl Exp $
*
**********************************************************************/
@@ -101,6 +101,7 @@ static void plperl_init_all(void);
static void plperl_init_interp(void);
Datum plperl_call_handler(PG_FUNCTION_ARGS);
+void plperl_init(void);
static Datum plperl_func_handler(PG_FUNCTION_ARGS);
@@ -128,12 +129,15 @@ perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
}
/**********************************************************************
- * plperl_init_all() - Initialize all
+ * plperl_init() - Initialize everything that can be
+ * safely initialized during postmaster
+ * startup.
+ *
+ * DO NOT make this static --- it has to be callable by preload
**********************************************************************/
-static void
-plperl_init_all(void)
+void
+plperl_init(void)
{
-
/************************************************************
* Do initialization only once
************************************************************/
@@ -168,6 +172,26 @@ plperl_init_all(void)
plperl_firstcall = 0;
}
+/**********************************************************************
+ * plperl_init_all() - Initialize all
+ **********************************************************************/
+static void
+plperl_init_all(void)
+{
+
+ /************************************************************
+ * Execute postmaster-startup safe initialization
+ ************************************************************/
+ if (plperl_firstcall)
+ plperl_init();
+
+ /************************************************************
+ * Any other initialization that must be done each time a new
+ * backend starts -- currently none
+ ************************************************************/
+
+}
+
/**********************************************************************
* plperl_init_interp() - Create the Perl interpreter
@@ -222,10 +246,9 @@ plperl_call_handler(PG_FUNCTION_ARGS)
Datum retval;
/************************************************************
- * Initialize interpreter on first call
+ * Initialize interpreter
************************************************************/
- if (plperl_firstcall)
- plperl_init_all();
+ plperl_init_all();
/************************************************************
* Connect to SPI manager
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 8ede81d061e..e08d6c82d75 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.63 2003/07/27 21:49:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.64 2003/07/31 18:36:35 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -106,7 +106,6 @@ static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
static void compute_function_hashkey(FmgrInfo *flinfo,
Form_pg_proc procStruct,
PLpgSQL_func_hashkey *hashkey);
-static void plpgsql_HashTableInit(void);
static PLpgSQL_function *plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key);
static void plpgsql_HashTableInsert(PLpgSQL_function *function,
PLpgSQL_func_hashkey *func_key);
@@ -1743,7 +1742,8 @@ compute_function_hashkey(FmgrInfo *flinfo,
}
}
-static void
+/* exported so we can call it from plpgsql_init() */
+void
plpgsql_HashTableInit(void)
{
HASHCTL ctl;
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index e77a2f9e0aa..0e0072e4ff4 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.15 2003/07/27 17:10:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.16 2003/07/31 18:36:35 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -44,6 +44,45 @@
#include "utils/builtins.h"
#include "utils/syscache.h"
+static int plpgsql_firstcall = 1;
+
+void plpgsql_init(void);
+static void plpgsql_init_all(void);
+
+
+/*
+ * plpgsql_init() - postmaster-startup safe initialization
+ *
+ * DO NOT make this static --- it has to be callable by preload
+ */
+void
+plpgsql_init(void)
+{
+ /* Do initialization only once */
+ if (!plpgsql_firstcall)
+ return;
+
+ plpgsql_HashTableInit();
+
+ plpgsql_firstcall = 0;
+}
+
+/*
+ * plpgsql_init_all() - Initialize all
+ */
+static void
+plpgsql_init_all(void)
+{
+ /* Execute any postmaster-startup safe initialization */
+ if (plpgsql_firstcall)
+ plpgsql_init();
+
+ /*
+ * Any other initialization that must be done each time a new
+ * backend starts -- currently none
+ */
+
+}
/* ----------
* plpgsql_call_handler
@@ -61,6 +100,9 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
PLpgSQL_function *func;
Datum retval;
+ /* perform initialization */
+ plpgsql_init_all();
+
/*
* Connect to SPI manager
*/
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index ae4d8909167..e12586011f1 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.37 2003/07/01 21:47:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.38 2003/07/31 18:36:35 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -613,6 +613,7 @@ extern PLpgSQL_row *plpgsql_build_rowtype(Oid classOid);
extern void plpgsql_adddatum(PLpgSQL_datum * new);
extern int plpgsql_add_initdatums(int **varnos);
extern void plpgsql_yyerror(const char *s);
+extern void plpgsql_HashTableInit(void);
/* ----------
* Functions in pl_handler.c
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 2a4c45e6e56..6f49e75ae47 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -29,7 +29,7 @@
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.35 2003/07/25 23:37:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.36 2003/07/31 18:36:39 tgl Exp $
*
*********************************************************************
*/
@@ -170,10 +170,12 @@ typedef struct PLyResultObject
/* function declarations
*/
-/* the only exported function, with the magic telling Postgresql
- * what function call interface it implements.
+/* Two exported functions: first is the magic telling Postgresql
+ * what function call interface it implements. Second allows
+ * preinitialization of the interpreter during postmaster startup.
*/
Datum plpython_call_handler(PG_FUNCTION_ARGS);
+void plpython_init(void);
PG_FUNCTION_INFO_V1(plpython_call_handler);
@@ -329,8 +331,7 @@ plpython_call_handler(PG_FUNCTION_ARGS)
enter();
- if (PLy_first_call)
- PLy_init_all();
+ PLy_init_all();
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI manager");
@@ -2302,11 +2303,22 @@ PLy_spi_error_string(int code)
/* language handler and interpreter initialization
*/
+/*
+ * plpython_init() - Initialize everything that can be
+ * safely initialized during postmaster
+ * startup.
+ *
+ * DO NOT make this static --- it has to be callable by preload
+ */
void
-PLy_init_all(void)
+plpython_init(void)
{
static volatile int init_active = 0;
+ /* Do initialization only once */
+ if (!PLy_first_call)
+ return;
+
enter();
if (init_active)
@@ -2327,6 +2339,20 @@ PLy_init_all(void)
leave();
}
+static void
+PLy_init_all(void)
+{
+ /* Execute postmaster-startup safe initialization */
+ if (PLy_first_call)
+ plpython_init();
+
+ /*
+ * Any other initialization that must be done each time a new
+ * backend starts -- currently none
+ */
+
+}
+
void
PLy_init_interp(void)
{
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 2f14245ee17..1375c9720cd 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.72 2003/07/25 23:37:31 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.73 2003/07/31 18:36:46 tgl Exp $
*
**********************************************************************/
@@ -128,7 +128,8 @@ typedef struct pltcl_query_desc
/**********************************************************************
* Global data
**********************************************************************/
-static int pltcl_firstcall = 1;
+static bool pltcl_pm_init_done = false;
+static bool pltcl_be_init_done = false;
static int pltcl_call_level = 0;
static int pltcl_restart_in_progress = 0;
static Tcl_Interp *pltcl_hold_interp = NULL;
@@ -149,6 +150,7 @@ static void pltcl_init_load_unknown(Tcl_Interp *interp);
Datum pltcl_call_handler(PG_FUNCTION_ARGS);
Datum pltclu_call_handler(PG_FUNCTION_ARGS);
+void pltcl_init(void);
static Datum pltcl_func_handler(PG_FUNCTION_ARGS);
@@ -197,17 +199,18 @@ perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
fmgr_info_cxt(functionId, finfo, TopMemoryContext);
}
-
/**********************************************************************
- * pltcl_init_all() - Initialize all
+ * pltcl_init() - Initialize all that's safe to do in the postmaster
+ *
+ * DO NOT make this static --- it has to be callable by preload
**********************************************************************/
-static void
-pltcl_init_all(void)
+void
+pltcl_init(void)
{
/************************************************************
* Do initialization only once
************************************************************/
- if (!pltcl_firstcall)
+ if (pltcl_pm_init_done)
return;
/************************************************************
@@ -240,8 +243,36 @@ pltcl_init_all(void)
Tcl_InitHashTable(pltcl_norm_query_hash, TCL_STRING_KEYS);
Tcl_InitHashTable(pltcl_safe_query_hash, TCL_STRING_KEYS);
- pltcl_firstcall = 0;
- return;
+ pltcl_pm_init_done = true;
+}
+
+/**********************************************************************
+ * pltcl_init_all() - Initialize all
+ **********************************************************************/
+static void
+pltcl_init_all(void)
+{
+ /************************************************************
+ * Execute postmaster-startup safe initialization
+ ************************************************************/
+ if (!pltcl_pm_init_done)
+ pltcl_init();
+
+ /************************************************************
+ * Any other initialization that must be done each time a new
+ * backend starts:
+ * - Try to load the unknown procedure from pltcl_modules
+ ************************************************************/
+ if (!pltcl_be_init_done)
+ {
+ if (SPI_connect() != SPI_OK_CONNECT)
+ elog(ERROR, "SPI_connect failed");
+ pltcl_init_load_unknown(pltcl_norm_interp);
+ pltcl_init_load_unknown(pltcl_safe_interp);
+ if (SPI_finish() != SPI_OK_FINISH)
+ elog(ERROR, "SPI_finish failed");
+ pltcl_be_init_done = true;
+ }
}
@@ -271,15 +302,6 @@ pltcl_init_interp(Tcl_Interp *interp)
pltcl_SPI_execp, NULL, NULL);
Tcl_CreateCommand(interp, "spi_lastoid",
pltcl_SPI_lastoid, NULL, NULL);
-
- /************************************************************
- * Try to load the unknown procedure from pltcl_modules
- ************************************************************/
- if (SPI_connect() != SPI_OK_CONNECT)
- elog(ERROR, "SPI_connect failed");
- pltcl_init_load_unknown(interp);
- if (SPI_finish() != SPI_OK_FINISH)
- elog(ERROR, "SPI_finish failed");
}
@@ -373,10 +395,9 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
FunctionCallInfo save_fcinfo;
/************************************************************
- * Initialize interpreters on first call
+ * Initialize interpreters
************************************************************/
- if (pltcl_firstcall)
- pltcl_init_all();
+ pltcl_init_all();
/************************************************************
* Connect to SPI manager