From 95fa76f5f3208d913320c13a05171ecdcd7134c2 Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Sat, 2 Jan 2010 10:27:26 +0000 Subject: Performance improvements when running both in multi-threaded and pre-forked HTTPD. Changed memory management to use Apache APR pools instead of ref counting pointers as it's much faster and easier to integrate with the Python and Ruby interpreters. Changed to use simple pool-based string and stream implementations instead of the STL ones, which cause a lots of mutex locks in a multi-threaded environment. Added build options to compile with threading and profiling. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@895165 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/modules/http/httpd.hpp | 103 ++++++++++++++++------------------- 1 file changed, 46 insertions(+), 57 deletions(-) (limited to 'sca-cpp/trunk/modules/http/httpd.hpp') diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 890fee8f01..e0c5d110c4 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -26,8 +26,8 @@ * HTTPD module implementation functions. */ -#include -#include +#include "string.hpp" +#include "stream.hpp" #include "apr_strings.h" #include "apr_fnmatch.h" @@ -60,9 +60,7 @@ namespace httpd { * Returns a server-scoped module configuration. */ template void* makeServerConf(apr_pool_t *p, server_rec *s) { - C* c = new (apr_palloc(p, sizeof(C))) C(s); - apr_pool_cleanup_register(p, c, gc_pool_cleanupCallback, apr_pool_cleanup_null) ; - return c; + return new (gc_new(p)) C(s); } template const C& serverConf(const request_rec* r, const module* mod) { @@ -78,9 +76,7 @@ template C& serverConf(const cmd_parms *cmd, const module* mod) { * Returns a directory-scoped module configuration. */ template void *makeDirConf(apr_pool_t *p, char *dirspec) { - C* c = new (apr_palloc(p, sizeof(C))) C(dirspec); - apr_pool_cleanup_register(p, c, gc_pool_cleanupCallback, apr_pool_cleanup_null) ; - return c; + return new (gc_new(p)) C(dirspec); } template C& dirConf(const request_rec* r, const module* mod) { @@ -90,31 +86,25 @@ template C& dirConf(const request_rec* r, const module* mod) { /** * Convert a path string to a list of values. */ -const list pathTokens(const char* p) { +const list pathTokens(const char* p) { if (p == NULL || p[0] == '\0') - return list(); + return list(); if (p[0] == '/') return tokenize("/", p + 1); return tokenize("/", p); } -const list pathValues(const list& l) { - if (isNil(l)) - return list(); - return cons(car(l), pathValues(cdr(l))); -} - -const list path(const char* p) { - return pathValues(pathTokens(p)); +const list pathValues(const char* p) { + return mkvalues(pathTokens(p)); } /** * Convert a path represented as a list of values to a string. */ -const std::string path(const list& p) { +const string path(const list& p) { if (isNil(p)) return ""; - return std::string("/") + std::string(car(p)) + path(cdr(p)); + return string("/") + car(p) + path(cdr(p)); } /** @@ -126,7 +116,7 @@ const char* optional(const char* s) { return s; } -const std::string contentType(const request_rec* r) { +const string contentType(const request_rec* r) { return optional(apr_table_get(r->headers_in, "Content-Type")); } @@ -136,24 +126,24 @@ const std::string contentType(const request_rec* r) { * Debug log. */ int debugHeader(unused void* r, const char* key, const char* value) { - std::cerr << " header key: " << key << ", value: " << value << std::endl; + cerr << " header key: " << key << ", value: " << value << endl; return 1; } -const bool debugRequest(request_rec* r, const std::string& msg) { - std::cerr << msg << ":" << std::endl; - std::cerr << " protocol: " << optional(r->protocol) << std::endl; - std::cerr << " method: " << optional(r->method) << std::endl; - std::cerr << " method number: " << r->method_number << std::endl; - std::cerr << " content type: " << contentType(r) << std::endl; - std::cerr << " content encoding: " << optional(r->content_encoding) << std::endl; +const bool debugRequest(request_rec* r, const string& msg) { + cerr << msg << ":" << endl; + cerr << " protocol: " << optional(r->protocol) << endl; + cerr << " method: " << optional(r->method) << endl; + cerr << " method number: " << r->method_number << endl; + cerr << " content type: " << contentType(r) << endl; + cerr << " content encoding: " << optional(r->content_encoding) << endl; apr_table_do(debugHeader, r, r->headers_in, NULL); - std::cerr << " unparsed uri: " << optional(r->unparsed_uri) << std::endl; - std::cerr << " uri: " << optional(r->uri) << std::endl; - std::cerr << " path info: " << optional(r->path_info) << std::endl; - std::cerr << " filename: " << optional(r->filename) << std::endl; - std::cerr << " uri tokens: " << pathTokens(r->uri) << std::endl; - std::cerr << " args: " << optional(r->args) << std::endl; + cerr << " unparsed uri: " << optional(r->unparsed_uri) << endl; + cerr << " uri: " << optional(r->uri) << endl; + cerr << " path info: " << optional(r->path_info) << endl; + cerr << " filename: " << optional(r->filename) << endl; + cerr << " uri tokens: " << pathTokens(r->uri) << endl; + cerr << " args: " << optional(r->args) << endl; return true; } @@ -177,16 +167,16 @@ const list pathInfo(const list& uri, const list& path) { /** * Returns a list of key value pairs from the args in a query string. */ -const list queryArg(const std::string& s) { - const list t = tokenize("=", s); - return mklist(car(t).c_str(), cadr(t)); +const list queryArg(const string& s) { + const list t = tokenize("=", s); + return mklist(c_str(car(t)), cadr(t)); } const list > queryArgs(const request_rec* r) { const char* a = r->args; if (a == NULL) return list >(); - return map>(queryArg, tokenize("&", a)); + return map>(queryArg, tokenize("&", a)); } /** @@ -229,50 +219,49 @@ const int setupReadPolicy(request_rec* r) { /** * Read the content of a POST or PUT. */ -const list read(request_rec* r) { - char b[2048]; - const int n = ap_get_client_block(r, b, 2048); +const list read(request_rec* r) { + char b[1024]; + const int n = ap_get_client_block(r, b, sizeof(b)); if (n <= 0) - return list(); - return cons(std::string(b, n), read(r)); + return list(); + return cons(string(b, n), read(r)); } /** * Convert a URI value to an absolute URL. */ const char* url(const value& v, request_rec* r) { - std::string u = r->uri; - u.append("/"); - u.append(v); - return ap_construct_url(r->pool, u.c_str(), r); + const string u = string(r->uri) + "/" + v; + return ap_construct_url(r->pool, c_str(u), r); } /** * Write an HTTP result. */ -const failable writeResult(const failable, std::string>& ls, const std::string& ct, request_rec* r) { +const failable writeResult(const failable >& ls, const string& ct, request_rec* r) { if (!hasContent(ls)) - return mkfailure(reason(ls)); - std::ostringstream os; + return mkfailure(reason(ls)); + ostringstream os; write(content(ls), os); - debug(os.str(), "httpd::result"); + const string ob(str(os)); + debug(ob, "httpd::result"); - const std::string etag(ap_md5(r->pool, (const unsigned char*)std::string(os.str()).c_str())); + const string etag(ap_md5(r->pool, (const unsigned char*)c_str(ob))); const char* match = apr_table_get(r->headers_in, "If-None-Match"); - apr_table_setn(r->headers_out, "ETag", apr_pstrdup(r->pool, etag.c_str())); + apr_table_setn(r->headers_out, "ETag", apr_pstrdup(r->pool, c_str(etag))); if (match != NULL && etag == match) { r->status = HTTP_NOT_MODIFIED; return OK; } - ap_set_content_type(r, apr_pstrdup(r->pool, ct.c_str())); - ap_rputs(std::string(os.str()).c_str(), r); + ap_set_content_type(r, apr_pstrdup(r->pool, c_str(ct))); + ap_rputs(c_str(ob), r); return OK; } /** * Report request execution status. */ -const int reportStatus(const failable& rc) { +const int reportStatus(const failable& rc) { if (!hasContent(rc)) return HTTP_INTERNAL_SERVER_ERROR; return content(rc); -- cgit v1.2.3