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