diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 43b8204389044e8950d28ccd88a232a498df603b..a44ccfde88a9135131e7aef6d44eb28705227e61 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 8f20f25dc19dff4b467a4d6ef28863a212224c44..4c4a7f61dff668a19a8c28e63bfea8a182727a32 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 fcbe55c9c2e36a2b10c98253e418648ac917e6ab..7edcac6c68ba5839e46ec533bc9b522dba1df403 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 8ede81d061ec726e9b76a2a0f0e19cfa2c62a54e..e08d6c82d7589c9ccfc2eef4af10eb821f9249a7 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 e77a2f9e0aaaad03b84da6d146d56c96ccd9d92c..0e0072e4ff4c4f9693814a7e01c90f3fb204c53e 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 ae4d890916756a8232c030e578fb88cd27e94a10..e12586011f13f5c57cd51d30c95db1cd9e282a85 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 2a4c45e6e56bd9568a11d58120a860e787452c69..6f49e75ae4790ef08ba31d29a57091aab12076fb 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 2f14245ee176e8cf24b8c52cdecbcf0aab27dd18..1375c9720cd4767a5eb8ee4c169f4d80bd794655 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