Commit 8b1ea2f5 authored by Tom Lane's avatar Tom Lane

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.
parent 8488f254
<!--
$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>
......
......@@ -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)();
......
......@@ -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
......
......@@ -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;
......
......@@ -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
*/
......
......@@ -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
......
......@@ -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)
{
......
......@@ -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
......
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