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