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/07/16 16:54:11 UTC
svn commit: r1611036 - in /tcl/rivet/trunk: ChangeLog src/experimental/
src/experimental/mod_rivet.c src/experimental/mod_rivet.h
Author: mxmanghi
Date: Wed Jul 16 14:54:11 2014
New Revision: 1611036
URL: http://svn.apache.org/r1611036
Log:
* src/experimental: add experimental code for threaded module
Added:
tcl/rivet/trunk/src/experimental/
tcl/rivet/trunk/src/experimental/mod_rivet.c
tcl/rivet/trunk/src/experimental/mod_rivet.h
Modified:
tcl/rivet/trunk/ChangeLog
Modified: tcl/rivet/trunk/ChangeLog
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/ChangeLog?rev=1611036&r1=1611035&r2=1611036&view=diff
==============================================================================
--- tcl/rivet/trunk/ChangeLog (original)
+++ tcl/rivet/trunk/ChangeLog Wed Jul 16 14:54:11 2014
@@ -1,3 +1,6 @@
+2014-07-16 Massimo Manghi <mx...@apache.org>
+ * src/experimental: add experimental code for threaded module
+
2014-07-10 Massimo Manghi <mx...@apache.org>
* src/apache-2/apache_config.[h|c]: moved to src/config
* src/apache-2/TclWebapache.c: this file moved temporarily into src/config to separate it from
Added: tcl/rivet/trunk/src/experimental/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet.c?rev=1611036&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet.c (added)
+++ tcl/rivet/trunk/src/experimental/mod_rivet.c Wed Jul 16 14:54:11 2014
@@ -0,0 +1,189 @@
+
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_protocol.h"
+#include <ap_config.h>
+#include <apr_queue.h>
+#include <apr_strings.h>
+#include <apr_general.h>
+#include <apr_thread_proc.h>
+#include <apr_thread_cond.h>
+#include <tcl.h>
+
+#include "TclWeb.h"
+#include "rivetChannel.h"
+#include "mod_rivet.h"
+
+#define RIVET_TEMPLATE_CTYPE "application/x-httpd-rivet"
+#define RIVET_TCLFILE_CTYPE "application/x-rivet-tcl"
+#define MODNAME "mod_rivet"
+
+int
+Rivet_ParseExecString (TclWebRequest* req, Tcl_Obj* inbuf)
+{
+ return TCL_OK;
+}
+
+int
+Rivet_ParseExecFile(TclWebRequest *req, char *filename, int toplevel)
+{
+ return TCL_OK;
+}
+
+static void RivetReleaseInterp(int interp_id)
+{
+ apr_thread_mutex_lock(module_globals.mutex);
+ module_globals.status[interp_id] = idle;
+ module_globals.busy_cnt--;
+ apr_thread_mutex_unlock(module_globals.mutex);
+}
+
+static int RivetFetchInterp(Tcl_Interp** interp_p)
+{
+ int c;
+ int interp_id;
+ int interp_found = 0;
+
+ apr_thread_mutex_lock(module_globals.mutex);
+ do
+ {
+ while (module_globals.busy_cnt >= TCL_INTERPS)
+ {
+ apr_thread_cond_wait(module_globals.cond, module_globals.mutex);
+ }
+
+ for (c = 0; c < TCL_INTERPS; c++)
+ {
+ interp_id = module_globals.interp_idx + c + 1;
+ interp_id %= TCL_INTERPS;
+ if (module_globals.status[interp_id] == idle)
+ {
+ module_globals.interp_idx = interp_id;
+ interp_found = 1;
+ module_globals.status[interp_id] = request_processing;
+ module_globals.busy_cnt++;
+ *interp_p = module_globals.interp_a[interp_id];
+ break;
+ }
+ }
+
+ // we should assert here an idle interpreter has been found, otherwise
+ // the busy_cnt was inconsistent.
+
+ } while (!interp_found);
+ apr_thread_mutex_unlock(module_globals.mutex);
+
+ return interp_id;
+}
+
+static int
+RivetServerInit (apr_pool_t *pPool, apr_pool_t *pLog, apr_pool_t *pTemp, server_rec *s)
+{
+ ap_add_version_component(pPool, "Rivet-experimental");
+ return OK;
+}
+
+static void
+RivetInit (apr_pool_t *pChild, server_rec *s)
+{
+ int i;
+
+ if (apr_pool_create(&module_globals.pool, NULL) != APR_SUCCESS)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ MODNAME ": could not initialize mod_rivet private pool");
+ exit(1);
+ }
+
+ apr_thread_mutex_create(&module_globals.mutex, APR_THREAD_MUTEX_UNNESTED, pChild);
+ apr_thread_cond_create(&module_globals.cond, pChild);
+ // apr_thread_create(&module_globals.thd, NULL, do_content, &module_globals, pPool);
+ // apr_queue_create(&module_globals.queue,100,pPool);
+
+ for (i = 0; i < TCL_INTERPS; i++)
+ {
+ Tcl_Interp* interp;
+ Tcl_Channel *outchannel; /* stuff for buffering output */
+
+ interp = Tcl_CreateInterp();
+ if (Tcl_Init(interp) == TCL_ERROR)
+ {
+ ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
+ MODNAME ": Error in Tcl_Init: %s, aborting\n",
+ Tcl_GetStringResult(interp));
+ exit(1);
+ }
+ module_globals.interp_a[i] = interp;
+ module_globals.status[i] = idle;
+
+ outchannel = apr_pcalloc (pPool, sizeof(Tcl_Channel));
+ outchannel = Tcl_CreateChannel(&RivetChan, "apacheout", &module_globals, 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);
+
+ /* We register the Tcl channel to the interpreter */
+
+ Tcl_RegisterChannel(interp, outchannel);
+ }
+ module_globals.interp_idx = 0;
+}
+
+static int RivetHandler(request_rec *r)
+{
+ Tcl_Interp* interp;
+ Tcl_Obj* script = NULL;
+ int interp_id;
+
+ if (strcmp(r->handler, "application/x-httpd-rivet")) {
+ return DECLINED;
+ }
+
+ if (r->method_number != M_GET) { return DECLINED; }
+
+ r->content_type = "text/html";
+ if (r->header_only) return OK;
+ //if (r->args == 0) return OK;
+
+ interp_id = RivetFetchInterp(&interp);
+
+ script = Tcl_NewStringObj("puts \"<html><head><title>experimental module</title></head><body><h2>\"\n",-1);
+ Tcl_AppendStringsToObj(script,"puts -nonewline \"current interp index: \"\nputs ",NULL);
+ Tcl_AppendObjToObj(script,Tcl_NewIntObj(interp_id));
+ Tcl_AppendStringsToObj(script,"\n</h2></body></html>",NULL);
+
+ Tcl_EvalObjEx(interp, script, 0);
+
+ RivetReleaseInterp(interp_id);
+
+ return OK;
+}
+
+static void rivet_register_hooks(apr_pool_t *p)
+{
+ ap_hook_handler(RivetHandler, NULL, NULL, APR_HOOK_MIDDLE);
+ ap_hook_child_init(RivetInit, NULL, NULL, APR_HOOK_LAST);
+ ap_hook_post_config (RivetServerInit, NULL, NULL, APR_HOOK_LAST);
+}
+
+
+/* Dispatch list for API hooks */
+module AP_MODULE_DECLARE_DATA rivet_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL, /* create per-dir config structures */
+ NULL, /* merge per-dir config structures */
+ NULL, /* create per-server config structures */
+ NULL, /* merge per-server config structures */
+ NULL, /* table of config file commands */
+ rivet_register_hooks /* register hooks */
+};
+
Added: tcl/rivet/trunk/src/experimental/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/trunk/src/experimental/mod_rivet.h?rev=1611036&view=auto
==============================================================================
--- tcl/rivet/trunk/src/experimental/mod_rivet.h (added)
+++ tcl/rivet/trunk/src/experimental/mod_rivet.h Wed Jul 16 14:54:11 2014
@@ -0,0 +1,31 @@
+#define TCL_INTERPS 4
+
+typedef int rivet_thr_status;
+
+typedef struct {
+
+ /* condition variable should be used with a mutex variable */
+
+ apr_thread_mutex_t *mutex;
+ apr_thread_cond_t *cond;
+ apr_queue_t *queue;
+ apr_pool_t *pool;
+ Tcl_Interp* interp_a[TCL_INTERPS];
+ rivet_thr_status status[TCL_INTERPS];
+ int interp_idx;
+ int busy_cnt;
+
+} mod_rivet_globals;
+
+typedef struct {
+ request_rec *r;
+} rivet_request;
+
+enum
+{
+ idle,
+ request_processing
+};
+
+mod_rivet_globals module_globals;
+
---------------------------------------------------------------------
To unsubscribe, e-mail: site-cvs-unsubscribe@tcl.apache.org
For additional commands, e-mail: site-cvs-help@tcl.apache.org