Permalink
Browse files

Increase performance by taking less global locks

Store progress data in request local pool, update shared memory twice per second

Signed-off-by: Michał Pokrywka <michal.pokrywka@gmail.com>
  • Loading branch information...
1 parent 3193a18 commit d8246af72c45642014c2d85ba8370b4878a24e15 @mpokrywka mpokrywka committed Mar 2, 2011
Showing with 65 additions and 38 deletions.
  1. +7 −0 ap_backports.h
  2. +58 −38 mod_upload_progress.c
View
@@ -7,6 +7,13 @@
#endif
/*
+ * apr_time_from_msec is defined in APR 1.4.0 or later
+ */
+#if (APR_MAJOR_VERSION < 1) || ((APR_MAJOR_VERSION == 1) && (APR_MINOR_VERSION < 4))
+#define apr_time_from_msec(x) (x * 1000)
+#endif
+
+/*
* The following is a patch ported from mod_fcgid for Apache 2.0 releases
* which don't provide a version of apr_shm_remove.
*
View
@@ -105,6 +105,11 @@ typedef struct upload_progress_node_s{
} upload_progress_node_t;
typedef struct {
+ apr_time_t cache_updated_at;
+ upload_progress_node_t node;
+} upload_progress_req_t;
+
+typedef struct {
int count;
int active;
} upload_progress_cache_t;
@@ -142,6 +147,12 @@ static inline DirConfig *get_dir_config(request_rec *r)
return (DirConfig *)ap_get_module_config(r->per_dir_config, &upload_progress_module);
}
+static inline upload_progress_req_t *get_request_config(request_rec *r)
+{
+ return (upload_progress_req_t *)ap_get_module_config(r->request_config, &upload_progress_module);
+}
+
+
static int upload_progress_handle_request(request_rec *r)
{
server_rec *server = r->server;
@@ -184,6 +195,13 @@ static int upload_progress_handle_request(request_rec *r)
}
if (node) {
+ upload_progress_req_t *reqinfo = (upload_progress_req_t *)apr_pcalloc(r->pool,
+ sizeof(upload_progress_req_t));
+ if (reqinfo) {
+ reqinfo->cache_updated_at = apr_time_now();
+ memcpy(&(reqinfo->node), node, sizeof(upload_progress_node_t));
+ }
+ ap_set_module_config(r->request_config, &upload_progress_module, reqinfo);
apr_pool_cleanup_register(r->pool, r, upload_progress_cleanup, apr_pool_cleanup_null);
ap_add_input_filter("UPLOAD_PROGRESS", NULL, r, r->connection);
}
@@ -298,40 +316,44 @@ static int track_upload_progress(ap_filter_t *f, apr_bucket_brigade *bb,
{
server_rec *server = f->r->server;
/**/up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "track_upload_progress()");
- apr_status_t rv;
- upload_progress_node_t *node;
ServerConfig* config = get_server_config(server);
- rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
-
- int param_error;
- const char* id = get_progress_id(f->r, &param_error);
+ apr_status_t rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
- if (id == NULL) {
- up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "Progress id not found, param_error %i", param_error);
+ upload_progress_req_t *reqinfo = get_request_config(f->r);
+ if (!reqinfo) {
+ up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "Request config not available");
return rv;
}
+ upload_progress_node_t *node = &(reqinfo->node);
- CACHE_LOCK();
- node = find_node(server, id);
- if (node) {
- time_t t = time(NULL);
- node->updated_at = t;
- if (rv == APR_SUCCESS) {
- apr_off_t length;
- apr_brigade_length(bb, 1, &length);
- node->received += length;
- if (node->received > node->length) /* handle chunked tranfer */
- node->length = node->received;
- int upload_time = t - node->started_at;
- if (upload_time > 0) {
- node->speed = node->received / upload_time;
- }
- } else {
- node->err_status = read_request_status(f->r);
+ time_t t = time(NULL);
+ node->updated_at = t;
+ if (rv == APR_SUCCESS) {
+ apr_off_t length;
+ apr_brigade_length(bb, 1, &length);
+ node->received += length;
+ if (node->received > node->length) /* handle chunked tranfer */
+ node->length = node->received;
+ int upload_time = t - node->started_at;
+ if (upload_time > 0) {
+ node->speed = node->received / upload_time;
}
+ } else {
+ node->err_status = read_request_status(f->r);
+ reqinfo->cache_updated_at = 0; /* force cache update */
+ }
+
+ apr_time_t now = apr_time_now();
+ if ((now - reqinfo->cache_updated_at) > apr_time_from_msec(500)) {
+ reqinfo->cache_updated_at = now;
+ CACHE_LOCK();
+ upload_progress_node_t *cache_node = find_node(server, node->key);
+ if (cache_node) {
+ memcpy(cache_node, node, sizeof(upload_progress_node_t);
+ }
+ CACHE_UNLOCK();
}
- CACHE_UNLOCK();
return rv;
}
@@ -469,22 +491,20 @@ static apr_status_t upload_progress_cleanup(void *data)
/**/up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "upload_progress_cleanup()");
ServerConfig *config = get_server_config(server);
- int param_error;
- const char* id = get_progress_id(r, &param_error);
-
- if (id == NULL) {
- up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "Progress id not found, param_error %i", param_error);
+ upload_progress_req_t *reqinfo = get_request_config(r);
+ if (!reqinfo) {
+ up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "Request config not available");
return APR_SUCCESS;
}
+ upload_progress_node_t *node = &(reqinfo->node);
+ node->err_status = read_request_status(r);
+ node->updated_at = time(NULL);
+ node->done = 1;
CACHE_LOCK();
- upload_progress_node_t *node = find_node(server, id);
- if (node) {
- node->err_status = read_request_status(r);
- node->updated_at = time(NULL);
- node->done = 1;
- } else {
- up_log(APLOG_MARK, APLOG_DEBUG, 0, server, "Node not found for id %s", id);
+ upload_progress_node_t *cache_node = find_node(server, node->key);
+ if (cache_node) {
+ memcpy(cache_node, node, sizeof(upload_progress_node_t));
}
CACHE_UNLOCK();

0 comments on commit d8246af

Please sign in to comment.