]> granicus.if.org Git - postgresql/commitdiff
Cause library-preload feature to report error if specified initialization
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 31 Jul 2003 18:36:46 +0000 (18:36 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 31 Jul 2003 18:36:46 +0000 (18:36 +0000)
function is not found.  Also, make all the PL libraries have initialization
functions with standard names.  Patch from Joe Conway.

doc/src/sgml/runtime.sgml
src/backend/utils/init/miscinit.c
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/pl_handler.c
src/pl/plpgsql/src/plpgsql.h
src/pl/plpython/plpython.c
src/pl/tcl/pltcl.c

index 43b8204389044e8950d28ccd88a232a498df603b..a44ccfde88a9135131e7aef6d44eb28705227e61 100644 (file)
@@ -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>
index 8f20f25dc19dff4b467a4d6ef28863a212224c44..4c4a7f61dff668a19a8c28e63bfea8a182727a32 100644 (file)
@@ -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)();
 
index fcbe55c9c2e36a2b10c98253e418648ac917e6ab..7edcac6c68ba5839e46ec533bc9b522dba1df403 100644 (file)
@@ -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
index 8ede81d061ec726e9b76a2a0f0e19cfa2c62a54e..e08d6c82d7589c9ccfc2eef4af10eb821f9249a7 100644 (file)
@@ -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;
index e77a2f9e0aaaad03b84da6d146d56c96ccd9d92c..0e0072e4ff4c4f9693814a7e01c90f3fb204c53e 100644 (file)
@@ -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.
  *
 #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
         */
index ae4d890916756a8232c030e578fb88cd27e94a10..e12586011f13f5c57cd51d30c95db1cd9e282a85 100644 (file)
@@ -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
index 2a4c45e6e56bd9568a11d58120a860e787452c69..6f49e75ae4790ef08ba31d29a57091aab12076fb 100644 (file)
@@ -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)
 {
index 2f14245ee176e8cf24b8c52cdecbcf0aab27dd18..1375c9720cd4767a5eb8ee4c169f4d80bd794655 100644 (file)
@@ -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