You are viewing a plain text version of this content. The canonical link for it is here.
Posted to site-cvs@tcl.apache.org by mx...@apache.org on 2015/12/26 01:22:11 UTC

svn commit: r1721698 - in /tcl/rivet/trunk: ./ doc/xml/ src/ src/mod_rivet/

Author: mxmanghi
Date: Sat Dec 26 00:22:11 2015
New Revision: 1721698

URL: http://svn.apache.org/viewvc?rev=1721698&view=rev
Log:
    * src/mod_rivet/worker_prefork_common.c: functions common to both the prefork
    and worker bridges, but not general enough bur rather specific to the worker
    model adopted by them
    * src/mod_rivet/rivet_lazy_mpm.c: further development, now capable of serving
    rivet requests, but needs to be completed.
    * src/mod_rivet/mod_rivet_common.c: more stuff moved from mod_rivet to this file
    * src/mod_rivet/mod_rivet.h: new data organization with bridge specific thread
    private data
    * src/mod_rivet/Tclwebapache.c: API changed from Tclwebreq pointers to 
    thread private data that is supposed to store most of the thread environment


Added:
    tcl/rivet/trunk/src/mod_rivet/rivetCore.h
    tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c
Modified:
    tcl/rivet/trunk/ChangeLog
    tcl/rivet/trunk/doc/xml/internals.xml
    tcl/rivet/trunk/src/Makefile.am
    tcl/rivet/trunk/src/TclWeb.h
    tcl/rivet/trunk/src/mod_rivet/TclWebapache.c
    tcl/rivet/trunk/src/mod_rivet/mod_rivet.c
    tcl/rivet/trunk/src/mod_rivet/mod_rivet.h
    tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c
    tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h
    tcl/rivet/trunk/src/mod_rivet/rivetCore.c
    tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c
    tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c
    tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c
    tcl/rivet/trunk/src/rivet.h

Modified: tcl/rivet/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/ChangeLog?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/ChangeLog (original)
+++ tcl/rivet/trunk/ChangeLog Sat Dec 26 00:22:11 2015
@@ -1,3 +1,15 @@
+2015-12-26 Massimo Manghi <mx...@apache.org>
+    * src/mod_rivet/worker_prefork_common.c: functions common to both the prefork
+    and worker bridges, but not general enough bur rather specific to the worker
+    model adopted by them
+    * src/mod_rivet/rivet_lazy_mpm.c: further development, now capable of serving
+    rivet requests, but needs to be completed.
+    * src/mod_rivet/mod_rivet_common.c: more stuff moved from mod_rivet to this file
+    * src/mod_rivet/mod_rivet.h: new data organization with bridge specific thread
+    private data
+    * src/mod_rivet/Tclwebapache.c: API changed from Tclwebreq pointers to 
+    thread private data that is supposed to store most of the thread environment
+
 2015-12-22 Massimo Manghi <mx...@apache.org>
     * src/mod_rivet/rivet_lazy_mpm.c: taking a snapshot of the current development
     as this code proved to be quite robust when stressed using 'ab'

Modified: tcl/rivet/trunk/doc/xml/internals.xml
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/doc/xml/internals.xml?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/doc/xml/internals.xml (original)
+++ tcl/rivet/trunk/doc/xml/internals.xml Sat Dec 26 00:22:11 2015
@@ -107,9 +107,10 @@
 				interpreters to orderly exit. This pointer can be NULL if the bridge 
 				has no special need when a child process must exit.
 				</listitem>
-				<listitem><emphasis>mpm_master_interp</emphasis>: This pointer must
-				be assigned with a valid function returning the child process master
-				interpreter descriptor. The master interpreter should be either the only 
+				<listitem><emphasis>mpm_master_interp</emphasis>: This function
+				is mainly existing to allow fork capable bridges to reuturn
+				the child process master interpreter descriptor. 
+				In general the master interpreter should be either the only 
 				interpreter descriptor pointer of the child process (when 
 				<command>SeparateVirtualInterps</command> is off (default)) or one of 
 				the virtual host interpreter pointers. The current implementation of

Modified: tcl/rivet/trunk/src/Makefile.am
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/Makefile.am?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/Makefile.am (original)
+++ tcl/rivet/trunk/src/Makefile.am Sat Dec 26 00:22:11 2015
@@ -56,12 +56,12 @@ mod_rivet_la_CPPFLAGS = -I@rivet_core@ -
 lib_libmpmdir = @RIVET_TCL_TARGET@/mpm
 lib_libmpm_LTLIBRARIES = rivet_worker_mpm.la rivet_prefork_mpm.la rivet_lazy_mpm.la
 
-rivet_worker_mpm_la_SOURCES = @rivet_core@/rivet_worker_mpm.c
+rivet_worker_mpm_la_SOURCES = @rivet_core@/rivet_worker_mpm.c @rivet_core@/worker_prefork_common.c
 rivet_worker_mpm_la_LDFLAGS = @TCL_STUB_LIB_SPEC@ @APXS_LDFLAGS@ -module -avoid-version
 rivet_worker_mpm_la_LIBADD  = @APXS_LIBS@
 rivet_worker_mpm_la_CPPFLAGS = @apache_include@ -I@rivet_core@ @TCL_INCLUDES@ @APXS_CPPFLAGS@ @APXS_INCLUDES@ @APR_CPPFLAGS@ @APR_INCLUDES@ @APU_INCLUDES@ -I@apache_request@ -I@RIVET_BASE_INCLUDE@
 
-rivet_prefork_mpm_la_SOURCES = @rivet_core@/rivet_prefork_mpm.c
+rivet_prefork_mpm_la_SOURCES = @rivet_core@/rivet_prefork_mpm.c @rivet_core@/worker_prefork_common.c
 rivet_prefork_mpm_la_LDFLAGS = @TCL_STUB_LIB_SPEC@ @APXS_LDFLAGS@ -module -avoid-version
 rivet_prefork_mpm_la_LIBADD  = @APXS_LIBS@
 rivet_prefork_mpm_la_CPPFLAGS = @apache_include@ -I@rivet_core@ @TCL_INCLUDES@ @APXS_CPPFLAGS@ @APXS_INCLUDES@ @APR_CPPFLAGS@ @APR_INCLUDES@ @APU_INCLUDES@ -I@apache_request@ -I@RIVET_BASE_INCLUDE@

Modified: tcl/rivet/trunk/src/TclWeb.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/TclWeb.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/TclWeb.h (original)
+++ tcl/rivet/trunk/src/TclWeb.h Sat Dec 26 00:22:11 2015
@@ -110,9 +110,9 @@ int TclWeb_GetVarNames(Tcl_Obj *result,
 
 int TclWeb_GetAllVars(Tcl_Obj *result, int source, TclWebRequest *req);
 
-int TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWebRequest *req);
+int TclWeb_GetEnvVars(Tcl_Obj *envvar, rivet_thread_private *p);
 
-int TclWeb_GetHeaderVars(Tcl_Obj *headersvar, TclWebRequest *req);
+int TclWeb_GetHeaderVars(Tcl_Obj *headersvar, rivet_thread_private *p);
 
 /*
  *-----------------------------------------------------------------------------
@@ -255,7 +255,7 @@ char *TclWeb_StringToUtf(char *in, TclWe
 
 Tcl_Obj * TclWeb_StringToUtfToObj(char *in, TclWebRequest *req);
 
-char *TclWeb_GetEnvVar( TclWebRequest *req, char * );
+char *TclWeb_GetEnvVar(rivet_thread_private *,char *);
 
 char *TclWeb_GetVirtualFile( TclWebRequest *req, char *virtualname );
 

Modified: tcl/rivet/trunk/src/mod_rivet/TclWebapache.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/TclWebapache.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/TclWebapache.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/TclWebapache.c Sat Dec 26 00:22:11 2015
@@ -40,7 +40,7 @@
 #include "TclWeb.h"
 
 extern module rivet_module;
-extern apr_threadkey_t* rivet_thread_key;
+extern mod_rivet_globals* module_globals;
 #define TCLWEBPOOL req->req->pool
 
 #define BUFSZ 4096
@@ -435,11 +435,11 @@ TclWeb_VarNumber(Tcl_Obj *result, int so
         apr_table_elts(req->apachereq->parms);
 
     if (source == VAR_SRC_QUERYSTRING) {
-	Tcl_SetIntObj(result, req->apachereq->nargs);
+	    Tcl_SetIntObj(result, req->apachereq->nargs);
     } else if (source == VAR_SRC_POST) {
-	Tcl_SetIntObj(result, parmsarray->nelts - req->apachereq->nargs);
+	    Tcl_SetIntObj(result, parmsarray->nelts - req->apachereq->nargs);
     } else {
-	Tcl_SetIntObj(result, parmsarray->nelts);
+	    Tcl_SetIntObj(result, parmsarray->nelts);
     }
 
     return TCL_OK;
@@ -450,21 +450,25 @@ TclWeb_VarNumber(Tcl_Obj *result, int so
  * have already done so, we don't need to do it again.
  */
 static void
-TclWeb_InitEnvVars( TclWebRequest *req )
+TclWeb_InitEnvVars (rivet_thread_private* private)
 {
-    rivet_server_conf *rsc;
-    apr_table_t *table = req->req->subprocess_env;
+    //rivet_server_conf *rsc;
     char *timefmt = DEFAULT_TIME_FORMAT;
     char *t;
-    apr_time_t date = req->req->request_time;
+    apr_time_t date;
 #ifndef WIN32
     struct passwd *pw;
 #endif /* ndef WIN32 */
-    rivet_thread_private* private;
+    TclWebRequest *req;
+    apr_table_t *table;  
+
+    req = private->req;
+    table = req->req->subprocess_env;
+    date = req->req->request_time;
 
     if( req->environment_set ) return;
 
-    rsc = RIVET_SERVER_CONF( req->req->server->module_config );
+    //rsc = RIVET_SERVER_CONF( req->req->server->module_config );
 
     /* Retrieve cgi variables. */
     ap_add_cgi_vars( req->req );
@@ -508,17 +512,16 @@ TclWeb_InitEnvVars( TclWebRequest *req )
 
     /* Here we create some variables with Rivet internal information. */
 
-    ap_assert (apr_threadkey_private_get ((void **)&private,rivet_thread_key) == APR_SUCCESS);
     apr_table_set (table, "RIVET_CACHE_FREE",
-            (char*) apr_psprintf (TCLWEBPOOL, "%d",private->interps[rsc->idx]->cache_free));
+            (char*) apr_psprintf (TCLWEBPOOL, "%d",RIVET_PEEK_INTERP(private,private->running_conf)->cache_free));
     apr_table_set (table, "RIVET_CACHE_SIZE",
-            (char*) apr_psprintf (TCLWEBPOOL, "%d",private->interps[rsc->idx]->cache_size));
+            (char*) apr_psprintf (TCLWEBPOOL, "%d",RIVET_PEEK_INTERP(private,private->running_conf)->cache_size));
 
     req->environment_set = 1;
 }
 
 int
-TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWebRequest *req)
+TclWeb_GetEnvVars(Tcl_Obj *envvar,rivet_thread_private* private)
 {
     int i;
 
@@ -526,9 +529,12 @@ TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWe
     apr_table_entry_t  *env;
     Tcl_Obj *key;
     Tcl_Obj *val;
+    TclWebRequest *req;
+
 
-    TclWeb_InitEnvVars( req );
+    TclWeb_InitEnvVars(private);
 
+    req = private->req;
     Tcl_IncrRefCount(envvar);
     /* Transfer Apache internal CGI variables to TCL request namespace. */
     env_arr = (apr_array_header_t *) apr_table_elts(req->req->subprocess_env);
@@ -563,16 +569,18 @@ TclWeb_GetEnvVars(Tcl_Obj *envvar, TclWe
 }
 
 int
-TclWeb_GetHeaderVars(Tcl_Obj *headersvar, TclWebRequest *req)
+TclWeb_GetHeaderVars(Tcl_Obj *headersvar,rivet_thread_private* private)
 {
     int i;
-
+    TclWebRequest *req;
     apr_array_header_t *hdrs_arr;
     apr_table_entry_t  *hdrs;
     Tcl_Obj *key;
     Tcl_Obj *val;
 
-    TclWeb_InitEnvVars( req );
+    req = private->req;
+
+    TclWeb_InitEnvVars(private);
 
     Tcl_IncrRefCount(headersvar);
     /* Transfer client request headers to TCL request namespace. */
@@ -580,19 +588,19 @@ TclWeb_GetHeaderVars(Tcl_Obj *headersvar
     hdrs = (apr_table_entry_t *) hdrs_arr->elts;
     for (i = 0; i < hdrs_arr->nelts; ++i)
     {
-	if (!hdrs[i].key)
-	    continue;
+        if (!hdrs[i].key)
+            continue;
 
-	key = TclWeb_StringToUtfToObj(hdrs[i].key, req);
-	val = TclWeb_StringToUtfToObj(hdrs[i].val, req);
-	Tcl_IncrRefCount(key);
-	Tcl_IncrRefCount(val);
+        key = TclWeb_StringToUtfToObj(hdrs[i].key, req);
+        val = TclWeb_StringToUtfToObj(hdrs[i].val, req);
+        Tcl_IncrRefCount(key);
+        Tcl_IncrRefCount(val);
 
-        /* See comment in TclWeb_GetEnvVars concerning Bug 48963*/
+            /* See comment in TclWeb_GetEnvVars concerning Bug 48963*/
 
         Tcl_ObjSetVar2(req->interp, headersvar, key, val, 0);
- 	Tcl_DecrRefCount(key);
-	Tcl_DecrRefCount(val);
+        Tcl_DecrRefCount(key);
+        Tcl_DecrRefCount(val);
     }
 
     /* Transfer Apache internal CGI variables to TCL request namespace. */
@@ -767,11 +775,13 @@ int TclWeb_UploadNames(Tcl_Obj *names, T
 }
 
 char *
-TclWeb_GetEnvVar( TclWebRequest *req, char *key )
+TclWeb_GetEnvVar(rivet_thread_private* private,char *key)
 {
     char *val;
+    TclWebRequest *req;
 
-    TclWeb_InitEnvVars( req );
+    req = private->req;
+    TclWeb_InitEnvVars(private);
 
     /* Check to see if it's a header variable first. */
     val = (char *)apr_table_get( req->req->headers_in, key );

Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet.c Sat Dec 26 00:22:11 2015
@@ -59,6 +59,7 @@
 #include "rivet.h"
 #include "mod_rivet_common.h"
 #include "rivetParser.h"
+#include "rivetCore.h"
 
 rivet_interp_globals    interp_globals;
 
@@ -66,9 +67,6 @@ extern Tcl_ChannelType   RivetChan;
 apr_threadkey_t*         rivet_thread_key    = NULL;
 mod_rivet_globals*       module_globals      = NULL;
 
-void        Rivet_PerInterpInit (rivet_thread_interp* interp, 
-                                 rivet_thread_private* private, 
-                                 server_rec *s, apr_pool_t *p );
 static int  Rivet_ExecuteAndCheck (rivet_thread_private *private, Tcl_Obj *tcl_script_obj);
 int         Rivet_InitCore (Tcl_Interp *interp,rivet_thread_private* p); 
 
@@ -114,29 +112,6 @@ Rivet_PrintErrorMessage (Tcl_Interp* int
     Tcl_DecrRefCount(errormsg);
 }
 
-
-/*----------------------------------------------------------------------------
- * -- Rivet_RunningScripts
- *
- *
- *
- *-----------------------------------------------------------------------------
- */
-
-static running_scripts*
-Rivet_RunningScripts (  apr_pool_t*         pool, 
-                        running_scripts*    scripts, 
-                        rivet_server_conf*  rivet_conf)
-{
-    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_before_script);
-    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_after_script);
-    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_error_script);
-    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_abort_script);
-    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,after_every_script);
-
-    return scripts;
-}
-
 /*-----------------------------------------------------------------------------
  * -- Rivet_ReleaseScript
  *
@@ -157,286 +132,6 @@ Rivet_ReleaseScripts (running_scripts* s
 }
 
 /*
- *-----------------------------------------------------------------------------
- * Rivet_CreateCache --
- *
- * Arguments:
- *     rsc: pointer to a server_rec structure
- *
- * Results:
- *     None
- *
- * Side Effects:
- *
- *-----------------------------------------------------------------------------
- */
-
-static void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj)
-{
-    interp_obj->objCacheList = apr_pcalloc(p, (signed)((interp_obj->cache_size)*sizeof(char *)));
-    interp_obj->objCache = apr_pcalloc(p, sizeof(Tcl_HashTable));
-    Tcl_InitHashTable(interp_obj->objCache, TCL_STRING_KEYS);
-}
-
-/*
- * Rivet_DuplicateVhostInterp
- *
- *
- */
-
-static rivet_thread_interp* 
-Rivet_DuplicateVHostInterp(apr_pool_t* pool, rivet_thread_interp* source_obj)
-{
-    rivet_thread_interp* interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
-
-    interp_obj->interp      = source_obj->interp;
-    interp_obj->channel     = source_obj->channel;
-    interp_obj->cache_free  = source_obj->cache_free;
-    interp_obj->cache_size  = source_obj->cache_size;
-
-    /* TODO: decouple cache by creating a new cache object */
-
-    if (interp_obj->cache_size) {
-        Rivet_CreateCache(pool,interp_obj); 
-    }
-
-    interp_obj->pool            = source_obj->pool;
-    interp_obj->scripts         = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
-    interp_obj->per_dir_scripts = apr_hash_make(pool); 
-    interp_obj->flags           = source_obj->flags;
-    return interp_obj;
-}
-
- /* XXX: the pool passed to Rivet_NewVHostInterp must be the private pool of
-  * a rivet_thread_private object 
-  */
-
-rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool)
-{
-    extern int              ap_max_requests_per_child;
-    rivet_thread_interp*    interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
-    rivet_server_conf*      rsc;
-
-    /* The cache size is global so we take it from here */
-    
-    rsc = RIVET_SERVER_CONF (module_globals->server->module_config);
-
-    /* This calls needs the root server_rec just for logging purposes*/
-
-    interp_obj->interp = Rivet_CreateTclInterp(module_globals->server); 
-
-    /* We now read from the pointers to the cache_size and cache_free conf parameters
-     * for compatibility with mod_rivet current version, but these values must become
-     * integers not pointers
-     */
-    
-    if (rsc->default_cache_size < 0) {
-        if (ap_max_requests_per_child != 0) {
-            interp_obj->cache_size = ap_max_requests_per_child / 5;
-        } else {
-            interp_obj->cache_size = 50;    // Arbitrary number
-        }
-    } else if (rsc->default_cache_size > 0) {
-        interp_obj->cache_size = rsc->default_cache_size;
-    }
-
-    if (interp_obj->cache_size > 0) {
-        interp_obj->cache_free = interp_obj->cache_size;
-    }
-
-    /* we now create memory from the cache pool as subpool of the thread private pool */
- 
-    if (apr_pool_create(&interp_obj->pool, pool) != APR_SUCCESS)
-    {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server, 
-                     MODNAME ": could not initialize cache private pool");
-        return NULL;
-    }
-
-    // Initialize cache structures
-
-    if (interp_obj->cache_size) {
-        Rivet_CreateCache(pool,interp_obj); 
-    }
-
-    interp_obj->flags = 0;
-
-    interp_obj->scripts         = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
-    interp_obj->per_dir_scripts = apr_hash_make(pool); 
-
-    return interp_obj;
-}
-
-/* -- Rivet_VirtualHostsInterps 
- *
- * The server_rec chain is walked through and server configurations is read to
- * set up the thread private configuration and interpreters database
- *
- *  Arguments:
- *
- *      rivet_thread_private* private;
- *
- *  Returned value:
- *
- *     a new rivet_thread_private object
- * 
- *  Side effects:
- *
- *     GlobalInitScript and ChildInitScript are run at this stage
- *     
- */
-
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private)
-{
-    server_rec*         s;
-    server_rec*         root_server = module_globals->server;
-    rivet_server_conf*  root_server_conf;
-    rivet_server_conf*  myrsc; 
-    rivet_thread_interp* root_interp;
-    void*               parentfunction;     /* this is topmost initialization script */
-    void*               function;
-
-    root_server_conf = RIVET_SERVER_CONF (root_server->module_config);
-    
-    root_interp = (*RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp))();
-
-    /* we must assume the module was able to create the root interprter otherwise
-     * it's just a null module. I try to have also this case to develop experimental
-     * bridges without the Tcl stuff 
-     */ 
-
-    //if (root_interp == NULL) return private;
-
-    ap_assert (root_interp != NULL);
-
-    /* Using the root interpreter we evaluate the global initialization script, if any */
-
-    if (root_server_conf->rivet_global_init_script != NULL) {
-        Tcl_Obj* global_tcl_script;
-
-        global_tcl_script = Tcl_NewStringObj(root_server_conf->rivet_global_init_script,-1);
-        Tcl_IncrRefCount(global_tcl_script);
-        if (Tcl_EvalObjEx(root_interp->interp, global_tcl_script, 0) != TCL_OK)
-        {
-            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server, 
-                         MODNAME ": Error running GlobalInitScript '%s': %s",
-                         root_server_conf->rivet_global_init_script,
-                         Tcl_GetVar(root_interp->interp, "errorInfo", 0));
-        } else {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, 
-                         MODNAME ": GlobalInitScript '%s' successful",
-                         root_server_conf->rivet_global_init_script);
-        }
-        Tcl_DecrRefCount(global_tcl_script);
-    }
-
-    /* then we proceed assigning/creating the interpreters for the
-     * virtual hosts known to the server
-     */
-
-    parentfunction = root_server_conf->rivet_child_init_script;
-
-    for (s = root_server; s != NULL; s = s->next)
-    {
-        rivet_thread_interp*   rivet_interp;
-
-        myrsc = RIVET_SERVER_CONF(s->module_config);
-
-        /* by default we assign the root_interpreter as
-         * interpreter of the virtual host. In case of separate
-         * virtual interpreters we create new ones for each
-         * virtual host 
-         */
-
-        rivet_interp = root_interp;
-
-        if (s == root_server)
-        {
-            Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
-        }
-        else 
-        {
-            if (root_server_conf->separate_virtual_interps)
-            {
-                rivet_interp = Rivet_NewVHostInterp(private->pool);
-                if (myrsc->separate_channels)
-                {
-                    rivet_interp->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
-                    Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
-                }
-                else
-                {
-                    rivet_interp->channel = private->channel;
-                }
-            }
-            else
-            {
-                rivet_interp = Rivet_DuplicateVHostInterp(private->pool,root_interp);           
-            }
-        }
-
-        /* interpreter base running scripts definition and initialization */
-
-        rivet_interp->scripts = Rivet_RunningScripts (private->pool,rivet_interp->scripts,myrsc);
-
-        private->interps[myrsc->idx] = rivet_interp;
-
-        /* Basic Rivet packages and libraries are loaded here */
-
-        if ((rivet_interp->flags & RIVET_INTERP_INITIALIZED) == 0)
-        {
-            Rivet_PerInterpInit(rivet_interp, private, root_server, private->pool);
-        }
-
-        /*  TODO: check if it's absolutely necessary to lock the pool_mutex in order
-         *  to allocate from the module global pool
-         */
-
-        /*  this stuff must be allocated from the module global pool which
-         *  has the child process' same lifespan
-         */
-
-        apr_thread_mutex_lock(module_globals->pool_mutex);
-        myrsc->server_name = (char*) apr_pstrdup (private->pool, s->server_hostname);
-        apr_thread_mutex_unlock(module_globals->pool_mutex);
-
-        /* when configured a child init script gets evaluated */
-
-        function = myrsc->rivet_child_init_script;
-        if (function && 
-            (s == root_server || root_server_conf->separate_virtual_interps || function != parentfunction))
-        {
-            char*       errmsg = MODNAME ": Error in Child init script: %s";
-            Tcl_Interp* interp = rivet_interp->interp;
-            Tcl_Obj*    tcl_child_init = Tcl_NewStringObj(function,-1);
-
-            Tcl_IncrRefCount(tcl_child_init);
-            Tcl_Preserve (interp);
-
-            /* There is a lot of passing around of pointers among various record 
-             * objects. We should understand if this is all that necessary.
-             * Here we assign the server_rec pointer to the interpreter which
-             * is wrong, because without separate interpreters it doens't make
-             * any sense. TODO
-             */
-
-            if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK) {
-                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
-                             errmsg, function);
-                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server, 
-                             "errorCode: %s", Tcl_GetVar(interp, "errorCode", 0));
-                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server, 
-                             "errorInfo: %s", Tcl_GetVar(interp, "errorInfo", 0));
-            }
-            Tcl_Release (interp);
-            Tcl_DecrRefCount(tcl_child_init);
-        }
-    }
-    return private;
-}
-
-
-/*
  * -- Rivet_SendContent
  *
  *   Set things up to execute a Tcl script or parse a rvt template, prepare
@@ -478,7 +173,7 @@ Rivet_SendContent(rivet_thread_private *
 
     /* the interp index in the private data can not be changed by a config merge */
 
-    interp_obj = private->interps[private->running_conf->idx];
+    interp_obj = RIVET_PEEK_INTERP(private,private->running_conf);
     private->running = interp_obj->scripts;
     running_channel = interp_obj->channel;
 
@@ -662,7 +357,7 @@ Rivet_SendContent(rivet_thread_private *
         //if (Tcl_EvalObjEx(interp_obj->interp,private->running->after_every_script,0) == TCL_ERROR)
         if (Rivet_ExecuteAndCheck(private,private->running->after_every_script) == TCL_ERROR)
         {
-            Rivet_PrintErrorMessage(private->interps[private->running_conf->idx]->interp,
+            Rivet_PrintErrorMessage(RIVET_PEEK_INTERP(private,private->running_conf)->interp,
                                     "<b>Rivet AfterEveryScript failed</b>");
         }
     }
@@ -791,7 +486,7 @@ static int
 Rivet_RunAbortScript (rivet_thread_private *private)
 {
     int retcode = TCL_OK;
-    Tcl_Interp* interp = private->interps[private->running_conf->idx]->interp;
+    Tcl_Interp* interp = RIVET_PEEK_INTERP(private,private->running_conf)->interp;
 
     if (private->running->rivet_abort_script) 
     {
@@ -857,7 +552,7 @@ Rivet_ExecuteAndCheck(rivet_thread_priva
     int           tcl_result;
     rivet_thread_interp* interp_obj;
 
-    interp_obj = private->interps[private->running_conf->idx];
+    interp_obj = RIVET_PEEK_INTERP(private,private->running_conf);
     //rivet_interp_globals *globals = Tcl_GetAssocData(interp_obj->interp, "rivet", NULL);
 
     Tcl_Preserve (interp_obj->interp);
@@ -961,7 +656,7 @@ Rivet_ParseExecFile(rivet_thread_private
 
     /* We have to fetch the interpreter data from the thread private environment */
 
-    rivet_interp = private->interps[private->running_conf->idx];
+    rivet_interp = RIVET_PEEK_INTERP(private,private->running_conf);
     interp = rivet_interp->interp;
 
     /* If the user configuration has indeed been updated, I guess that
@@ -1217,140 +912,6 @@ Rivet_CreateTclInterp (server_rec* s)
     return interp;
 }
 
-/*
- *-----------------------------------------------------------------------------
- *
- * Rivet_PerInterpInit --
- *
- *  Do the initialization that needs to happen for every
- *  interpreter.
- *
- * Results:
- *  None.
- *
- * Side Effects:
- *  None.
- *
- *-----------------------------------------------------------------------------
- */
-void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p)
-{
-    rivet_interp_globals*   globals     = NULL;
-    Tcl_Obj*                auto_path   = NULL;
-    Tcl_Obj*                rivet_tcl   = NULL;
-    Tcl_Interp*             interp      = interp_obj->interp;
-
-    ap_assert (interp != (Tcl_Interp *)NULL);
-    Tcl_Preserve (interp);
-
-    /* Set up interpreter associated data */
-
-    globals = apr_pcalloc (p, sizeof(rivet_interp_globals));
-    Tcl_SetAssocData (interp,"rivet",NULL,globals);
-    
-    /* 
-     * abort_page status variables in globals are set here and then 
-     * reset in Rivet_SendContent just before the request processing is 
-     * completed 
-     */
-
-    /* Rivet commands namespace is created */
-
-    globals->rivet_ns = Tcl_CreateNamespace (interp,RIVET_NS,NULL,
-                                            (Tcl_NamespaceDeleteProc *)NULL);
-    //globals->req    = TclWeb_NewRequestObject (p); 
-    //globals->r      = NULL;
-    //globals->srec   = s;
-
-    /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
-
-    /* We put in front the auto_path list the path to the directory where
-     * init.tcl is located (provides package Rivet, previously RivetTcl)
-     */
-
-    auto_path = Tcl_GetVar2Ex(interp,"auto_path",NULL,TCL_GLOBAL_ONLY);
-
-    rivet_tcl = Tcl_NewStringObj(RIVET_DIR,-1);
-    Tcl_IncrRefCount(rivet_tcl);
-
-    if (Tcl_IsShared(auto_path)) {
-        auto_path = Tcl_DuplicateObj(auto_path);
-    }
-
-    if (Tcl_ListObjReplace(interp,auto_path,0,0,1,&rivet_tcl) == TCL_ERROR)
-    {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s, 
-                     MODNAME ": error setting auto_path: %s",
-                     Tcl_GetStringFromObj(auto_path,NULL));
-    } else {
-        Tcl_SetVar2Ex(interp,"auto_path",NULL,auto_path,TCL_GLOBAL_ONLY);
-    }
-
-    Tcl_DecrRefCount(rivet_tcl);
-
-    /* Initialize the interpreter with Rivet's Tcl commands. */
-
-    if (private == NULL)
-    {
-        /* reduced core for the server init interpreter */
-
-        // RIVET_OBJ_CMD ("inspect",Rivet_InspectCmd,private);
-        
-    } 
-    else
-    {
-        /* full fledged rivet core */
-
-        Rivet_InitCore(interp,private);
-
-    }
-
-    /* Create a global array with information about the server. */
-    Rivet_InitServerVariables(interp, p );
-
-    /* Loading into the interpreter commands in librivet.so */
-    /* Tcl Bug #3216070 has been solved with 8.5.10 and commands shipped with
-     * Rivetlib can be mapped at this stage
-     */
-
-    if (Tcl_PkgRequire(interp, RIVETLIB_TCL_PACKAGE, RIVET_VERSION, 1) == NULL)
-    {
-        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
-                     MODNAME ": Error loading rivetlib package: %s",
-                     Tcl_GetStringResult(interp) );
-        exit(1);
-    }
-
-    /*  If rivet is configured to export the ::rivet namespace commands we set the
-     *  array variable ::rivet::module_conf(export_namespace_commands) before calling init.tcl
-     *  This array will be unset after commands are exported.
-     */
-
-    Tcl_SetVar2Ex(interp,"module_conf","export_namespace_commands",Tcl_NewIntObj(RIVET_NAMESPACE_EXPORT),0);
-    Tcl_SetVar2Ex(interp,"module_conf","import_rivet_commands",Tcl_NewIntObj(RIVET_NAMESPACE_IMPORT),0);
-
-    /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
-
-    /* Watch out! Calling Tcl_PkgRequire with a version number binds this module to
-     * the Rivet package revision number in rivet/init.tcl
-     *
-     * RIVET_TCL_PACKAGE_VERSION is defined by configure.ac as the combination
-     * "MAJOR_VERSION.MINOR_VERSION". We don't expect to change rivet/init.tcl
-     * across patchlevel releases
-     */
-
-    if (Tcl_PkgRequire(interp, "Rivet", RIVET_INIT_VERSION, 1) == NULL)
-    {
-        ap_log_error (APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
-                      MODNAME ": init.tcl must be installed correctly for Apache Rivet to function: %s (%s)",
-                      Tcl_GetStringResult(interp), RIVET_DIR );
-        exit(1);
-    }
-
-    Tcl_Release(interp);
-    interp_obj->flags |= RIVET_INTERP_INITIALIZED;
-}
-
 /* 
  * -- Rivet_RunServerInit
  *
@@ -1541,7 +1102,6 @@ Rivet_ServerInit (apr_pool_t *pPool, apr
         /* we require only mpm_request and mpm_master_interp to be defined */
 
         ap_assert(RIVET_MPM_BRIDGE_FUNCTION(mpm_request) != NULL);
-        ap_assert(RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp) != NULL);
 
         apr_thread_mutex_create(&module_globals->pool_mutex, APR_THREAD_MUTEX_UNNESTED, pPool);
 

Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet.h (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet.h Sat Dec 26 00:22:11 2015
@@ -156,14 +156,15 @@ typedef struct _rivet_thread_interp {
     unsigned int        flags;              /* signals of various interp specific conditions    */
 } rivet_thread_interp;
 
+typedef struct _thread_worker_private rivet_thread_private;
+
 typedef int  (RivetBridge_ServerInit)   (apr_pool_t*,apr_pool_t*,apr_pool_t*,server_rec*);
 typedef void (RivetBridge_ChildInit)    (apr_pool_t* pPool,server_rec* s);
 typedef int  (RivetBridge_Request)      (request_rec*,rivet_req_ctype);
-typedef apr_status_t 
-             (RivetBridge_Finalize)(void*);
-typedef rivet_thread_interp*
-             (RivetBridge_Master_Interp) (void);
+typedef apr_status_t                    (RivetBridge_Finalize)(void*);
+typedef rivet_thread_interp*            (RivetBridge_Master_Interp) (void);
 typedef int  (RivetBridge_Exit_Handler) (int);
+typedef rivet_thread_interp* (RivetBridge_Thread_Interp)(rivet_thread_private*,rivet_server_conf *);
 
 typedef struct _mpm_bridge_table {
     RivetBridge_ServerInit    *mpm_server_init;
@@ -172,6 +173,7 @@ typedef struct _mpm_bridge_table {
     RivetBridge_Finalize      *mpm_finalize;
     RivetBridge_Master_Interp *mpm_master_interp;
     RivetBridge_Exit_Handler  *mpm_exit_handler;
+    RivetBridge_Thread_Interp *mpm_thread_interp;
 } rivet_bridge_table;
 
 /* we need also a place where to store module wide globals */
@@ -196,15 +198,13 @@ typedef struct _mod_rivet_globals {
 #endif
 } mod_rivet_globals;
 
+typedef struct mpm_bridge_specific mpm_bridge_specific;
+
 typedef struct _thread_worker_private {
     apr_pool_t*         pool;               /* threads private memory pool          */
     rivet_thread_interp** interps;          /* database of virtual host interps     */
     Tcl_Channel*        channel;            /* the Tcl thread private channel       */
     int                 req_cnt;            /* requests served by thread            */
-    int                 keep_going;         /* thread loop controlling variable     */
-                                            /* the request_rec and TclWebRequest    *
-                                             * are copied here to be passed to a    *
-                                             * channel                              */
     rivet_req_ctype     ctype;              /*                                      */
     request_rec*        r;                  /* current request_rec                  */
     TclWebRequest*      req;
@@ -224,6 +224,7 @@ typedef struct _thread_worker_private {
     apr_pool_t*         rivet_panic_pool;
     server_rec*         rivet_panic_server_rec;
 
+    mpm_bridge_specific* ext;               /* bridge specific extension            */
 } rivet_thread_private;
 
 /* eventually we will transfer 'global' variables in here and 'de-globalize' them */
@@ -319,6 +320,8 @@ EXTERN Tcl_Interp* Rivet_CreateTclInterp
     (*module_globals->bridge_jump_table->fun)(__VA_ARGS__);\
 }
 
+#define RIVET_PEEK_INTERP (module_globals->bridge_jump_table->mpm_thread_interp)
+
 #define RIVET_MPM_BRIDGE rivet_bridge_table bridge_jump_table =
 
 #endif /* MOD_RIVET_H */

Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.c Sat Dec 26 00:22:11 2015
@@ -1,7 +1,6 @@
-/*
-    mod_rivet_common.c - functions likely to be shared among 
-    different versions of mod_rivet.c 
+/* -- mod_rivet_common.c - functions likely to be shared among different versions of mod_rivet.c */
 
+/*
     Licensed to the Apache Software Foundation (ASF) under one
     or more contributor license agreements.  See the NOTICE file
     distributed with this work for additional information
@@ -35,10 +34,254 @@
 #include "rivetParser.h"
 #include "rivet.h"
 #include "apache_config.h"
+#include "rivetCore.h"
 
 extern apr_threadkey_t*   rivet_thread_key;
 extern mod_rivet_globals* module_globals;
 
+/*----------------------------------------------------------------------------
+ * -- Rivet_RunningScripts
+ *
+ *
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+running_scripts* Rivet_RunningScripts (apr_pool_t* pool,running_scripts* scripts,rivet_server_conf*  rivet_conf)
+{
+    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_before_script);
+    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_after_script);
+    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_error_script);
+    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,rivet_abort_script);
+    RIVET_SCRIPT_INIT (pool,scripts,rivet_conf,after_every_script);
+
+    return scripts;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Rivet_PerInterpInit --
+ *
+ *  Do the initialization that needs to happen for every
+ *  interpreter.
+ *
+ * Results:
+ *  None.
+ *
+ * Side Effects:
+ *  None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p)
+{
+    rivet_interp_globals*   globals     = NULL;
+    Tcl_Obj*                auto_path   = NULL;
+    Tcl_Obj*                rivet_tcl   = NULL;
+    Tcl_Interp*             interp      = interp_obj->interp;
+
+    ap_assert (interp != (Tcl_Interp *)NULL);
+    Tcl_Preserve (interp);
+
+    /* Set up interpreter associated data */
+
+    globals = apr_pcalloc (p, sizeof(rivet_interp_globals));
+    Tcl_SetAssocData (interp,"rivet",NULL,globals);
+    
+    /* 
+     * abort_page status variables in globals are set here and then 
+     * reset in Rivet_SendContent just before the request processing is 
+     * completed 
+     */
+
+    /* Rivet commands namespace is created */
+
+    globals->rivet_ns = Tcl_CreateNamespace (interp,RIVET_NS,NULL,
+                                            (Tcl_NamespaceDeleteProc *)NULL);
+    //globals->req    = TclWeb_NewRequestObject (p); 
+    //globals->r      = NULL;
+    //globals->srec   = s;
+
+    /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
+
+    /* We put in front the auto_path list the path to the directory where
+     * init.tcl is located (provides package Rivet, previously RivetTcl)
+     */
+
+    auto_path = Tcl_GetVar2Ex(interp,"auto_path",NULL,TCL_GLOBAL_ONLY);
+
+    rivet_tcl = Tcl_NewStringObj(RIVET_DIR,-1);
+    Tcl_IncrRefCount(rivet_tcl);
+
+    if (Tcl_IsShared(auto_path)) {
+        auto_path = Tcl_DuplicateObj(auto_path);
+    }
+
+    if (Tcl_ListObjReplace(interp,auto_path,0,0,1,&rivet_tcl) == TCL_ERROR)
+    {
+        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s, 
+                     MODNAME ": error setting auto_path: %s",
+                     Tcl_GetStringFromObj(auto_path,NULL));
+    } else {
+        Tcl_SetVar2Ex(interp,"auto_path",NULL,auto_path,TCL_GLOBAL_ONLY);
+    }
+
+    Tcl_DecrRefCount(rivet_tcl);
+
+    /* Initialize the interpreter with Rivet's Tcl commands. */
+
+    if (private == NULL)
+    {
+        /* reduced core for the server init interpreter */
+
+        // RIVET_OBJ_CMD ("inspect",Rivet_InspectCmd,private);
+        
+    } 
+    else
+    {
+        /* full fledged rivet core */
+
+        Rivet_InitCore(interp,private);
+
+    }
+
+    /* Create a global array with information about the server. */
+    Rivet_InitServerVariables(interp, p );
+
+    /* Loading into the interpreter commands in librivet.so */
+    /* Tcl Bug #3216070 has been solved with 8.5.10 and commands shipped with
+     * Rivetlib can be mapped at this stage
+     */
+
+    if (Tcl_PkgRequire(interp, RIVETLIB_TCL_PACKAGE, RIVET_VERSION, 1) == NULL)
+    {
+        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+                     MODNAME ": Error loading rivetlib package: %s",
+                     Tcl_GetStringResult(interp) );
+        exit(1);
+    }
+
+    /*  If rivet is configured to export the ::rivet namespace commands we set the
+     *  array variable ::rivet::module_conf(export_namespace_commands) before calling init.tcl
+     *  This array will be unset after commands are exported.
+     */
+
+    Tcl_SetVar2Ex(interp,"module_conf","export_namespace_commands",Tcl_NewIntObj(RIVET_NAMESPACE_EXPORT),0);
+    Tcl_SetVar2Ex(interp,"module_conf","import_rivet_commands",Tcl_NewIntObj(RIVET_NAMESPACE_IMPORT),0);
+
+    /* Eval Rivet's init.tcl file to load in the Tcl-level commands. */
+
+    /* Watch out! Calling Tcl_PkgRequire with a version number binds this module to
+     * the Rivet package revision number in rivet/init.tcl
+     *
+     * RIVET_TCL_PACKAGE_VERSION is defined by configure.ac as the combination
+     * "MAJOR_VERSION.MINOR_VERSION". We don't expect to change rivet/init.tcl
+     * across patchlevel releases
+     */
+
+    if (Tcl_PkgRequire(interp, "Rivet", RIVET_INIT_VERSION, 1) == NULL)
+    {
+        ap_log_error (APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+                      MODNAME ": init.tcl must be installed correctly for Apache Rivet to function: %s (%s)",
+                      Tcl_GetStringResult(interp), RIVET_DIR );
+        exit(1);
+    }
+
+    Tcl_Release(interp);
+    interp_obj->flags |= RIVET_INTERP_INITIALIZED;
+}
+/*
+ * Rivet_CreateCache --
+ *
+ * Arguments:
+ *     rsc: pointer to a server_rec structure
+ *
+ * Results:
+ *     None
+ *
+ * Side Effects:
+ *
+ */
+
+void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj)
+{
+    interp_obj->objCacheList = apr_pcalloc(p, (signed)((interp_obj->cache_size)*sizeof(char *)));
+    interp_obj->objCache = apr_pcalloc(p, sizeof(Tcl_HashTable));
+    Tcl_InitHashTable(interp_obj->objCache, TCL_STRING_KEYS);
+}
+
+ /* -- Rivet_NewVHostInterp
+  *
+  * Returns a new rivet_thread_interp object with a new Tcl interpreter
+  * configuration scripts and cache. The pool passed to Rivet_NewVHostInterp 
+  *
+  *     Arguments: 
+  *       apr_pool_t* pool: a memory pool, it must be the private pool of a 
+  *       rivet_thread_private object (thread private)
+  *
+  *   Returned value:
+  *       a rivet_thread_interp* record object
+  *
+  */
+
+rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool)
+{
+    extern int              ap_max_requests_per_child;
+    rivet_thread_interp*    interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
+    rivet_server_conf*      rsc;
+
+    /* The cache size is global so we take it from here */
+    
+    rsc = RIVET_SERVER_CONF (module_globals->server->module_config);
+
+    /* This calls needs the root server_rec just for logging purposes*/
+
+    interp_obj->interp = Rivet_CreateTclInterp(module_globals->server); 
+
+    /* We now read from the pointers to the cache_size and cache_free conf parameters
+     * for compatibility with mod_rivet current version, but these values must become
+     * integers not pointers
+     */
+    
+    if (rsc->default_cache_size < 0) {
+        if (ap_max_requests_per_child != 0) {
+            interp_obj->cache_size = ap_max_requests_per_child / 5;
+        } else {
+            interp_obj->cache_size = 50;    // Arbitrary number
+        }
+    } else if (rsc->default_cache_size > 0) {
+        interp_obj->cache_size = rsc->default_cache_size;
+    }
+
+    if (interp_obj->cache_size > 0) {
+        interp_obj->cache_free = interp_obj->cache_size;
+    }
+
+    /* we now create memory from the cache pool as subpool of the thread private pool */
+ 
+    if (apr_pool_create(&interp_obj->pool, pool) != APR_SUCCESS)
+    {
+        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server, 
+                     MODNAME ": could not initialize cache private pool");
+        return NULL;
+    }
+
+    // Initialize cache structures
+
+    if (interp_obj->cache_size) {
+        Rivet_CreateCache(pool,interp_obj); 
+    }
+
+    interp_obj->flags = 0;
+
+    interp_obj->scripts         = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
+    interp_obj->per_dir_scripts = apr_hash_make(pool); 
+
+    return interp_obj;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -147,7 +390,6 @@ rivet_thread_private* Rivet_CreatePrivat
         return NULL;
     }
     private->req_cnt        = 0;
-    private->keep_going     = 1;
     private->r              = NULL;
     private->req            = TclWeb_NewRequestObject (private->pool);
     private->page_aborting  = 0;
@@ -159,14 +401,7 @@ rivet_thread_private* Rivet_CreatePrivat
     Tcl_IncrRefCount(private->request_init);
     Tcl_IncrRefCount(private->request_cleanup);
 
-
-    /* We allocate the array for the interpreters database.
-     * Data referenced in this database must be freed by the thread before exit
-     */
-
-    private->interps    = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
     apr_threadkey_private_set (private,rivet_thread_key);
-
     return private;
 }
 
@@ -484,87 +719,4 @@ Rivet_CheckType (request_rec *req)
     return ctype; 
 }
 
-/*
- * -- Rivet_ProcessorCleanup
- *
- * Thread private data cleanup. This function is called by MPM bridges to 
- * release data owned by private and pointed in the array of rivet_thread_interp
- * objects. It has to be called just before an agent, either thread or
- * process, exits.
- *
- *  Arguments:
- *
- *      data:   pointer to a rivet_thread_private data structure. 
- *
- *  Returned value:
- *
- *      none
- *
- *  Side effects:
- *
- *      resources stored in the array of rivet_thread_interp objects are released
- *      and interpreters are deleted.
- *
- */
-
-void Rivet_ProcessorCleanup (void *data)
-{
-    rivet_thread_private*   private = (rivet_thread_private *) data;
-    Tcl_HashSearch*         searchCtx; 
-    Tcl_HashEntry*          entry;
-    int                     i;
-    rivet_server_conf*      rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
-
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, 
-                 "Thread exiting after %d requests served (%d vhosts)", 
-                                        private->req_cnt,module_globals->vhosts_count);
-
-    /* We are deleting the interpreters and release the thread channel. 
-     * Rivet channel is set as stdout channel of Tcl and as such is treated
-     * by Tcl_UnregisterChannel is a special way. When its refCount reaches 1
-     * the channel is released immediately by forcing the refCount to 0
-     * (see Tcl source code: generic/TclIO.c). Unregistering for each interpreter
-     * causes the process to segfault at least for certain Tcl versions.
-     * We unset the channel as stdout to avoid this
-     */
-
-    Tcl_SetStdChannel(NULL,TCL_STDOUT);
-
-    /* there must be always a root interpreter in the slot 0 of private->interps,
-       so there is always need to run at least one cycle here */
-
-    i = 0;
-    do
-    {
-
-        /* cleaning the cache contents and deleting it */
-
-        searchCtx = apr_pcalloc(private->pool,sizeof(Tcl_HashSearch));
-        entry = Tcl_FirstHashEntry(private->interps[i]->objCache,searchCtx);    
-        while (entry)
-        {
-            Tcl_DecrRefCount(Tcl_GetHashValue(entry)); /* Let Tcl clear the mem allocated */
-            Tcl_DeleteHashEntry(entry);
-
-            entry = Tcl_NextHashEntry(searchCtx);
-        }
- 
-        if ((i > 0) && rsc->separate_channels) 
-            Rivet_ReleaseRivetChannel(private->interps[i]->interp,private->channel);
-
-        Tcl_DeleteInterp(private->interps[i]->interp);
-
-        /* if separate_virtual_interps == 0 we are running the same interpreter
-         * instance for each vhost, thus we can jump out of this loop after 
-         * the first cycle as the only real intepreter object we have is stored
-         * in private->interps[0]
-         */
-
-    } while ((++i < module_globals->vhosts_count) && rsc->separate_virtual_interps);
-
-    Tcl_DecrRefCount(private->request_init);
-    Tcl_DecrRefCount(private->request_cleanup);
-    apr_pool_destroy(private->pool);
-    
-}
 

Modified: tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h (original)
+++ tcl/rivet/trunk/src/mod_rivet/mod_rivet_common.h Sat Dec 26 00:22:11 2015
@@ -21,7 +21,10 @@
 
 #ifndef _MOD_RIVET_COMMON_
 #define _MOD_RIVET_COMMON_
-
+EXTERN running_scripts* Rivet_RunningScripts (apr_pool_t* pool,running_scripts* scripts,rivet_server_conf* rivet_conf);
+EXTERN void Rivet_PerInterpInit(rivet_thread_interp* interp_obj,rivet_thread_private* private, server_rec *s, apr_pool_t *p);
+EXTERN void Rivet_CreateCache (apr_pool_t *p, rivet_thread_interp* interp_obj);
+EXTERN rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t *pool);
 EXTERN void Rivet_ProcessorCleanup (void *data);
 EXTERN int Rivet_chdir_file (const char *file);
 EXTERN int Rivet_CheckType (request_rec* r);

Modified: tcl/rivet/trunk/src/mod_rivet/rivetCore.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivetCore.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivetCore.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivetCore.c Sat Dec 26 00:22:11 2015
@@ -60,6 +60,11 @@ extern apr_threadkey_t*  rivet_thread_ke
 
 #define POOL (private->r->pool)
 
+ /* define a convenience macro to cast the ClientData
+  * into the thread private data pointer */
+
+#define THREAD_PRIVATE_DATA(p)  p = (rivet_thread_private *)clientData;
+
 /*
  * -- Rivet_NoRequestRec
  *
@@ -122,7 +127,7 @@ TCL_CMD_HEADER( Rivet_MakeURL )
     CHECK_REQUEST_REC(private,"::rivet::makeurl")
     if (objc == 1)
     {
-        url_target_name = TclWeb_GetEnvVar (private->req,"SCRIPT_NAME");
+        url_target_name = TclWeb_GetEnvVar (private,"SCRIPT_NAME");
     }
     else
     {
@@ -135,7 +140,7 @@ TCL_CMD_HEADER( Rivet_MakeURL )
         if (url_target_name[0] != '/')
         {
             /* relative path */
-            char* script_name = TclWeb_GetEnvVar (private->req,"SCRIPT_NAME");
+            char* script_name = TclWeb_GetEnvVar (private,"SCRIPT_NAME");
             int   script_name_l = strlen(script_name);
 
             // regardless the reason for a SCRIPT_NAME being undefined we
@@ -498,7 +503,7 @@ TCL_CMD_HEADER( Rivet_LoadEnv )
         ArrayObj = Tcl_NewStringObj( ENV_ARRAY_NAME, -1 );
     }
 
-    return TclWeb_GetEnvVars(ArrayObj,private->req);
+    return TclWeb_GetEnvVars(ArrayObj,private);
 }
 
 /*
@@ -537,7 +542,7 @@ TCL_CMD_HEADER ( Rivet_LoadHeaders )
         ArrayObj = Tcl_NewStringObj( HEADERS_ARRAY_NAME, -1 );
     }
 
-    return TclWeb_GetHeaderVars(ArrayObj,private->req);
+    return TclWeb_GetHeaderVars(ArrayObj,private);
 }
 
 /* Tcl command to return a particular variable.  */
@@ -1309,7 +1314,7 @@ TCL_CMD_HEADER( Rivet_EnvCmd )
 
     key = Tcl_GetStringFromObj( objv[1], NULL );
 
-    val = TclWeb_GetEnvVar( private->req, key );
+    val = TclWeb_GetEnvVar( private, key );
 
     Tcl_SetObjResult(interp, Tcl_NewStringObj( val, -1 ) );
     return TCL_OK;

Added: tcl/rivet/trunk/src/mod_rivet/rivetCore.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivetCore.h?rev=1721698&view=auto
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivetCore.h (added)
+++ tcl/rivet/trunk/src/mod_rivet/rivetCore.h Sat Dec 26 00:22:11 2015
@@ -0,0 +1,28 @@
+/* rivetCore.h -- Core commands which are compiled into mod_rivet itself */
+
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+/* $Id: rivetCore.c 1718131 2015-12-05 22:58:33Z mxmanghi $ */
+
+#ifndef __rivetcore_h__
+#define __rivetcore_h__
+int Rivet_InitCore(Tcl_Interp *interp,rivet_thread_private* private);
+#endif
+

Modified: tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivet_lazy_mpm.c Sat Dec 26 00:22:11 2015
@@ -19,7 +19,7 @@
     under the License.
  */
 
-/* $Id: */
+/* $Id$ */
 
 #include <httpd.h>
 #include <http_request.h>
@@ -39,7 +39,6 @@ extern mod_rivet_globals*   module_globa
 extern apr_threadkey_t*     rivet_thread_key;
 extern apr_threadkey_t*     handler_thread_key;
 
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
 rivet_thread_interp*  Rivet_NewVHostInterp(apr_pool_t* pool);
 
 enum
@@ -58,7 +57,7 @@ typedef struct lazy_tcl_worker {
     apr_thread_cond_t*  condition2;
     int                 status;
     apr_thread_t*       thread_id;
-    int                 idx;
+    server_rec*         server;
     request_rec*        r;
     int                 ctype;
     int                 ap_sts;
@@ -67,7 +66,6 @@ typedef struct lazy_tcl_worker {
 
 typedef struct vhost_iface {
     apr_uint32_t*       idle_threads_cnt;       /* */
-    //apr_queue_t*        queue;                  /* available threads  */
     apr_thread_mutex_t* mutex;
     apr_array_header_t* array;                   /* available threads  */
 } vhost;
@@ -81,6 +79,15 @@ typedef struct mpm_bridge_status {
     vhost*              vhosts;
 } mpm_bridge_status;
 
+typedef struct mpm_bridge_specific {
+    rivet_thread_interp*  interp;           /* thread Tcl interpreter object        */
+    rivet_server_conf*    conf;             /* rivet_server_conf* record            */
+    int                   keep_going;       /* thread loop controlling variable     */
+                                            /* the request_rec and TclWebRequest    *
+                                             * are copied here to be passed to a    *
+                                             * channel                              */
+} mpm_bridge_specific;
+
 #define DEFAULT_HEADER_TYPE "text/html"
 #define BASIC_PAGE          "<b>Lazy Bridge</b>"
 
@@ -89,38 +96,96 @@ typedef struct mpm_bridge_status {
 static void* APR_THREAD_FUNC request_processor (apr_thread_t *thd, void *data)
 {
     lazy_tcl_worker* w = (lazy_tcl_worker*) data; 
+    rivet_thread_private*   private;
+    void*                   function;
 
+    private = Rivet_CreatePrivateData();
+    if (private == NULL) 
+    {
+        /* TODO: we have to log something here */
+        apr_thread_exit(thd,APR_SUCCESS);
+    }
+    private->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
+    Rivet_SetupTclPanicProc ();
+
+    private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+    private->ext->keep_going = 1;
+    private->ext->interp = Rivet_NewVHostInterp(private->pool);
+    private->ext->interp->channel = private->channel;
+    private->ext->conf   = RIVET_SERVER_CONF(w->server->module_config);
     w->nreqs = 0;
+    Tcl_RegisterChannel(private->ext->interp->interp,*private->channel);
+
+    Rivet_PerInterpInit(private->ext->interp,private,module_globals->server,private->pool);
+        
+    function = private->ext->conf->rivet_child_init_script;
+    if (function)
+    {
+        char*       errmsg = "rivet_lazy_mpm.so: Error in thread initialization init script: %s";
+        Tcl_Obj*    tcl_child_init = Tcl_NewStringObj(function,-1);
+        Tcl_Interp* interp = private->ext->interp->interp;
+
+        Tcl_IncrRefCount(tcl_child_init);
+
+        if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK) 
+        {
+            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, w->server,
+                         errmsg, function);
+            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, w->server, 
+                         "errorCode: %s", Tcl_GetVar(interp, "errorCode", 0));
+            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, w->server, 
+                         "errorInfo: %s", Tcl_GetVar(interp, "errorInfo", 0));
+            apr_thread_mutex_lock(w->mutex2);
+            w->status = done;
+            w->ap_sts = HTTP_INTERNAL_SERVER_ERROR;
+            apr_thread_cond_signal(w->condition2);
+            apr_thread_mutex_unlock(w->mutex2);
+
+            /* This is broken: there must be a way to tell the array of 
+             * available threads this thread is about to exit, otherwise
+             * it would be impossible to implement the exit command in the
+             * way we did for prefork and worker bridges */
+
+            apr_thread_exit(thd,APR_SUCCESS);
+            return NULL;
+        }
+
+        Tcl_DecrRefCount(tcl_child_init);
+    }
+
     do 
     {
-        char* page;
+        //char* page;
+        int   http_code;
+        int   idx = private->ext->conf->idx;
 
         apr_thread_mutex_lock(w->mutex1);
-        //apr_queue_push(module_globals->mpm->vhosts[w->idx].queue,w);
-        apr_atomic_inc32(module_globals->mpm->vhosts[w->idx].idle_threads_cnt);
+        apr_atomic_inc32(module_globals->mpm->vhosts[idx].idle_threads_cnt);
         while (w->status != init) {
             apr_thread_cond_wait(w->condition1,w->mutex1);
         } 
 
         w->status = processing;
+        w->nreqs++;
         apr_thread_mutex_unlock(w->mutex1);
-        apr_atomic_dec32(module_globals->mpm->vhosts[w->idx].idle_threads_cnt);
+        apr_atomic_dec32(module_globals->mpm->vhosts[idx].idle_threads_cnt);
 
         /* Content generation */
 
+        http_code = Rivet_SendContent(private,w->r);
+
+        /*
         ap_set_content_type(w->r,apr_pstrdup(w->r->pool,DEFAULT_HEADER_TYPE));
         ap_send_http_header(w->r);
-        //ap_rwrite(apr_pstrdup(w->r->pool,BASIC_PAGE),strlen(BASIC_PAGE),w->r);
-
-        page = apr_psprintf(w->r->pool,"%s: vh %d, idle threads: %d, nreqs: %d",BASIC_PAGE,w->idx,
-                            (int) apr_atomic_read32(module_globals->mpm->vhosts[w->idx].idle_threads_cnt),++(w->nreqs));
-
+        page = apr_psprintf(w->r->pool,"%s: vh %d, idle threads: %d, nreqs: %d",BASIC_PAGE,idx,
+                            (int) apr_atomic_read32(module_globals->mpm->vhosts[idx].idle_threads_cnt),w->nreqs);
         ap_rwrite(page,strlen(page),w->r);
         ap_rflush(w->r);
+        */
 
         apr_thread_mutex_lock(w->mutex2);
         w->status = done;
-        w->ap_sts = OK;
+        w->ap_sts = http_code;
         apr_thread_cond_signal(w->condition2);
         apr_thread_mutex_unlock(w->mutex2);
 
@@ -132,23 +197,23 @@ static void* APR_THREAD_FUNC request_pro
  
         // rescheduling itself in the array of idle threads
        
-        apr_thread_mutex_lock(module_globals->mpm->vhosts[w->idx].mutex);
-        *(lazy_tcl_worker **) apr_array_push(module_globals->mpm->vhosts[w->idx].array) = w;
-        apr_thread_mutex_unlock(module_globals->mpm->vhosts[w->idx].mutex);
+        apr_thread_mutex_lock(module_globals->mpm->vhosts[idx].mutex);
+        *(lazy_tcl_worker **) apr_array_push(module_globals->mpm->vhosts[idx].array) = w;
+        apr_thread_mutex_unlock(module_globals->mpm->vhosts[idx].mutex);
 
-    } while (1);
+    } while (private->ext->keep_going);
 
     return NULL;
 }
 
-static lazy_tcl_worker* create_worker (apr_pool_t* pool,int idx)
+static lazy_tcl_worker* create_worker (apr_pool_t* pool,server_rec* server)
 {
     lazy_tcl_worker*    w;
 
     w = apr_pcalloc(pool,sizeof(lazy_tcl_worker));
 
     w->status = idle;
-    w->idx = idx;
+    w->server = server;
     ap_assert(apr_thread_mutex_create(&w->mutex1,APR_THREAD_MUTEX_UNNESTED,pool) == APR_SUCCESS);
     ap_assert(apr_thread_cond_create(&w->condition1, pool) == APR_SUCCESS); 
     ap_assert(apr_thread_mutex_create(&w->mutex2,APR_THREAD_MUTEX_UNNESTED,pool) == APR_SUCCESS);
@@ -161,28 +226,27 @@ static lazy_tcl_worker* create_worker (a
 void Lazy_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
 {
     apr_status_t    rv;
-    int             vh;
+    server_rec*     s;
+    server_rec*     root_server = module_globals->server;
 
     module_globals->mpm = apr_pcalloc(pool,sizeof(mpm_bridge_status));
 
-    //module_globals->mpm->vhosts = (vhost *) apr_pcalloc(pool,sizeof(vhost) * module_globals->vhosts_count);
-
     rv = apr_thread_mutex_create(&module_globals->mpm->mutex,APR_THREAD_MUTEX_UNNESTED,pool);
     ap_assert(rv == APR_SUCCESS);
     rv = apr_thread_cond_create(&module_globals->mpm->condition, pool); 
     ap_assert(rv == APR_SUCCESS);
 
-    /*
-    apr_atomic_set32(module_globals->mpm->first_available,0);
-    */
-
     module_globals->mpm->vhosts = (vhost *) apr_pcalloc(pool,module_globals->vhosts_count * sizeof(vhost));
     ap_assert(module_globals->mpm->vhosts != NULL);
 
-    for (vh = 0; vh < module_globals->vhosts_count; vh++)
+    //for (vh = 0; vh < module_globals->vhosts_count; vh++)
+    for (s = root_server; s != NULL; s = s->next)
     {
+        int                 vh;
         apr_array_header_t* array;
+        rivet_server_conf*  rsc = RIVET_SERVER_CONF(s->module_config);
 
+        vh = rsc->idx;
         ap_assert(apr_thread_mutex_create(&module_globals->mpm->vhosts[vh].mutex,APR_THREAD_MUTEX_UNNESTED,pool) == APR_SUCCESS);
         array = apr_array_make(pool,0,sizeof(void*));
         ap_assert(array != NULL);
@@ -191,16 +255,11 @@ void Lazy_MPM_ChildInit (apr_pool_t* poo
         //ap_assert(apr_queue_create(&module_globals->mpm->vhosts[vh].queue,MOD_RIVET_QUEUE_SIZE,pool) == APR_SUCCESS);
         module_globals->mpm->vhosts[vh].idle_threads_cnt = (apr_uint32_t *) apr_pcalloc(pool,sizeof(apr_uint32_t));
         apr_atomic_set32(module_globals->mpm->vhosts[vh].idle_threads_cnt,0);
-        
-        //create_worker(pool,vh);
-        //create_worker(pool,vh);
     }
 }
 
 int Lazy_MPM_Request (request_rec* r,rivet_req_ctype ctype)
 {
-    //void*               v;
-    //apr_status_t        rv;
     lazy_tcl_worker*    w;
     int                 ap_sts;
     rivet_server_conf*  conf = RIVET_SERVER_CONF(r->server->module_config);
@@ -219,7 +278,7 @@ int Lazy_MPM_Request (request_rec* r,riv
     apr_thread_mutex_lock(mutex);
     if (apr_is_empty_array(array))
     {
-        w = create_worker(module_globals->pool,conf->idx);
+        w = create_worker(module_globals->pool,r->server);
     }
     else
     {
@@ -231,7 +290,6 @@ int Lazy_MPM_Request (request_rec* r,riv
     w->r        = r;
     w->ctype    = ctype;
     w->status   = init;
-    w->idx      = conf->idx;
     apr_thread_cond_signal(w->condition1);
     apr_thread_mutex_unlock(w->mutex1);
 
@@ -251,9 +309,10 @@ int Lazy_MPM_Request (request_rec* r,riv
     return ap_sts;
 }
 
-rivet_thread_interp* Lazy_MPM_MasterInterp(void)
+rivet_thread_interp* Lazy_MPM_Interp(rivet_thread_private *private,
+                                     rivet_server_conf* conf)
 {
-    return NULL;
+    return private->ext->interp;   
 }
 
 RIVET_MPM_BRIDGE {
@@ -261,6 +320,7 @@ RIVET_MPM_BRIDGE {
     Lazy_MPM_ChildInit,
     Lazy_MPM_Request,
     NULL,
-    Lazy_MPM_MasterInterp,
-    NULL
+    NULL,
+    NULL,
+    Lazy_MPM_Interp
 };

Modified: tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivet_prefork_mpm.c Sat Dec 26 00:22:11 2015
@@ -29,14 +29,17 @@
 #include "rivetChannel.h"
 #include "apache_config.h"
 #include "rivet.h"
+#include "rivetCore.h"
 
 extern mod_rivet_globals* module_globals;
 extern apr_threadkey_t*   rivet_thread_key;
 
-int Rivet_InitCore (Tcl_Interp *interp,rivet_thread_private* p); 
+rivet_thread_private*   Rivet_VirtualHostsInterps (rivet_thread_private* private);
+rivet_thread_interp*    Rivet_NewVHostInterp(apr_pool_t* pool);
 
-rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
-rivet_thread_interp* Rivet_NewVHostInterp(apr_pool_t* pool);
+/* typedef struct mpm_bridge_specific {
+    rivet_thread_interp** interps;          
+} mpm_bridge_specific; */
 
 /* -- Prefork_MPM_Finalize */
 
@@ -69,7 +72,9 @@ void Prefork_MPM_ChildInit (apr_pool_t*
      */
 
     private = Rivet_CreatePrivateData();
-    
+    //private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+    private->interps = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
+   
     Rivet_SetupTclPanicProc ();
     ap_assert(private != NULL);
 
@@ -161,12 +166,18 @@ int Prefork_MPM_ExitHandler(int code)
     return TCL_OK;
 }
 
+rivet_thread_interp* Prefork_MPM_Interp(rivet_thread_private *private,rivet_server_conf* conf)
+{
+    return private->interps[conf->idx];   
+}
+
 RIVET_MPM_BRIDGE {
     NULL,
     Prefork_MPM_ChildInit,
     Prefork_MPM_Request,
     Prefork_MPM_Finalize,
     Prefork_MPM_MasterInterp,
-    Prefork_MPM_ExitHandler
+    Prefork_MPM_ExitHandler,
+    Prefork_MPM_Interp
 };
 

Modified: tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c (original)
+++ tcl/rivet/trunk/src/mod_rivet/rivet_worker_mpm.c Sat Dec 26 00:22:11 2015
@@ -76,6 +76,13 @@ typedef struct mpm_bridge_status {
 #endif
 } mpm_bridge_status;
 
+/* This object is thread specific */
+
+typedef struct mpm_bridge_specific {
+    int                   keep_going;       /* thread loop controlling variable     */
+} mpm_bridge_specific;
+
+
 /* data private to the Apache callback handling the request */
 
 typedef struct _handler_private 
@@ -177,10 +184,15 @@ static void* APR_THREAD_FUNC request_pro
     apr_thread_mutex_lock(module_globals->mpm->job_mutex);
 
     private = Rivet_CreatePrivateData();
+    private->interps = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
+    private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
+    private->ext->keep_going = 1;
+
     if (private == NULL) 
     {
         /* TODO: we have to log something here */
         apr_thread_exit(thd,APR_SUCCESS);
+        return NULL;
     }
     private->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
     Rivet_SetupTclPanicProc ();
@@ -239,7 +251,7 @@ static void* APR_THREAD_FUNC request_pro
         request_obj = (handler_private *) v;
         if (request_obj->job_type == orderly_exit)
         {
-            private->keep_going = 0;
+            private->ext->keep_going = 0;
             continue;
         }
 
@@ -265,7 +277,7 @@ static void* APR_THREAD_FUNC request_pro
         private->req_cnt++;
         apr_atomic_dec32(module_globals->mpm->running_threads_count);
 
-    } while (private->keep_going > 0);
+    } while (private->ext->keep_going > 0);
             
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, "processor thread orderly exit");
 
@@ -760,7 +772,7 @@ int Worker_MPM_ExitHandler(int code)
 
     /* This will force the current thread to exit */
 
-    private->keep_going = 0;
+    private->ext->keep_going = 0;
 
     module_globals->mpm->exit_command = 1;
     module_globals->mpm->exit_command_status = code;
@@ -772,11 +784,18 @@ int Worker_MPM_ExitHandler(int code)
     return TCL_OK;
 }
 
+rivet_thread_interp* Worker_MPM_Interp(rivet_thread_private *private,
+                                       rivet_server_conf *conf)
+{
+    return private->interps[conf->idx];   
+}
+
 RIVET_MPM_BRIDGE {
     NULL,
     Worker_MPM_ChildInit,
     Worker_MPM_Request,
     Worker_MPM_Finalize,
     Worker_MPM_MasterInterp,
-    Worker_MPM_ExitHandler
+    Worker_MPM_ExitHandler,
+    Worker_MPM_Interp
 };

Added: tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c?rev=1721698&view=auto
==============================================================================
--- tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c (added)
+++ tcl/rivet/trunk/src/mod_rivet/worker_prefork_common.c Sat Dec 26 00:22:11 2015
@@ -0,0 +1,314 @@
+/* worker_prefork_common.c: function common to both the prefork and worker bridges */
+
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+ */
+
+/* $Id: rivet_prefork_mpm.c 1719851 2015-12-14 00:50:43Z mxmanghi $ */
+
+#include <httpd.h>
+#include <apr_strings.h>
+#include "mod_rivet.h"
+#include "mod_rivet_common.h"
+
+extern mod_rivet_globals* module_globals;
+extern apr_threadkey_t*   rivet_thread_key;
+
+/*
+ * Rivet_DuplicateVhostInterp
+ *
+ *
+ */
+
+static rivet_thread_interp* 
+Rivet_DuplicateVHostInterp(apr_pool_t* pool, rivet_thread_interp* source_obj)
+{
+    rivet_thread_interp* interp_obj = apr_pcalloc(pool,sizeof(rivet_thread_interp));
+
+    interp_obj->interp      = source_obj->interp;
+    interp_obj->channel     = source_obj->channel;
+    interp_obj->cache_free  = source_obj->cache_free;
+    interp_obj->cache_size  = source_obj->cache_size;
+
+    /* TODO: decouple cache by creating a new cache object */
+
+    if (interp_obj->cache_size) {
+        Rivet_CreateCache(pool,interp_obj); 
+    }
+
+    interp_obj->pool            = source_obj->pool;
+    interp_obj->scripts         = (running_scripts *) apr_pcalloc(pool,sizeof(running_scripts));
+    interp_obj->per_dir_scripts = apr_hash_make(pool); 
+    interp_obj->flags           = source_obj->flags;
+    return interp_obj;
+}
+
+/* -- Rivet_VirtualHostsInterps 
+ *
+ * The server_rec chain is walked through and server configurations is read to
+ * set up the thread private configuration and interpreters database
+ *
+ *  Arguments:
+ *
+ *      rivet_thread_private* private;
+ *
+ *  Returned value:
+ *
+ *     a new rivet_thread_private object
+ * 
+ *  Side effects:
+ *
+ *     GlobalInitScript and ChildInitScript are run at this stage
+ *     
+ */
+
+rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private)
+{
+    server_rec*         s;
+    server_rec*         root_server = module_globals->server;
+    rivet_server_conf*  root_server_conf;
+    rivet_server_conf*  myrsc; 
+    rivet_thread_interp* root_interp;
+    void*               parentfunction;     /* this is topmost initialization script */
+    void*               function;
+
+    root_server_conf = RIVET_SERVER_CONF (root_server->module_config);
+    
+    ap_assert(RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp) != NULL);
+    root_interp = (*RIVET_MPM_BRIDGE_FUNCTION(mpm_master_interp))();
+
+    /* we must assume the module was able to create the root interprter otherwise
+     * it's just a null module. I try to have also this case to develop experimental
+     * bridges without the Tcl stuff 
+     */ 
+
+    //if (root_interp == NULL) return private;
+
+    ap_assert (root_interp != NULL);
+
+    /* Using the root interpreter we evaluate the global initialization script, if any */
+
+    if (root_server_conf->rivet_global_init_script != NULL) 
+    {
+        Tcl_Obj* global_tcl_script;
+
+        global_tcl_script = Tcl_NewStringObj(root_server_conf->rivet_global_init_script,-1);
+        Tcl_IncrRefCount(global_tcl_script);
+        if (Tcl_EvalObjEx(root_interp->interp, global_tcl_script, 0) != TCL_OK)
+        {
+            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, module_globals->server, 
+                         MODNAME ": Error running GlobalInitScript '%s': %s",
+                         root_server_conf->rivet_global_init_script,
+                         Tcl_GetVar(root_interp->interp, "errorInfo", 0));
+        } else {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, 
+                         MODNAME ": GlobalInitScript '%s' successful",
+                         root_server_conf->rivet_global_init_script);
+        }
+        Tcl_DecrRefCount(global_tcl_script);
+    }
+
+    /* then we proceed assigning/creating the interpreters for the
+     * virtual hosts known to the server
+     */
+
+    parentfunction = root_server_conf->rivet_child_init_script;
+
+    for (s = root_server; s != NULL; s = s->next)
+    {
+        rivet_thread_interp*   rivet_interp;
+
+        myrsc = RIVET_SERVER_CONF(s->module_config);
+
+        /* by default we assign the root_interpreter as
+         * interpreter of the virtual host. In case of separate
+         * virtual interpreters we create new ones for each
+         * virtual host 
+         */
+
+        rivet_interp = root_interp;
+
+        if (s == root_server)
+        {
+            Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
+        }
+        else 
+        {
+            if (root_server_conf->separate_virtual_interps)
+            {
+                rivet_interp = Rivet_NewVHostInterp(private->pool);
+                if (myrsc->separate_channels)
+                {
+                    rivet_interp->channel = Rivet_CreateRivetChannel(private->pool,rivet_thread_key);
+                    Tcl_RegisterChannel(rivet_interp->interp,*rivet_interp->channel);
+                }
+                else
+                {
+                    rivet_interp->channel = private->channel;
+                }
+            }
+            else
+            {
+                rivet_interp = Rivet_DuplicateVHostInterp(private->pool,root_interp);           
+            }
+        }
+
+        /* interpreter base running scripts definition and initialization */
+
+        rivet_interp->scripts = Rivet_RunningScripts (private->pool,rivet_interp->scripts,myrsc);
+
+        private->interps[myrsc->idx] = rivet_interp;
+
+        /* Basic Rivet packages and libraries are loaded here */
+
+        if ((rivet_interp->flags & RIVET_INTERP_INITIALIZED) == 0)
+        {
+            Rivet_PerInterpInit(rivet_interp, private, root_server, private->pool);
+        }
+
+        /*  TODO: check if it's absolutely necessary to lock the pool_mutex in order
+         *  to allocate from the module global pool
+         */
+
+        /*  this stuff must be allocated from the module global pool which
+         *  has the child process' same lifespan
+         */
+
+        apr_thread_mutex_lock(module_globals->pool_mutex);
+        myrsc->server_name = (char*) apr_pstrdup (private->pool, s->server_hostname);
+        apr_thread_mutex_unlock(module_globals->pool_mutex);
+
+        /* when configured a child init script gets evaluated */
+
+        function = myrsc->rivet_child_init_script;
+        if (function && 
+            (s == root_server || root_server_conf->separate_virtual_interps || function != parentfunction))
+        {
+            char*       errmsg = MODNAME ": Error in Child init script: %s";
+            Tcl_Interp* interp = rivet_interp->interp;
+            Tcl_Obj*    tcl_child_init = Tcl_NewStringObj(function,-1);
+
+            Tcl_IncrRefCount(tcl_child_init);
+            Tcl_Preserve (interp);
+
+            /* There is a lot of passing around of pointers among various record 
+             * objects. We should understand if this is all that necessary.
+             * Here we assign the server_rec pointer to the interpreter which
+             * is wrong, because without separate interpreters it doens't make
+             * any sense. TODO
+             */
+
+            if (Tcl_EvalObjEx(interp,tcl_child_init, 0) != TCL_OK) {
+                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server,
+                             errmsg, function);
+                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server, 
+                             "errorCode: %s", Tcl_GetVar(interp, "errorCode", 0));
+                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, root_server, 
+                             "errorInfo: %s", Tcl_GetVar(interp, "errorInfo", 0));
+            }
+            Tcl_Release (interp);
+            Tcl_DecrRefCount(tcl_child_init);
+        }
+    }
+    return private;
+}
+
+
+/*
+ * -- Rivet_ProcessorCleanup
+ *
+ * Thread private data cleanup. This function is called by MPM bridges to 
+ * release data owned by private and pointed in the array of rivet_thread_interp
+ * objects. It has to be called just before an agent, either thread or
+ * process, exits. We aren't calling this function anymore as we rely entirely
+ * on the child process termination
+ *
+ *  Arguments:
+ *
+ *      data:   pointer to a rivet_thread_private data structure. 
+ *
+ *  Returned value:
+ *
+ *      none
+ *
+ *  Side effects:
+ *
+ *      resources stored in the array of rivet_thread_interp objects are released
+ *      and interpreters are deleted.
+ *
+ */
+
+void Rivet_ProcessorCleanup (void *data)
+{
+    rivet_thread_private*   private = (rivet_thread_private *) data;
+    Tcl_HashSearch*         searchCtx; 
+    Tcl_HashEntry*          entry;
+    int                     i;
+    rivet_server_conf*      rsc = RIVET_SERVER_CONF(module_globals->server->module_config);
+
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, module_globals->server, 
+                 "Thread exiting after %d requests served (%d vhosts)", 
+                                        private->req_cnt,module_globals->vhosts_count);
+
+    /* We are deleting the interpreters and release the thread channel. 
+     * Rivet channel is set as stdout channel of Tcl and as such is treated
+     * by Tcl_UnregisterChannel is a special way. When its refCount reaches 1
+     * the channel is released immediately by forcing the refCount to 0
+     * (see Tcl source code: generic/TclIO.c). Unregistering for each interpreter
+     * causes the process to segfault at least for certain Tcl versions.
+     * We unset the channel as stdout to avoid this
+     */
+
+    Tcl_SetStdChannel(NULL,TCL_STDOUT);
+
+    /* there must be always a root interpreter in the slot 0 of private->interps,
+       so there is always need to run at least one cycle here */
+
+    i = 0;
+    do
+    {
+
+        /* cleaning the cache contents and deleting it */
+
+        searchCtx = apr_pcalloc(private->pool,sizeof(Tcl_HashSearch));
+        entry = Tcl_FirstHashEntry(private->interps[i]->objCache,searchCtx);    
+        while (entry)
+        {
+            Tcl_DecrRefCount(Tcl_GetHashValue(entry)); /* Let Tcl clear the mem allocated */
+            Tcl_DeleteHashEntry(entry);
+
+            entry = Tcl_NextHashEntry(searchCtx);
+        }
+ 
+        if ((i > 0) && rsc->separate_channels) 
+            Rivet_ReleaseRivetChannel(private->interps[i]->interp,private->channel);
+
+        Tcl_DeleteInterp(private->interps[i]->interp);
+
+        /* if separate_virtual_interps == 0 we are running the same interpreter
+         * instance for each vhost, thus we can jump out of this loop after 
+         * the first cycle as the only real intepreter object we have is stored
+         * in private->ext->interps[0]
+         */
+
+    } while ((++i < module_globals->vhosts_count) && rsc->separate_virtual_interps);
+
+    Tcl_DecrRefCount(private->request_init);
+    Tcl_DecrRefCount(private->request_cleanup);
+    apr_pool_destroy(private->pool);
+}

Modified: tcl/rivet/trunk/src/rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/rivet.h?rev=1721698&r1=1721697&r2=1721698&view=diff
==============================================================================
--- tcl/rivet/trunk/src/rivet.h (original)
+++ tcl/rivet/trunk/src/rivet.h Sat Dec 26 00:22:11 2015
@@ -59,11 +59,6 @@ static int cmd(\
     int objc,\
     Tcl_Obj *CONST objv[])
 
- /* we also define a convenience macro to cast the ClientData
-  * into the thread private data pointer */
-
-#define THREAD_PRIVATE_DATA(p)  p = (rivet_thread_private *)clientData;
-
 #define TCL_OBJ_CMD( name, func ) \
 Tcl_CreateObjCommand( interp,           /* Tcl interpreter */\
 		      name,                     /* Function name in Tcl */\



---------------------------------------------------------------------
To unsubscribe, e-mail: site-cvs-unsubscribe@tcl.apache.org
For additional commands, e-mail: site-cvs-help@tcl.apache.org