You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by pq...@apache.org on 2009/03/28 02:02:32 UTC

svn commit: r759414 - in /httpd/httpd/trunk/modules/proxy: mod_serf.c mod_serf.h

Author: pquerna
Date: Sat Mar 28 01:02:32 2009
New Revision: 759414

URL: http://svn.apache.org/viewvc?rev=759414&view=rev
Log:
If the MPM supports serf in its core, use this to drive the proxied request 
completely async from the original thread.

Right now it uses a 100ms timer to determine when the request is actaully complete,
but I think this can be removed in the long run with a better mechanism.

Modified:
    httpd/httpd/trunk/modules/proxy/mod_serf.c
    httpd/httpd/trunk/modules/proxy/mod_serf.h

Modified: httpd/httpd/trunk/modules/proxy/mod_serf.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_serf.c?rev=759414&r1=759413&r2=759414&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_serf.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_serf.c Sat Mar 28 01:02:32 2009
@@ -25,9 +25,10 @@
 #include "serf.h"
 #include "apr_uri.h"
 #include "apr_strings.h"
-
+#include "ap_mpm.h"
 
 module AP_MODULE_DECLARE_DATA serf_module;
+static int mpm_supprts_serf = 0;
 
 typedef struct {
     int on;
@@ -325,13 +326,39 @@
     return APR_SUCCESS;
 }
 
+static void 
+timed_callback(void *baton)
+{
+    s_baton_t *ctx = baton;
+
+    if (ctx->keep_reading) {
+        ap_mpm_register_timed_callback(apr_time_from_msec(100), timed_callback, baton);
+    }
+    else if (ctx->rstatus) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, ctx->rstatus, ctx->r,
+                      "serf: request returned: %d", ctx->rstatus);
+        ctx->r->status = HTTP_OK;
+        ap_die(ctx->rstatus, ctx->r);
+    }
+    else {
+        ap_finalize_request_protocol(ctx->r);
+        ap_process_request_after_handler(ctx->r);
+        return;
+    }
+}
+
+
+#ifndef apr_time_from_msec
+#define apr_time_from_msec(x) (x * 1000)
+#endif
+
 /* TOOD: rewrite drive_serf to make it async */
 static int drive_serf(request_rec *r, serf_config_t *conf)
 {
     apr_status_t rv;
     apr_pool_t *pool = r->pool;
     apr_sockaddr_t *address;
-    s_baton_t baton;
+    s_baton_t *baton = apr_palloc(r->pool, sizeof(s_baton_t));
     /* XXXXX: make persistent/per-process or something.*/
     serf_context_t *serfme;
     serf_connection_t *conn;
@@ -409,49 +436,71 @@
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    serfme = serf_context_create(pool);
+    if (mpm_supprts_serf) {
+        serfme = ap_lookup_provider("mpm_serf", "instance", "0");
+        if (!serfme) {
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "mpm lied to us about supporting serf.");
+            return HTTP_INTERNAL_SERVER_ERROR;
+        }
+    }
+    else {
+        serfme = serf_context_create(pool);
+    }
 
-    baton.r = r;
-    baton.conf = conf;
-    baton.bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
-    baton.ssl_ctx = NULL;
-    baton.rstatus = OK;
+    baton->r = r;
+    baton->conf = conf;
+    baton->bkt_alloc = serf_bucket_allocator_create(pool, NULL, NULL);
+    baton->ssl_ctx = NULL;
+    baton->rstatus = OK;
 
-    baton.done_headers = 0;
-    baton.keep_reading = 1;
+    baton->done_headers = 0;
+    baton->keep_reading = 1;
 
     if (strcasecmp(conf->url.scheme, "https") == 0) {
-        baton.want_ssl = 1;
+        baton->want_ssl = 1;
     }
     else {
-        baton.want_ssl = 0;
+        baton->want_ssl = 0;
     }
 
     conn = serf_connection_create(serfme, address,
-                                  conn_setup, &baton,
-                                  closed_connection, &baton,
+                                  conn_setup, baton,
+                                  closed_connection, baton,
                                   pool);
 
     srequest = serf_connection_request_create(conn, setup_request,
-                                              &baton);
+                                              baton);
 
-    do {
-        rv = serf_context_run(serfme, SERF_DURATION_FOREVER, pool);
-
-        /* XXXX: Handle timeouts */
-        if (APR_STATUS_IS_TIMEUP(rv)) {
-            continue;
-        }
+    if (mpm_supprts_serf) {
 
+        rv = ap_mpm_register_timed_callback(apr_time_from_msec(100), timed_callback, baton);
+        
         if (rv != APR_SUCCESS) {
-            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "serf_context_run()");
+            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "ap_mpm_register_timed_callback failed.");
             return HTTP_INTERNAL_SERVER_ERROR;       
         }
 
-        serf_debug__closed_conn(baton.bkt_alloc);
-    } while (baton.keep_reading);
-
-    return baton.rstatus;
+        return SUSPENDED;
+    }
+    else {
+        do {
+            rv = serf_context_run(serfme, SERF_DURATION_FOREVER, pool);
+            
+            /* XXXX: Handle timeouts */
+            if (APR_STATUS_IS_TIMEUP(rv)) {
+                continue;
+            }
+            
+            if (rv != APR_SUCCESS) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "serf_context_run()");
+                return HTTP_INTERNAL_SERVER_ERROR;       
+            }
+            
+            serf_debug__closed_conn(baton->bkt_alloc);
+        } while (baton->keep_reading);
+        
+        return baton->rstatus;
+    }
 }
 
 static int serf_handler(request_rec *r)
@@ -860,6 +909,13 @@
 
 static void register_hooks(apr_pool_t *p)
 {
+    apr_status_t rv;
+    rv = ap_mpm_query(AP_MPMQ_HAS_SERF, &mpm_supprts_serf);
+
+    if (rv != APR_SUCCESS) {
+        mpm_supprts_serf = 0;
+    }
+    
     ap_register_provider(p, AP_SERF_CLUSTER_PROVIDER,
                          "heartbeat", "0", &builtin_heartbeat);
 

Modified: httpd/httpd/trunk/modules/proxy/mod_serf.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_serf.h?rev=759414&r1=759413&r2=759414&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_serf.h (original)
+++ httpd/httpd/trunk/modules/proxy/mod_serf.h Sat Mar 28 01:02:32 2009
@@ -23,6 +23,14 @@
 
 #include "httpd.h"
 #include "http_config.h"
+#include "ap_config_auto.h"
+#ifdef HAVE_SERF_H
+#include "serf.h"
+#ifndef AP_HAS_SERF
+#define AP_HAS_SERF 1
+#endif
+#endif
+
 #include "ap_provider.h"
 
 #ifndef _MOD_SERF_H_