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 2014/08/19 18:09:16 UTC

svn commit: r1618891 - in /tcl/rivet/trunk: ChangeLog configure.ac src/experimental/Makefile.am src/experimental/mod_rivet.c src/experimental/mod_rivet.h src/experimental/rivet_aprthread_mpm.c src/experimental/rivet_worker_mpm.c

Author: mxmanghi
Date: Tue Aug 19 16:09:15 2014
New Revision: 1618891

URL: http://svn.apache.org/r1618891
Log:
    * src/experimental/mod_rivet.c: mutex serializing request processing now controlled by 
    RIVET_SERIALIZE_HTTP_REQUEST. 
    * src/experimental/mod_rivet.h: mutex req_mutex conditional to definition of RIVET_SERIALIZE_HTTP_REQUESTS.
    Also defined macro HTTP_REQUESTS_PROC macro to protect execution of code by module_globals->req_mutex
    * src/experimental/rivet_aprthread_mpm.c: new simplified bridge rivet_aprthread_mpm.c which creates
    Tcl interpreters within thread private data.
    * configure.ac: introducing HTTP_REQUESTS_MUTEX for handling of request serialization


Added:
    tcl/rivet/trunk/src/experimental/rivet_aprthread_mpm.c   (with props)
Modified:
    tcl/rivet/trunk/ChangeLog
    tcl/rivet/trunk/configure.ac
    tcl/rivet/trunk/src/experimental/Makefile.am
    tcl/rivet/trunk/src/experimental/mod_rivet.c
    tcl/rivet/trunk/src/experimental/mod_rivet.h
    tcl/rivet/trunk/src/experimental/rivet_worker_mpm.c

Modified: tcl/rivet/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/ChangeLog?rev=1618891&r1=1618890&r2=1618891&view=diff
==============================================================================
--- tcl/rivet/trunk/ChangeLog (original)
+++ tcl/rivet/trunk/ChangeLog Tue Aug 19 16:09:15 2014
@@ -1,3 +1,12 @@
+2014-08-19 Massimo Manghi <mx...@apache.org>
+    * src/experimental/mod_rivet.c: mutex serializing request processing now controlled by 
+    RIVET_SERIALIZE_HTTP_REQUEST. 
+    * src/experimental/mod_rivet.h: mutex req_mutex conditional to definition of RIVET_SERIALIZE_HTTP_REQUESTS.
+    Also defined macro HTTP_REQUESTS_PROC macro to protect execution of code by module_globals->req_mutex
+    * src/experimental/rivet_aprthread_mpm.c: new simplified bridge rivet_aprthread_mpm.c which creates
+    Tcl interpreters within thread private data.
+    * configure.ac: introducing HTTP_REQUESTS_MUTEX for handling of request serialization
+
 2014-08-18 Massimo Manghi <mx...@apache.org>
     * src/apache-2/mod_rivet.c: fixed old symbols now renamed as 'module_globals'
 

Modified: tcl/rivet/trunk/configure.ac
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/configure.ac?rev=1618891&r1=1618890&r2=1618891&view=diff
==============================================================================
--- tcl/rivet/trunk/configure.ac (original)
+++ tcl/rivet/trunk/configure.ac Tue Aug 19 16:09:15 2014
@@ -629,7 +629,7 @@ AC_DEFUN([HONOR_HEAD_REQUESTS],[
     fi
 ])
 
-AC_DEFUN([SINGLE_TCL_THREAD],[
+AC_DEFUN([SINGLE_WORKER_TCL_THREAD],[
     AC_ARG_ENABLE(
     single_thread,
     [  --enable-single-thread Forces single Tcl thread in worker bridge ],
@@ -640,13 +640,35 @@ AC_DEFUN([SINGLE_TCL_THREAD],[
     AC_MSG_CHECKING(whether MPM bridge has to run a single thread)
     if test "$single_thread" = "yes"; then
         AC_MSG_RESULT([yes])
-        AC_DEFINE(MPM_SINGLE_THREAD,1,[yes, MPM worker single thread])
+        AC_DEFINE(MPM_SINGLE_TCL_THREAD,1,[yes, MPM worker single thread])
     else
         AC_MSG_RESULT([no, maximal number of Tcl threads])
-        #AC_DEFINE(HEAD_REQUESTS,0,[Honor HEAD requests])
     fi
 ])
 
+# -- SERIALIZE_HTTP_REQUEST
+#
+# this macro is introduced to make debugging easier when
+# we want threads to serialize accessing the request handling central
+# method Rivet_SendContent. The macro defines the symbol SERIALIZE_HTTP_REQUESTS
+# and cooperates with macro SERIALIZED_REQUESTS
+
+AC_DEFUN([HTTP_REQUESTS_MUTEX],[
+    AC_ARG_ENABLE(
+        requests_serialization,
+        [  --enable-serialize-requests Forces HTTP requests serialization ],
+        [ requests_serialization=$enable_requests_serialization ],
+        [ requests_serialization="no" ]
+    )
+
+    AC_MSG_CHECKING([whether we want to serialize HTTP requests among threads])
+    if test "$requests_serialization" = "yes"; then
+        AC_MSG_RESULT([yes])
+        AC_DEFINE(SERIALIZE_HTTP_REQUESTS,1,[requests will be serialized])
+    else
+        AC_MSG_RESULT([no, HTTP requests will not be serialized])
+    fi
+])
 
 # RIVET_COMMANDS_EXPORT (--enable-rivet-commands-export).
 # Enable export of commands in Rivet's namespace. Definining this symbols
@@ -781,7 +803,8 @@ IMPORT_RIVET_COMMANDS
 APACHE_REQUEST
 RIVET_CORE_CMDS
 RIVET_CHANNEL
-SINGLE_TCL_THREAD
+SINGLE_WORKER_TCL_THREAD
+HTTP_REQUESTS_MUTEX
 
 # Let's separate the point version from the major and minor version
 # to build a Rivet version to be substituted as basic version for 

Modified: tcl/rivet/trunk/src/experimental/Makefile.am
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/Makefile.am?rev=1618891&r1=1618890&r2=1618891&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/Makefile.am (original)
+++ tcl/rivet/trunk/src/experimental/Makefile.am Tue Aug 19 16:09:15 2014
@@ -23,7 +23,7 @@ mod_rivet_la_LIBADD = @TCL_LIBS@ @APXS_L
 mod_rivet_la_CPPFLAGS = -I../@rivet_core@ -I../@rivet_channel@ -I@RIVET_BASE_INCLUDE@/common -I@RIVET_BASE_INCLUDE@/parser -I../@apache_request@ @apache_include@ -I@RIVET_BASE_INCLUDE@ @TCL_INCLUDES@ @APXS_CPPFLAGS@ @APXS_INCLUDES@ @APR_CPPFLAGS@ @APR_INCLUDES@ -DSTART_TAG='"<?"' -DEND_TAG='"?>"'
 
 lib_libexecdir = @RIVET_TCL_TARGET@/mpm
-lib_libexec_LTLIBRARIES = rivet_worker_mpm.la rivet_prefork_mpm.la
+lib_libexec_LTLIBRARIES = rivet_worker_mpm.la rivet_prefork_mpm.la rivet_aprthread_mpm.la
 
 rivet_worker_mpm_la_SOURCES = rivet_worker_mpm.c
 rivet_worker_mpm_la_LDFLAGS = @TCL_STUB_LIB_SPEC@ @APXS_LDFLAGS@ -module -avoid-version
@@ -35,4 +35,8 @@ rivet_prefork_mpm_la_LDFLAGS = @TCL_STUB
 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@ -I../@apache_request@ -I@RIVET_BASE_INCLUDE@/common -I@RIVET_BASE_INCLUDE@
 
+rivet_aprthread_mpm_la_SOURCES = rivet_aprthread_mpm.c
+rivet_aprthread_mpm_la_LDFLAGS = @TCL_STUB_LIB_SPEC@ @APXS_LDFLAGS@ -module -avoid-version
+rivet_aprthread_mpm_la_LIBADD  = @APXS_LIBS@
+rivet_aprthread_mpm_la_CPPFLAGS = @apache_include@ -I@rivet_core@ @TCL_INCLUDES@ @APXS_CPPFLAGS@ @APXS_INCLUDES@ @APR_CPPFLAGS@ @APR_INCLUDES@ -I../@apache_request@ -I@RIVET_BASE_INCLUDE@/common -I@RIVET_BASE_INCLUDE@
 

Modified: tcl/rivet/trunk/src/experimental/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet.c?rev=1618891&r1=1618890&r2=1618891&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet.c (original)
+++ tcl/rivet/trunk/src/experimental/mod_rivet.c Tue Aug 19 16:09:15 2014
@@ -200,7 +200,7 @@ rivet_thread_private* Rivet_VirtualHosts
         private->interps[myrsc->idx] = rivet_interp;
 
         /* Basic Rivet packages and libraries are loaded here. Also the interpreter globals
-         * are setup here. We have to explore if could be sensed to moved them to the
+         * are setup here. We have to explore if it could be sensible to move them to the
          * thread private data.
          */
 
@@ -221,7 +221,7 @@ rivet_thread_private* Rivet_VirtualHosts
         myrsc->server_name = (char*)apr_pstrdup(module_globals->pool, s->server_hostname);
         apr_thread_mutex_unlock(module_globals->pool_mutex);
 
-        /* if configured child init script gets evaluated */
+        /* when configured a child init script gets evaluated */
 
         function = myrsc->rivet_child_init_script;
         if (function && 
@@ -358,7 +358,6 @@ Rivet_SendContent(rivet_thread_private *
     }
 
     //Tcl_MutexLock(&sendMutex);
-    apr_thread_mutex_lock(module_globals->req_mutex);
 
     /* Set the global request req to know what we are dealing with in
      * case we have to call the PanicProc. */
@@ -552,7 +551,6 @@ sendcleanup:
     /* We reset this pointer to signal we have terminated the request processing */
 
     globals->r = NULL;
-    apr_thread_mutex_unlock(module_globals->req_mutex);
 
     //Tcl_MutexUnlock(&sendMutex);
     return retval;
@@ -1265,7 +1263,9 @@ static void Rivet_ChildInit (apr_pool_t 
     rivet_server_conf*  root_server_conf;
     server_rec*         s;
 
+#ifdef RIVET_SERIALIZE_HTTP_REQUESTS
     apr_thread_mutex_create(&module_globals->req_mutex, APR_THREAD_MUTEX_UNNESTED, pChild);
+#endif
 
 /* This code is run once per child process. In a threaded Tcl builds the forking 
  * of a child process most likely has not preserved the thread where the Tcl 
@@ -1308,7 +1308,7 @@ static void Rivet_ChildInit (apr_pool_t 
     }
     module_globals->vhosts_count = idx;
 
-    apr_threadkey_private_create (&rivet_thread_key, NULL, pChild);
+    apr_threadkey_private_create (&rivet_thread_key, Rivet_ProcessorCleanup, pChild);
 
     /* Calling the brigde child process initialization */
 

Modified: tcl/rivet/trunk/src/experimental/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet.h?rev=1618891&r1=1618890&r2=1618891&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet.h (original)
+++ tcl/rivet/trunk/src/experimental/mod_rivet.h Tue Aug 19 16:09:15 2014
@@ -191,8 +191,9 @@ typedef struct _mod_rivet_globals {
     int                 num_load_samples;
     double              average_working_threads; 
     */
-
+#ifdef RIVET_SERIALIZE_HTTP_REQUESTS
     apr_thread_mutex_t* req_mutex;
+#endif
 } mod_rivet_globals;
 
 #define BRIDGE_SUPERVISOR_WAIT  1000000
@@ -298,4 +299,13 @@ EXTERN int RivetContent (rivet_thread_pr
 
 #define MODNAME                     "mod_rivet"
 
+#ifdef RIVET_SERIALIZE_HTTP_REQUESTS
+    #define HTTP_REQUESTS_PROC(request_proc_call) \
+        apr_thread_mutex_lock(module_globals->req_mutex);\
+        request_proc_call;\
+        apr_thread_mutex_unlock(module_globals->req_mutex);
+#else
+    #define HTTP_REQUESTS_PROC(request_proc_call) request_proc_call;
+#endif
+
 #endif /* MOD_RIVET_H */

Added: tcl/rivet/trunk/src/experimental/rivet_aprthread_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/rivet_aprthread_mpm.c?rev=1618891&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/rivet_aprthread_mpm.c (added)
+++ tcl/rivet/trunk/src/experimental/rivet_aprthread_mpm.c Tue Aug 19 16:09:15 2014
@@ -0,0 +1,214 @@
+/* rivet_aprthread_mpm.c: dynamically loaded MPM aware functions for threaded MPM */
+
+/*
+    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: */
+
+#include <httpd.h>
+#include <math.h>
+#include <tcl.h>
+#include <ap_mpm.h>
+#include <apr_strings.h>
+
+#include "mod_rivet.h"
+#include "mod_rivet_common.h"
+#include "httpd.h"
+#include "rivetChannel.h"
+#include "apache_config.h"
+
+extern mod_rivet_globals* module_globals;
+extern apr_threadkey_t*  rivet_thread_key;
+extern apr_threadkey_t*  handler_thread_key;
+
+void                  Rivet_PerInterpInit(Tcl_Interp* interp, server_rec *s, apr_pool_t *p);
+void                  Rivet_ProcessorCleanup (void *data);
+rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
+vhost_interp*         Rivet_NewVHostInterp(apr_pool_t* pool);
+
+
+
+
+/* -- supervisor_chores
+ *
+ */
+
+#if 0
+static void supervisor_housekeeping (void)
+{
+    int         nruns = module_globals->num_load_samples;
+    double      devtn;
+    double      count;
+
+    if (nruns == 60)
+    {
+        nruns = 0;
+        module_globals->average_working_threads = 0;
+    }
+
+    ++nruns;
+    count = (int) apr_atomic_read32(module_globals->running_threads_count);
+
+    devtn = ((double)count - module_globals->average_working_threads);
+    module_globals->average_working_threads += devtn / (double)nruns;
+    module_globals->num_load_samples = nruns;
+}
+#endif
+
+int Rivet_MPM_ServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s)
+{
+    Tcl_Interp*         interp;
+    rivet_server_conf*  rsc = RIVET_SERVER_CONF( s->module_config );
+
+    interp = Rivet_CreateTclInterp(s) ; /* Tcl server init interpreter */
+    Rivet_PerInterpInit(interp,s,pPool);
+
+    if (rsc->rivet_server_init_script != NULL) {
+
+        if (Tcl_EvalObjEx(interp, rsc->rivet_server_init_script, 0) != TCL_OK)
+        {
+            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s, 
+                         MODNAME ": Error running ServerInitScript '%s': %s",
+                         Tcl_GetString(rsc->rivet_server_init_script),
+                         Tcl_GetVar(interp, "errorInfo", 0));
+        } else {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 
+                         MODNAME ": ServerInitScript '%s' successful", 
+                         Tcl_GetString(rsc->rivet_server_init_script));
+        }
+    }
+
+    Tcl_DeleteInterp(interp);
+
+    Tcl_SetPanicProc(Rivet_Panic);
+    return OK;
+}
+
+void Rivet_MPM_ChildInit (apr_pool_t* pool, server_rec* server)
+{
+
+    apr_thread_mutex_create(&module_globals->job_mutex, APR_THREAD_MUTEX_UNNESTED, pool);
+    apr_thread_cond_create(&module_globals->job_cond, pool);
+
+}
+
+int Rivet_MPM_Request (request_rec* r)
+{
+    rivet_thread_private*   private;
+    Tcl_Channel*            outchannel;		    /* stuff for buffering output */
+    rivet_server_conf*      server_conf;
+    int                     retcode;
+
+    if (apr_threadkey_private_get ((void **)&private,rivet_thread_key) != APR_SUCCESS)
+    {
+        return HTTP_INTERNAL_SERVER_ERROR;
+    } 
+    else 
+    {
+
+        if (private == NULL)
+        {
+            apr_thread_mutex_lock(module_globals->pool_mutex);
+            private = apr_palloc (module_globals->pool,sizeof(*private));
+            apr_thread_mutex_unlock(module_globals->pool_mutex);
+
+            private->req_cnt    = 0;
+            private->keep_going = 1;
+            private->r          = NULL;
+            private->req        = TclWeb_NewRequestObject (module_globals->pool);
+
+            if (apr_pool_create(&private->pool, NULL) != APR_SUCCESS) 
+            {
+                ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, 
+                             MODNAME ": could not create thread private pool");
+                return HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            /* We allocate the array for the interpreters database.
+             * Data referenced in this database must be freed by the thread before exit
+             */
+
+            private->channel    = apr_pcalloc(private->pool,sizeof(Tcl_Channel));
+            private->interps    = apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(vhost_interp));
+            apr_threadkey_private_set (private,rivet_thread_key);
+            outchannel  = private->channel;
+            *outchannel = Tcl_CreateChannel(&RivetChan, "apacheout", rivet_thread_key, TCL_WRITABLE);
+
+                /* The channel we have just created replaces Tcl's stdout */
+
+            Tcl_SetStdChannel (*outchannel, TCL_STDOUT);
+
+                /* Set the output buffer size to the largest allowed value, so that we 
+                 * won't send any result packets to the browser unless the Rivet
+                 * programmer does a "flush stdout" or the page is completed.
+                 */
+
+            Tcl_SetChannelBufferSize (*outchannel, TCL_MAX_CHANNEL_BUFFER_SIZE);
+
+                /* So far nothing differs much with what we did for the prefork bridge */
+                /* At this stage we have to set up the private interpreters of configured 
+                 * virtual hosts (if any). We assume the server_rec stored in the module
+                 * globals can be used to retrieve the reference to the root interpreter
+                 * configuration and to the rivet global script
+                 */
+
+            if (Rivet_VirtualHostsInterps (private) == NULL)
+            {
+                return HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+        }
+    }
+
+    private->r   = r;
+    server_conf = RIVET_SERVER_CONF(private->r->server->module_config);
+    TclWeb_InitRequest(private->req, private->interps[server_conf->idx]->interp, private->r);
+
+    HTTP_REQUESTS_PROC(retcode = Rivet_SendContent(private));
+
+    return retcode;
+}
+
+apr_status_t Rivet_MPM_Finalize (void* data)
+{
+    apr_status_t  rv;
+    apr_status_t  thread_status;
+    server_rec* s = (server_rec*) data;
+    
+    apr_thread_mutex_lock(module_globals->job_mutex);
+    module_globals->server_shutdown = 1;
+    apr_thread_cond_signal(module_globals->job_cond);
+    apr_thread_mutex_unlock(module_globals->job_mutex);
+
+    rv = apr_thread_join (&thread_status,module_globals->supervisor);
+    if (rv != APR_SUCCESS)
+    {
+        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+                     MODNAME ": Error joining supervisor thread");
+    }
+
+    apr_threadkey_private_delete (rivet_thread_key);
+    return OK;
+}
+
+vhost_interp* Rivet_MPM_MasterInterp(apr_pool_t* pool)
+{
+    return Rivet_NewVHostInterp(pool);
+}
+

Propchange: tcl/rivet/trunk/src/experimental/rivet_aprthread_mpm.c
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: tcl/rivet/trunk/src/experimental/rivet_worker_mpm.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/rivet_worker_mpm.c?rev=1618891&r1=1618890&r2=1618891&view=diff
==============================================================================
--- tcl/rivet/trunk/src/experimental/rivet_worker_mpm.c (original)
+++ tcl/rivet/trunk/src/experimental/rivet_worker_mpm.c Tue Aug 19 16:09:15 2014
@@ -194,7 +194,7 @@ static void* APR_THREAD_FUNC request_pro
         private->r   = request_obj->r;
         private->req = request_obj->req;
 
-        request_obj->code = Rivet_SendContent(private);
+        HTTP_REQUESTS_PROC(request_obj->code = Rivet_SendContent(private))
 
         apr_thread_mutex_lock(request_obj->mutex);
         request_obj->status = done;



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