diff options
Diffstat (limited to 'modules/cache')
-rw-r--r-- | modules/cache/cache_storage.c | 5 | ||||
-rw-r--r-- | modules/cache/cache_util.c | 2 | ||||
-rw-r--r-- | modules/cache/config.m4 | 1 | ||||
-rw-r--r-- | modules/cache/mod_cache.c | 27 | ||||
-rw-r--r-- | modules/cache/mod_cache_disk.c | 41 | ||||
-rw-r--r-- | modules/cache/mod_cache_socache.c | 98 | ||||
-rw-r--r-- | modules/cache/mod_file_cache.c | 2 | ||||
-rw-r--r-- | modules/cache/mod_socache_dbm.c | 171 | ||||
-rw-r--r-- | modules/cache/mod_socache_dc.c | 2 | ||||
-rw-r--r-- | modules/cache/mod_socache_memcache.c | 13 | ||||
-rw-r--r-- | modules/cache/mod_socache_redis.c | 486 | ||||
-rw-r--r-- | modules/cache/mod_socache_redis.dep | 5 | ||||
-rw-r--r-- | modules/cache/mod_socache_redis.dsp | 111 | ||||
-rw-r--r-- | modules/cache/mod_socache_redis.mak | 353 | ||||
-rw-r--r-- | modules/cache/mod_socache_shmcb.c | 27 |
15 files changed, 1233 insertions, 111 deletions
diff --git a/modules/cache/cache_storage.c b/modules/cache/cache_storage.c index 41f638c..dfda34b 100644 --- a/modules/cache/cache_storage.c +++ b/modules/cache/cache_storage.c @@ -270,8 +270,7 @@ int cache_select(cache_request_rec *cache, request_rec *r) * language negotiated document in a different language by mistake. * * This code makes the assumption that the storage manager will - * cache the req_hdrs if the response contains a Vary - * header. + * cache the req_hdrs if the response contains a Vary header. * * RFC2616 13.6 and 14.44 describe the Vary mechanism. */ @@ -549,7 +548,7 @@ static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, } else { if (conf->base_uri && conf->base_uri->port_str) { - port_str = conf->base_uri->port_str; + port_str = apr_pstrcat(p, ":", conf->base_uri->port_str, NULL); } else if (conf->base_uri && conf->base_uri->hostname) { port_str = ""; diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c index aa04913..fc36431 100644 --- a/modules/cache/cache_util.c +++ b/modules/cache/cache_util.c @@ -30,7 +30,7 @@ extern module AP_MODULE_DECLARE_DATA cache_module; /* Determine if "url" matches the hostname, scheme and port and path * in "filter". All but the path comparisons are case-insensitive. */ -static int uri_meets_conditions(const apr_uri_t *filter, const int pathlen, +static int uri_meets_conditions(const apr_uri_t *filter, const apr_size_t pathlen, const apr_uri_t *url, const char *path) { /* Scheme, hostname port and local part. The filter URI and the diff --git a/modules/cache/config.m4 b/modules/cache/config.m4 index 8115094..4fa414b 100644 --- a/modules/cache/config.m4 +++ b/modules/cache/config.m4 @@ -133,6 +133,7 @@ fi APACHE_MODULE(socache_shmcb, shmcb small object cache provider, , , most) APACHE_MODULE(socache_dbm, dbm small object cache provider, , , most) APACHE_MODULE(socache_memcache, memcache small object cache provider, , , most) +APACHE_MODULE(socache_redis, redis small object cache provider, , , most) APACHE_MODULE(socache_dc, distcache small object cache provider, , , no, [ APACHE_CHECK_DISTCACHE ]) diff --git a/modules/cache/mod_cache.c b/modules/cache/mod_cache.c index 56a09f5..3b4469e 100644 --- a/modules/cache/mod_cache.c +++ b/modules/cache/mod_cache.c @@ -986,7 +986,7 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* 304 does not contain Content-Type and mod_mime regenerates the * Content-Type based on the r->filename. This would lead to original - * Content-Type to be lost (overwriten by whatever mod_mime generates). + * Content-Type to be lost (overwritten by whatever mod_mime generates). * We preserves the original Content-Type here. */ ap_set_content_type(r, apr_table_get( cache->stale_handle->resp_hdrs, "Content-Type")); @@ -1229,6 +1229,16 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) return APR_SUCCESS; } + /* Set the content length if known. + */ + cl = apr_table_get(r->err_headers_out, "Content-Length"); + if (cl == NULL) { + cl = apr_table_get(r->headers_out, "Content-Length"); + } + if (cl && !ap_parse_strict_length(&size, cl)) { + reason = "invalid content length"; + } + if (reason) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00768) "cache: %s not cached for request %s. Reason: %s", @@ -1251,19 +1261,6 @@ static apr_status_t cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in) /* Make it so that we don't execute this path again. */ cache->in_checked = 1; - /* Set the content length if known. - */ - cl = apr_table_get(r->err_headers_out, "Content-Length"); - if (cl == NULL) { - cl = apr_table_get(r->headers_out, "Content-Length"); - } - if (cl) { - char *errp; - if (apr_strtoff(&size, cl, &errp, 10) || *errp || size < 0) { - cl = NULL; /* parse error, see next 'if' block */ - } - } - if (!cl) { /* if we don't get the content-length, see if we have all the * buckets and use their length to calculate the size @@ -2533,7 +2530,7 @@ static const command_rec cache_cmds[] = { /* XXX * Consider a new config directive that enables loading specific cache - * implememtations (like mod_cache_mem, mod_cache_file, etc.). + * implementations (like mod_cache_mem, mod_cache_file, etc.). * Rather than using a LoadModule directive, admin would use something * like CacheModule mem_cache_module | file_cache_module, etc, * which would cause the approprpriate cache module to be loaded. diff --git a/modules/cache/mod_cache_disk.c b/modules/cache/mod_cache_disk.c index 52d5dba..8d17a19 100644 --- a/modules/cache/mod_cache_disk.c +++ b/modules/cache/mod_cache_disk.c @@ -284,11 +284,11 @@ static const char* regen_key(apr_pool_t *p, apr_table_t *headers, * HTTP URI's (3.2.3) [host and scheme are insensitive] * HTTP method (5.1.1) * HTTP-date values (3.3.1) - * 3.7 Media Types [exerpt] + * 3.7 Media Types [excerpt] * The type, subtype, and parameter attribute names are case- * insensitive. Parameter values might or might not be case-sensitive, * depending on the semantics of the parameter name. - * 4.20 Except [exerpt] + * 4.20 Except [excerpt] * Comparison of expectation values is case-insensitive for unquoted * tokens (including the 100-continue token), and is case-sensitive for * quoted-string expectation-extensions. @@ -713,7 +713,7 @@ static apr_status_t read_array(request_rec *r, apr_array_header_t* arr, apr_file_t *file) { char w[MAX_STRING_LEN]; - int p; + apr_size_t p; apr_status_t rv; while (1) { @@ -778,7 +778,7 @@ static apr_status_t read_table(cache_handle_t *handle, request_rec *r, { char w[MAX_STRING_LEN]; char *l; - int p; + apr_size_t p; apr_status_t rv; while (1) { @@ -994,10 +994,11 @@ static apr_status_t write_headers(cache_handle_t *h, request_rec *r) } rv = mkdir_structure(conf, dobj->hdrs.file, r->pool); - - rv = apr_file_mktemp(&dobj->vary.tempfd, dobj->vary.tempfile, - APR_CREATE | APR_WRITE | APR_BINARY | APR_EXCL, - dobj->vary.pool); + if (rv == APR_SUCCESS) { + rv = apr_file_mktemp(&dobj->vary.tempfd, dobj->vary.tempfile, + APR_CREATE | APR_WRITE | APR_BINARY | APR_EXCL, + dobj->vary.pool); + } if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r, APLOGNO(00721) @@ -1275,9 +1276,9 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r, * sanity checks. */ if (seen_eos) { - const char *cl_header = apr_table_get(r->headers_out, "Content-Length"); - if (!dobj->disk_info.header_only) { + const char *cl_header; + apr_off_t cl; if (dobj->data.tempfd) { rv = apr_file_close(dobj->data.tempfd); @@ -1296,6 +1297,7 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r, apr_pool_destroy(dobj->data.pool); return APR_EGENERAL; } + if (dobj->file_size < dconf->minfs) { ap_log_rerror( APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00734) "URL %s failed the size check " @@ -1304,17 +1306,16 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r, apr_pool_destroy(dobj->data.pool); return APR_EGENERAL; } - if (cl_header) { - apr_int64_t cl = apr_atoi64(cl_header); - if ((errno == 0) && (dobj->file_size != cl)) { - ap_log_rerror( - APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00735) "URL %s didn't receive complete response, not caching", h->cache_obj->key); - /* Remove the intermediate cache file and return non-APR_SUCCESS */ - apr_pool_destroy(dobj->data.pool); - return APR_EGENERAL; - } - } + cl_header = apr_table_get(r->headers_out, "Content-Length"); + if (cl_header && (!ap_parse_strict_length(&cl, cl_header) + || cl != dobj->file_size)) { + ap_log_rerror( + APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00735) "URL %s didn't receive complete response, not caching", h->cache_obj->key); + /* Remove the intermediate cache file and return non-APR_SUCCESS */ + apr_pool_destroy(dobj->data.pool); + return APR_EGENERAL; + } } /* All checks were fine, we're good to go when the commit comes */ diff --git a/modules/cache/mod_cache_socache.c b/modules/cache/mod_cache_socache.c index 0d76760..5f9e1d6 100644 --- a/modules/cache/mod_cache_socache.c +++ b/modules/cache/mod_cache_socache.c @@ -18,6 +18,12 @@ #include "apr_file_io.h" #include "apr_strings.h" #include "apr_buckets.h" + +#include "apr_version.h" +#if !APR_VERSION_AT_LEAST(2,0,0) +#include "apu_version.h" +#endif + #include "httpd.h" #include "http_config.h" #include "http_log.h" @@ -217,8 +223,8 @@ static apr_status_t read_table(cache_handle_t *handle, request_rec *r, while (apr_isspace(buffer[colon]) && (colon < *slider)) { colon++; } - apr_table_addn(table, apr_pstrndup(r->pool, (const char *) buffer - + key, len - key), apr_pstrndup(r->pool, + apr_table_addn(table, apr_pstrmemdup(r->pool, (const char *) buffer + + key, len - key), apr_pstrmemdup(r->pool, (const char *) buffer + colon, *slider - colon)); (*slider)++; if (buffer[*slider] == '\n') { @@ -298,11 +304,11 @@ static const char* regen_key(apr_pool_t *p, apr_table_t *headers, * HTTP URI's (3.2.3) [host and scheme are insensitive] * HTTP method (5.1.1) * HTTP-date values (3.3.1) - * 3.7 Media Types [exerpt] + * 3.7 Media Types [excerpt] * The type, subtype, and parameter attribute names are case- * insensitive. Parameter values might or might not be case-sensitive, * depending on the semantics of the parameter name. - * 4.20 Except [exerpt] + * 4.20 Except [excerpt] * Comparison of expectation values is case-insensitive for unquoted * tokens (including the 100-continue token), and is case-sensitive for * quoted-string expectation-extensions. @@ -429,6 +435,14 @@ static int create_entity(cache_handle_t *h, request_rec *r, const char *key, return OK; } +static apr_status_t sobj_body_pre_cleanup(void *baton) +{ + cache_socache_object_t *sobj = baton; + apr_brigade_cleanup(sobj->body); + sobj->body = NULL; + return APR_SUCCESS; +} + static int open_entity(cache_handle_t *h, request_rec *r, const char *key) { cache_socache_dir_conf *dconf = @@ -463,6 +477,7 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key) * about for the lifetime of the response. */ apr_pool_create(&sobj->pool, r->pool); + apr_pool_tag(sobj->pool, "mod_cache_socache (open_entity)"); sobj->buffer = apr_palloc(sobj->pool, dconf->max); sobj->buffer_len = dconf->max; @@ -648,36 +663,25 @@ static int open_entity(cache_handle_t *h, request_rec *r, const char *key) } /* Retrieve the body if we have one */ - sobj->body = apr_brigade_create(r->pool, r->connection->bucket_alloc); len = buffer_len - slider; - - /* - * Optimisation: if the body is small, we want to make a - * copy of the body and free the temporary pool, as we - * don't want large blocks of unused memory hanging around - * to the end of the response. In contrast, if the body is - * large, we would rather leave the body where it is in the - * temporary pool, and save ourselves the copy. - */ - if (len * 2 > dconf->max) { + if (len > 0) { apr_bucket *e; - - /* large - use the brigade as is, we're done */ - e = apr_bucket_immortal_create((const char *) sobj->buffer + slider, - len, r->connection->bucket_alloc); - + /* Create the body brigade later concatenated to the output filters' + * brigade by recall_body(). Since sobj->buffer (the data) point to + * sobj->pool (a subpool of r->pool), be safe by using a pool bucket + * which can morph to heap if sobj->pool is destroyed while the bucket + * is still alive. But if sobj->pool gets destroyed while the bucket is + * still in sobj->body (i.e. recall_body() was never called), we don't + * need to morph to something just about to be freed, so a pre_cleanup + * will take care of cleaning up sobj->body before this happens (and is + * a noop otherwise). + */ + sobj->body = apr_brigade_create(sobj->pool, r->connection->bucket_alloc); + apr_pool_pre_cleanup_register(sobj->pool, sobj, sobj_body_pre_cleanup); + e = apr_bucket_pool_create((const char *) sobj->buffer + slider, len, + sobj->pool, r->connection->bucket_alloc); APR_BRIGADE_INSERT_TAIL(sobj->body, e); } - else { - - /* small - make a copy of the data... */ - apr_brigade_write(sobj->body, NULL, NULL, (const char *) sobj->buffer - + slider, len); - - /* ...and get rid of the large memory buffer */ - apr_pool_destroy(sobj->pool); - sobj->pool = NULL; - } /* make the configuration stick */ h->cache_obj = obj; @@ -766,13 +770,9 @@ static apr_status_t recall_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb) { cache_socache_object_t *sobj = (cache_socache_object_t*) h->cache_obj->vobj; - apr_bucket *e; - e = APR_BRIGADE_FIRST(sobj->body); - - if (e != APR_BRIGADE_SENTINEL(sobj->body)) { - APR_BUCKET_REMOVE(e); - APR_BRIGADE_INSERT_TAIL(bb, e); + if (sobj->body) { + APR_BRIGADE_CONCAT(bb, sobj->body); } return APR_SUCCESS; @@ -807,6 +807,7 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r, : obj->info.expire + dconf->mintime; apr_pool_create(&sobj->pool, r->pool); + apr_pool_tag(sobj->pool, "mod_cache_socache (store_headers)"); sobj->buffer = apr_palloc(sobj->pool, dconf->max); sobj->buffer_len = dconf->max; @@ -1051,7 +1052,8 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r, /* Was this the final bucket? If yes, perform sanity checks. */ if (seen_eos) { - const char *cl_header = apr_table_get(r->headers_out, "Content-Length"); + const char *cl_header; + apr_off_t cl; if (r->connection->aborted || r->no_cache) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02380) @@ -1062,18 +1064,16 @@ static apr_status_t store_body(cache_handle_t *h, request_rec *r, sobj->pool = NULL; return APR_EGENERAL; } - if (cl_header) { - apr_off_t cl; - char *cl_endp; - if (apr_strtoff(&cl, cl_header, &cl_endp, 10) != APR_SUCCESS - || *cl_endp != '\0' || cl != sobj->body_length) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02381) - "URL %s didn't receive complete response, not caching", - h->cache_obj->key); - apr_pool_destroy(sobj->pool); - sobj->pool = NULL; - return APR_EGENERAL; - } + + cl_header = apr_table_get(r->headers_out, "Content-Length"); + if (cl_header && (!ap_parse_strict_length(&cl, cl_header) + || cl != sobj->body_length)) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02381) + "URL %s didn't receive complete response, not caching", + h->cache_obj->key); + apr_pool_destroy(sobj->pool); + sobj->pool = NULL; + return APR_EGENERAL; } /* All checks were fine, we're good to go when the commit comes */ diff --git a/modules/cache/mod_file_cache.c b/modules/cache/mod_file_cache.c index 4199361..ce1db2d 100644 --- a/modules/cache/mod_file_cache.c +++ b/modules/cache/mod_file_cache.c @@ -380,7 +380,7 @@ static int file_cache_handler(request_rec *r) return rc; } -static command_rec file_cache_cmds[] = +static const command_rec file_cache_cmds[] = { AP_INIT_ITERATE("cachefile", cachefilehandle, NULL, RSRC_CONF, "A space separated list of files to add to the file handle cache at config time"), diff --git a/modules/cache/mod_socache_dbm.c b/modules/cache/mod_socache_dbm.c index 579d2ff..df97573 100644 --- a/modules/cache/mod_socache_dbm.c +++ b/modules/cache/mod_socache_dbm.c @@ -92,6 +92,7 @@ static const char *socache_dbm_create(ap_socache_instance_t **context, } apr_pool_create(&ctx->pool, p); + apr_pool_tag(ctx->pool, "socache_dbm_instance"); return NULL; } @@ -120,6 +121,10 @@ static apr_status_t socache_dbm_init(ap_socache_instance_t *ctx, const struct ap_socache_hints *hints, server_rec *s, apr_pool_t *p) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_status_t rv; @@ -141,6 +146,22 @@ static apr_status_t socache_dbm_init(ap_socache_instance_t *ctx, /* open it once to create it and to make sure it _can_ be created */ apr_pool_clear(ctx->pool); +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10277) + "Cannot load socache DBM library '%s': %s", + err->reason, err->msg); + return rv; + } + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, + APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00804) + "Cannot create socache DBM file `%s'", + ctx->data_file); + return DECLINED; + } +#else if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00804) @@ -148,6 +169,7 @@ static apr_status_t socache_dbm_init(ap_socache_instance_t *ctx, ctx->data_file); return rv; } +#endif apr_dbm_close(dbm); ctx->expiry_interval = (hints && hints->expiry_interval @@ -192,6 +214,10 @@ static apr_status_t socache_dbm_store(ap_socache_instance_t *ctx, unsigned char *ucaData, unsigned int nData, apr_pool_t *pool) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_datum_t dbmkey; apr_datum_t dbmval; @@ -227,6 +253,25 @@ static apr_status_t socache_dbm_store(ap_socache_instance_t *ctx, /* and store it to the DBM file */ apr_pool_clear(ctx->pool); +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10278) + "Cannot load socache DBM library '%s' (store): %s", + err->reason, err->msg); + free(dbmval.dptr); + return rv; + } + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, + APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00807) + "Cannot open socache DBM file `%s' for writing " + "(store)", + ctx->data_file); + free(dbmval.dptr); + return rv; + } +#else if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00807) @@ -236,6 +281,7 @@ static apr_status_t socache_dbm_store(ap_socache_instance_t *ctx, free(dbmval.dptr); return rv; } +#endif if ((rv = apr_dbm_store(dbm, dbmkey, dbmval)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00808) "Cannot store socache object to DBM file `%s'", @@ -260,6 +306,10 @@ static apr_status_t socache_dbm_retrieve(ap_socache_instance_t *ctx, server_rec unsigned char *dest, unsigned int *destlen, apr_pool_t *p) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_datum_t dbmkey; apr_datum_t dbmval; @@ -280,6 +330,23 @@ static apr_status_t socache_dbm_retrieve(ap_socache_instance_t *ctx, server_rec * do the apr_dbm_close? This would make the code a bit cleaner. */ apr_pool_clear(ctx->pool); +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10279) + "Cannot load socache DBM library '%s' (fetch): %s", + err->reason, err->msg); + return rc; + } + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, + APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, APLOGNO(00809) + "Cannot open socache DBM file `%s' for reading " + "(fetch)", + ctx->data_file); + return rc; + } +#else if ((rc = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rc, s, APLOGNO(00809) @@ -288,6 +355,7 @@ static apr_status_t socache_dbm_retrieve(ap_socache_instance_t *ctx, server_rec ctx->data_file); return rc; } +#endif rc = apr_dbm_fetch(dbm, dbmkey, &dbmval); if (rc != APR_SUCCESS) { apr_dbm_close(dbm); @@ -325,6 +393,10 @@ static apr_status_t socache_dbm_remove(ap_socache_instance_t *ctx, server_rec *s, const unsigned char *id, unsigned int idlen, apr_pool_t *p) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_datum_t dbmkey; apr_status_t rv; @@ -336,6 +408,23 @@ static apr_status_t socache_dbm_remove(ap_socache_instance_t *ctx, /* and delete it from the DBM file */ apr_pool_clear(ctx->pool); +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10280) + "Cannot load socache DBM library '%s' (delete): %s", + err->reason, err->msg); + return rv; + } + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, + APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00810) + "Cannot open socache DBM file `%s' for writing " + "(delete)", + ctx->data_file); + return rv; + } +#else if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00810) @@ -344,6 +433,7 @@ static apr_status_t socache_dbm_remove(ap_socache_instance_t *ctx, ctx->data_file); return rv; } +#endif apr_dbm_delete(dbm, dbmkey); apr_dbm_close(dbm); @@ -352,6 +442,10 @@ static apr_status_t socache_dbm_remove(ap_socache_instance_t *ctx, static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_datum_t dbmkey; apr_datum_t dbmval; @@ -377,6 +471,16 @@ static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) ctx->last_expiry = now; +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10281) + "Cannot load socache DBM library '%s' (expire): %s", + err->reason, err->msg); + return rv; + } +#endif + /* * Here we have to be very carefully: Not all DBM libraries are * smart enough to allow one to iterate over the elements and at the @@ -400,6 +504,16 @@ static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) /* pass 1: scan DBM database */ keyidx = 0; +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, APR_DBM_RWCREATE, + DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00811) + "Cannot open socache DBM file `%s' for " + "scanning", + ctx->data_file); + break; + } +#else if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00811) @@ -408,6 +522,7 @@ static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) ctx->data_file); break; } +#endif apr_dbm_firstkey(dbm, &dbmkey); while (dbmkey.dptr != NULL) { elts++; @@ -433,6 +548,16 @@ static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) apr_dbm_close(dbm); /* pass 2: delete expired elements */ +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if (apr_dbm_open2(&dbm, driver, ctx->data_file, APR_DBM_RWCREATE, + DBM_FILE_MODE, ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00812) + "Cannot re-open socache DBM file `%s' for " + "expiring", + ctx->data_file); + break; + } +#else if (apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00812) @@ -441,6 +566,7 @@ static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) ctx->data_file); break; } +#endif for (i = 0; i < keyidx; i++) { apr_dbm_delete(dbm, keylist[i]); deleted++; @@ -460,6 +586,10 @@ static void socache_dbm_expire(ap_socache_instance_t *ctx, server_rec *s) static void socache_dbm_status(ap_socache_instance_t *ctx, request_rec *r, int flags) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_datum_t dbmkey; apr_datum_t dbmval; @@ -472,14 +602,32 @@ static void socache_dbm_status(ap_socache_instance_t *ctx, request_rec *r, size = 0; apr_pool_clear(ctx->pool); +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(10282) + "Cannot load socache DBM library '%s' (status retrieval): %s", + err->reason, err->msg); + return; + } + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, APR_DBM_RWCREATE, + DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00814) + "Cannot open socache DBM file `%s' for status " + "retrieval", + ctx->data_file); + return; + } +#else if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(00814) "Cannot open socache DBM file `%s' for status " - "retrival", + "retrieval", ctx->data_file); return; } +#endif /* * XXX - Check the return value of apr_dbm_firstkey, apr_dbm_fetch - TBD */ @@ -515,6 +663,10 @@ static apr_status_t socache_dbm_iterate(ap_socache_instance_t *ctx, ap_socache_iterator_t *iterator, apr_pool_t *pool) { +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + const apr_dbm_driver_t *driver; + const apu_err_t *err; +#endif apr_dbm_t *dbm; apr_datum_t dbmkey; apr_datum_t dbmval; @@ -527,6 +679,22 @@ static apr_status_t socache_dbm_iterate(ap_socache_instance_t *ctx, * make sure the expired records are omitted */ now = apr_time_now(); +#if APU_MAJOR_VERSION > 1 || (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 7) + if ((rv = apr_dbm_get_driver(&driver, NULL, &err, + ctx->pool) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10283) + "Cannot load socache DBM library '%s' (iterating): %s", + err->reason, err->msg); + return rv; + } + if ((rv = apr_dbm_open2(&dbm, driver, ctx->data_file, APR_DBM_RWCREATE, + DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00815) + "Cannot open socache DBM file `%s' for " + "iterating", ctx->data_file); + return rv; + } +#else if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00815) @@ -534,6 +702,7 @@ static apr_status_t socache_dbm_iterate(ap_socache_instance_t *ctx, "iterating", ctx->data_file); return rv; } +#endif rv = apr_dbm_firstkey(dbm, &dbmkey); while (rv == APR_SUCCESS && dbmkey.dptr != NULL) { expired = FALSE; diff --git a/modules/cache/mod_socache_dc.c b/modules/cache/mod_socache_dc.c index c1d4ab8..1fc52a7 100644 --- a/modules/cache/mod_socache_dc.c +++ b/modules/cache/mod_socache_dc.c @@ -69,7 +69,7 @@ static apr_status_t socache_dc_init(ap_socache_instance_t *ctx, /* This mode of operation will open a temporary connection to the 'target' * for each cache operation - this makes it safe against fork() * automatically. This mode is preferred when running a local proxy (over - * unix domain sockets) because overhead is negligable and it reduces the + * unix domain sockets) because overhead is negligible and it reduces the * performance/stability danger of file-descriptor bloatage. */ #define SESSION_CTX_FLAGS 0 #endif diff --git a/modules/cache/mod_socache_memcache.c b/modules/cache/mod_socache_memcache.c index e943b9b..f122ba4 100644 --- a/modules/cache/mod_socache_memcache.c +++ b/modules/cache/mod_socache_memcache.c @@ -20,15 +20,6 @@ #include "http_protocol.h" #include "apr.h" -#include "apu_version.h" - -/* apr_memcache support requires >= 1.3 */ -#if APU_MAJOR_VERSION > 1 || \ - (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION > 2) -#define HAVE_APU_MEMCACHE 1 -#endif - -#ifdef HAVE_APU_MEMCACHE #include "ap_socache.h" #include "ap_mpm.h" @@ -371,8 +362,6 @@ static const ap_socache_provider_t socache_mc = { socache_mc_iterate }; -#endif /* HAVE_APU_MEMCACHE */ - static void *create_server_config(apr_pool_t *p, server_rec *s) { socache_mc_svr_cfg *sconf = apr_pcalloc(p, sizeof(socache_mc_svr_cfg)); @@ -407,11 +396,9 @@ static const char *socache_mc_set_ttl(cmd_parms *cmd, void *dummy, static void register_hooks(apr_pool_t *p) { -#ifdef HAVE_APU_MEMCACHE ap_register_provider(p, AP_SOCACHE_PROVIDER_GROUP, "memcache", AP_SOCACHE_PROVIDER_VERSION, &socache_mc); -#endif } static const command_rec socache_memcache_cmds[] = { diff --git a/modules/cache/mod_socache_redis.c b/modules/cache/mod_socache_redis.c new file mode 100644 index 0000000..450f406 --- /dev/null +++ b/modules/cache/mod_socache_redis.c @@ -0,0 +1,486 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "httpd.h" +#include "http_config.h" +#include "http_protocol.h" + +#include "apr.h" +#include "apu_version.h" + +#include "ap_socache.h" +#include "ap_mpm.h" +#include "http_log.h" +#include "apr_strings.h" +#include "mod_status.h" + +typedef struct { + apr_uint32_t ttl; + apr_uint32_t rwto; +} socache_rd_svr_cfg; + +/* apr_redis support requires >= 1.6 */ +#if APU_MAJOR_VERSION > 1 || \ + (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION > 5) +#define HAVE_APU_REDIS 1 +#endif + +/* The underlying apr_redis system is thread safe.. */ +#define RD_KEY_LEN 254 + +#ifndef RD_DEFAULT_SERVER_PORT +#define RD_DEFAULT_SERVER_PORT 6379 +#endif + + +#ifndef RD_DEFAULT_SERVER_MIN +#define RD_DEFAULT_SERVER_MIN 0 +#endif + +#ifndef RD_DEFAULT_SERVER_SMAX +#define RD_DEFAULT_SERVER_SMAX 1 +#endif + +#ifndef RD_DEFAULT_SERVER_TTL +#define RD_DEFAULT_SERVER_TTL apr_time_from_sec(15) +#endif + +#ifndef RD_DEFAULT_SERVER_RWTO +#define RD_DEFAULT_SERVER_RWTO apr_time_from_sec(5) +#endif + +module AP_MODULE_DECLARE_DATA socache_redis_module; + +#ifdef HAVE_APU_REDIS +#include "apr_redis.h" +struct ap_socache_instance_t { + const char *servers; + apr_redis_t *rc; + const char *tag; + apr_size_t taglen; /* strlen(tag) + 1 */ +}; + +static const char *socache_rd_create(ap_socache_instance_t **context, + const char *arg, + apr_pool_t *tmp, apr_pool_t *p) +{ + ap_socache_instance_t *ctx; + + *context = ctx = apr_pcalloc(p, sizeof *ctx); + + if (!arg || !*arg) { + return "List of server names required to create redis socache."; + } + + ctx->servers = apr_pstrdup(p, arg); + + return NULL; +} + +static apr_status_t socache_rd_init(ap_socache_instance_t *ctx, + const char *namespace, + const struct ap_socache_hints *hints, + server_rec *s, apr_pool_t *p) +{ + apr_status_t rv; + int thread_limit = 0; + apr_uint16_t nservers = 0; + char *cache_config; + char *split; + char *tok; + + socache_rd_svr_cfg *sconf = ap_get_module_config(s->module_config, + &socache_redis_module); + + ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); + + /* Find all the servers in the first run to get a total count */ + cache_config = apr_pstrdup(p, ctx->servers); + split = apr_strtok(cache_config, ",", &tok); + while (split) { + nservers++; + split = apr_strtok(NULL,",", &tok); + } + + rv = apr_redis_create(p, nservers, 0, &ctx->rc); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(03473) + "Failed to create Redis Object of '%d' size.", + nservers); + return rv; + } + + /* Now add each server to the redis */ + cache_config = apr_pstrdup(p, ctx->servers); + split = apr_strtok(cache_config, ",", &tok); + while (split) { + apr_redis_server_t *st; + char *host_str; + char *scope_id; + apr_port_t port; + + rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(03474) + "Failed to Parse redis Server: '%s'", split); + return rv; + } + + if (host_str == NULL) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(03475) + "Failed to Parse Server, " + "no hostname specified: '%s'", split); + return APR_EINVAL; + } + + if (port == 0) { + port = RD_DEFAULT_SERVER_PORT; + } + + rv = apr_redis_server_create(p, + host_str, port, + RD_DEFAULT_SERVER_MIN, + RD_DEFAULT_SERVER_SMAX, + thread_limit, + sconf->ttl, + sconf->rwto, + &st); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(03476) + "Failed to Create redis Server: %s:%d", + host_str, port); + return rv; + } + + rv = apr_redis_add_server(ctx->rc, st); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(03477) + "Failed to Add redis Server: %s:%d", + host_str, port); + return rv; + } + + split = apr_strtok(NULL,",", &tok); + } + + ctx->tag = apr_pstrcat(p, namespace, ":", NULL); + ctx->taglen = strlen(ctx->tag) + 1; + + /* socache API constraint: */ + AP_DEBUG_ASSERT(ctx->taglen <= 16); + + return APR_SUCCESS; +} + +static void socache_rd_destroy(ap_socache_instance_t *context, server_rec *s) +{ + /* noop. */ +} + +/* Converts (binary) id into a key prefixed by the predetermined + * namespace tag; writes output to key buffer. Returns non-zero if + * the id won't fit in the key buffer. */ +static int socache_rd_id2key(ap_socache_instance_t *ctx, + const unsigned char *id, unsigned int idlen, + char *key, apr_size_t keylen) +{ + char *cp; + + if (idlen * 2 + ctx->taglen >= keylen) + return 1; + + cp = apr_cpystrn(key, ctx->tag, ctx->taglen); + ap_bin2hex(id, idlen, cp); + + return 0; +} + +static apr_status_t socache_rd_store(ap_socache_instance_t *ctx, server_rec *s, + const unsigned char *id, unsigned int idlen, + apr_time_t expiry, + unsigned char *ucaData, unsigned int nData, + apr_pool_t *p) +{ + char buf[RD_KEY_LEN]; + apr_status_t rv; + apr_uint32_t timeout; + + if (socache_rd_id2key(ctx, id, idlen, buf, sizeof(buf))) { + return APR_EINVAL; + } + timeout = apr_time_sec(expiry - apr_time_now()); + if (timeout <= 0) { + return APR_EINVAL; + } + + rv = apr_redis_setex(ctx->rc, buf, (char*)ucaData, nData, timeout, 0); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, APLOGNO(03478) + "scache_rd: error setting key '%s' " + "with %d bytes of data", buf, nData); + return rv; + } + + return APR_SUCCESS; +} + +static apr_status_t socache_rd_retrieve(ap_socache_instance_t *ctx, server_rec *s, + const unsigned char *id, unsigned int idlen, + unsigned char *dest, unsigned int *destlen, + apr_pool_t *p) +{ + apr_size_t data_len; + char buf[RD_KEY_LEN], *data; + apr_status_t rv; + + if (socache_rd_id2key(ctx, id, idlen, buf, sizeof buf)) { + return APR_EINVAL; + } + + /* ### this could do with a subpool, but _getp looks like it will + * eat memory like it's going out of fashion anyway. */ + + rv = apr_redis_getp(ctx->rc, p, buf, &data, &data_len, NULL); + if (rv) { + if (rv != APR_NOTFOUND) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(03479) + "scache_rd: 'retrieve' FAIL"); + } + return rv; + } + else if (data_len > *destlen) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(03480) + "scache_rd: 'retrieve' OVERFLOW"); + return APR_ENOMEM; + } + + memcpy(dest, data, data_len); + *destlen = data_len; + + return APR_SUCCESS; +} + +static apr_status_t socache_rd_remove(ap_socache_instance_t *ctx, server_rec *s, + const unsigned char *id, + unsigned int idlen, apr_pool_t *p) +{ + char buf[RD_KEY_LEN]; + apr_status_t rv; + + if (socache_rd_id2key(ctx, id, idlen, buf, sizeof buf)) { + return APR_EINVAL; + } + + rv = apr_redis_delete(ctx->rc, buf, 0); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(03481) + "scache_rd: error deleting key '%s' ", + buf); + } + + return rv; +} + +static void socache_rd_status(ap_socache_instance_t *ctx, request_rec *r, int flags) +{ + apr_redis_t *rc = ctx->rc; + int i; + + for (i = 0; i < rc->ntotal; i++) { + apr_redis_server_t *rs; + apr_redis_stats_t *stats; + char *role; + apr_status_t rv; + char *br = (!(flags & AP_STATUS_SHORT) ? "<br />" : ""); + + rs = rc->live_servers[i]; + + ap_rprintf(r, "Redis server: %s:%d [%s]%s\n", rs->host, (int)rs->port, + (rs->status == APR_RC_SERVER_LIVE) ? "Up" : "Down", + br); + rv = apr_redis_stats(rs, r->pool, &stats); + if (rv != APR_SUCCESS) + continue; + if (!(flags & AP_STATUS_SHORT)) { + ap_rprintf(r, "<b>General::</b> Version: <i>%u.%u.%u</i> [%u bits], PID: <i>%u</i>, Uptime: <i>%u hrs</i> <br />\n", + stats->major, stats->minor, stats->patch, stats->arch_bits, + stats->process_id, stats->uptime_in_seconds/3600); + ap_rprintf(r, "<b>Clients::</b> Connected: <i>%d</i>, Blocked: <i>%d</i> <br />\n", + stats->connected_clients, stats->blocked_clients); + ap_rprintf(r, "<b>Memory::</b> Total: <i>%" APR_UINT64_T_FMT "</i>, Max: <i>%" APR_UINT64_T_FMT "</i>, Used: <i>%" APR_UINT64_T_FMT "</i> <br />\n", + stats->total_system_memory, stats->maxmemory, stats->used_memory); + ap_rprintf(r, "<b>CPU::</b> System: <i>%u</i>, User: <i>%u</i><br />\n", + stats->used_cpu_sys, stats->used_cpu_user ); + ap_rprintf(r, "<b>Connections::</b> Recd: <i>%" APR_UINT64_T_FMT "</i>, Processed: <i>%" APR_UINT64_T_FMT "</i>, Rejected: <i>%" APR_UINT64_T_FMT "</i> <br />\n", + stats->total_connections_received, stats->total_commands_processed, + stats->rejected_connections); + ap_rprintf(r, "<b>Cache::</b> Hits: <i>%" APR_UINT64_T_FMT "</i>, Misses: <i>%" APR_UINT64_T_FMT "</i> <br />\n", + stats->keyspace_hits, stats->keyspace_misses); + ap_rprintf(r, "<b>Net::</b> Input bytes: <i>%" APR_UINT64_T_FMT "</i>, Output bytes: <i>%" APR_UINT64_T_FMT "</i> <br />\n", + stats->total_net_input_bytes, stats->total_net_output_bytes); + if (stats->role == APR_RS_SERVER_MASTER) + role = "master"; + else if (stats->role == APR_RS_SERVER_SLAVE) + role = "slave"; + else + role = "unknown"; + ap_rprintf(r, "<b>Misc::</b> Role: <i>%s</i>, Connected Slaves: <i>%u</i>, Is Cluster?: <i>%s</i> \n", + role, stats->connected_clients, + (stats->cluster_enabled ? "yes" : "no")); + ap_rputs("<hr><br />\n", r); + } + else { + ap_rprintf(r, "Version: %u.%u.%u [%u bits], PID: %u, Uptime: %u hrs %s\n", + stats->major, stats->minor, stats->patch, stats->arch_bits, + stats->process_id, stats->uptime_in_seconds/3600, br); + ap_rprintf(r, "Clients:: Connected: %d, Blocked: %d %s\n", + stats->connected_clients, stats->blocked_clients, br); + ap_rprintf(r, "Memory:: Total: %" APR_UINT64_T_FMT ", Max: %" APR_UINT64_T_FMT ", Used: %" APR_UINT64_T_FMT " %s\n", + stats->total_system_memory, stats->maxmemory, stats->used_memory, + br); + ap_rprintf(r, "CPU:: System: %u, User: %u %s\n", + stats->used_cpu_sys, stats->used_cpu_user , br); + ap_rprintf(r, "Connections:: Recd: %" APR_UINT64_T_FMT ", Processed: %" APR_UINT64_T_FMT ", Rejected: %" APR_UINT64_T_FMT " %s\n", + stats->total_connections_received, stats->total_commands_processed, + stats->rejected_connections, br); + ap_rprintf(r, "Cache:: Hits: %" APR_UINT64_T_FMT ", Misses: %" APR_UINT64_T_FMT " %s\n", + stats->keyspace_hits, stats->keyspace_misses, br); + ap_rprintf(r, "Net:: Input bytes: %" APR_UINT64_T_FMT ", Output bytes: %" APR_UINT64_T_FMT " %s\n", + stats->total_net_input_bytes, stats->total_net_output_bytes, br); + if (stats->role == APR_RS_SERVER_MASTER) + role = "master"; + else if (stats->role == APR_RS_SERVER_SLAVE) + role = "slave"; + else + role = "unknown"; + ap_rprintf(r, "Misc:: Role: %s, Connected Slaves: %u, Is Cluster?: %s %s\n", + role, stats->connected_clients, + (stats->cluster_enabled ? "yes" : "no"), br); + } + } + +} + +static apr_status_t socache_rd_iterate(ap_socache_instance_t *instance, + server_rec *s, void *userctx, + ap_socache_iterator_t *iterator, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +static const ap_socache_provider_t socache_mc = { + "redis", + 0, + socache_rd_create, + socache_rd_init, + socache_rd_destroy, + socache_rd_store, + socache_rd_retrieve, + socache_rd_remove, + socache_rd_status, + socache_rd_iterate, +}; + +#endif /* HAVE_APU_REDIS */ + +static void* create_server_config(apr_pool_t* p, server_rec* s) +{ + socache_rd_svr_cfg *sconf = apr_palloc(p, sizeof(socache_rd_svr_cfg)); + + sconf->ttl = RD_DEFAULT_SERVER_TTL; + sconf->rwto = RD_DEFAULT_SERVER_RWTO; + + return sconf; +} + +static const char *socache_rd_set_ttl(cmd_parms *cmd, void *dummy, + const char *arg) +{ + apr_interval_time_t ttl; + socache_rd_svr_cfg *sconf = ap_get_module_config(cmd->server->module_config, + &socache_redis_module); + + if (ap_timeout_parameter_parse(arg, &ttl, "s") != APR_SUCCESS) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + " has wrong format", NULL); + } + + if ((ttl < apr_time_from_sec(0)) || (ttl > apr_time_from_sec(3600))) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + " can only be 0 or up to one hour.", NULL); + } + + /* apr_redis_server_create needs a ttl in usec. */ + sconf->ttl = ttl; + + return NULL; +} + +static const char *socache_rd_set_rwto(cmd_parms *cmd, void *dummy, + const char *arg) +{ + apr_interval_time_t rwto; + socache_rd_svr_cfg *sconf = ap_get_module_config(cmd->server->module_config, + &socache_redis_module); + + if (ap_timeout_parameter_parse(arg, &rwto, "s") != APR_SUCCESS) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + " has wrong format", NULL); + } + + if ((rwto < apr_time_from_sec(0)) || (rwto > apr_time_from_sec(3600))) { + return apr_pstrcat(cmd->pool, cmd->cmd->name, + " can only be 0 or up to one hour.", NULL); + } + + /* apr_redis_server_create needs a ttl in usec. */ + sconf->rwto = rwto; + + return NULL; +} + +static void register_hooks(apr_pool_t *p) +{ +#ifdef HAVE_APU_REDIS + + ap_register_provider(p, AP_SOCACHE_PROVIDER_GROUP, "redis", + AP_SOCACHE_PROVIDER_VERSION, + &socache_mc); +#endif +} + +static const command_rec socache_redis_cmds[] = +{ + AP_INIT_TAKE1("RedisConnPoolTTL", socache_rd_set_ttl, NULL, RSRC_CONF, + "TTL used for the connection pool with the Redis server(s)"), + AP_INIT_TAKE1("RedisTimeout", socache_rd_set_rwto, NULL, RSRC_CONF, + "R/W timeout used for the connection with the Redis server(s)"), + {NULL} +}; + +AP_DECLARE_MODULE(socache_redis) = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + create_server_config, /* create per-server config structures */ + NULL, /* merge per-server config structures */ + socache_redis_cmds, /* table of config file commands */ + register_hooks /* register hooks */ +}; + diff --git a/modules/cache/mod_socache_redis.dep b/modules/cache/mod_socache_redis.dep new file mode 100644 index 0000000..a450a54 --- /dev/null +++ b/modules/cache/mod_socache_redis.dep @@ -0,0 +1,5 @@ +# Microsoft Developer Studio Generated Dependency File, included by mod_socache_shmcb.mak + +..\..\build\win32\httpd.rc : \ + "..\..\include\ap_release.h"\ + diff --git a/modules/cache/mod_socache_redis.dsp b/modules/cache/mod_socache_redis.dsp new file mode 100644 index 0000000..18f5962 --- /dev/null +++ b/modules/cache/mod_socache_redis.dsp @@ -0,0 +1,111 @@ +# Microsoft Developer Studio Project File - Name="mod_socache_redis" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=mod_socache_redis - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mod_socache_redis.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mod_socache_redis.mak" CFG="mod_socache_redis - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mod_socache_redis - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "mod_socache_redis - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mod_socache_redis - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../generators" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Release\mod_socache_redis_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/mod_socache_redis.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_socache_redis.so" /d LONG_NAME="socache_redis module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_socache_redis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_socache_redis.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_socache_redis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_socache_redis.so /opt:ref
+# Begin Special Build Tool
+TargetPath=.\Release\mod_socache_redis.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "mod_socache_redis - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../generators" /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AAA_DECLARE_EXPORT" /Fd"Debug\mod_socache_redis_src" /FD /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/mod_socache_redis.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_socache_redis.so" /d LONG_NAME="socache_redis module for Apache"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_socache_redis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_socache_redis.so
+# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_socache_redis.so" /base:@..\..\os\win32\BaseAddr.ref,mod_socache_redis.so
+# Begin Special Build Tool
+TargetPath=.\Debug\mod_socache_redis.so
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "mod_socache_redis - Win32 Release"
+# Name "mod_socache_redis - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\mod_socache_redis.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\build\win32\httpd.rc
+# End Source File
+# End Target
+# End Project
diff --git a/modules/cache/mod_socache_redis.mak b/modules/cache/mod_socache_redis.mak new file mode 100644 index 0000000..e4aab37 --- /dev/null +++ b/modules/cache/mod_socache_redis.mak @@ -0,0 +1,353 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on mod_socache_redis.dsp +!IF "$(CFG)" == "" +CFG=mod_socache_redis - Win32 Debug +!MESSAGE No configuration specified. Defaulting to mod_socache_redis - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "mod_socache_redis - Win32 Release" && "$(CFG)" != "mod_socache_redis - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "mod_socache_redis.mak" CFG="mod_socache_redis - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "mod_socache_redis - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "mod_socache_redis - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "mod_socache_redis - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_socache_redis.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_socache_redis.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_socache_redis.obj" + -@erase "$(INTDIR)\mod_socache_redis.res" + -@erase "$(INTDIR)\mod_socache_redis_src.idb" + -@erase "$(INTDIR)\mod_socache_redis_src.pdb" + -@erase "$(OUTDIR)\mod_socache_redis.exp" + -@erase "$(OUTDIR)\mod_socache_redis.lib" + -@erase "$(OUTDIR)\mod_socache_redis.pdb" + -@erase "$(OUTDIR)\mod_socache_redis.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /Zi /O2 /Oy- /I "../../srclib/apr-util/include" /I "../../srclib/apr/include" /I "../../include" /I "../generators" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_socache_redis_src" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_socache_redis.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_socache_redis.so" /d LONG_NAME="socache_redis_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_socache_redis.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_socache_redis.pdb" /debug /out:"$(OUTDIR)\mod_socache_redis.so" /implib:"$(OUTDIR)\mod_socache_redis.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_socache_redis.so /opt:ref +LINK32_OBJS= \ + "$(INTDIR)\mod_socache_redis.obj" \ + "$(INTDIR)\mod_socache_redis.res" \ + "..\..\srclib\apr\Release\libapr-1.lib" \ + "..\..\srclib\apr-util\Release\libaprutil-1.lib" \ + "..\..\Release\libhttpd.lib" + +"$(OUTDIR)\mod_socache_redis.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Release\mod_socache_redis.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_socache_redis.so" + if exist .\Release\mod_socache_redis.so.manifest mt.exe -manifest .\Release\mod_socache_redis.so.manifest -outputresource:.\Release\mod_socache_redis.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "mod_socache_redis - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\mod_socache_redis.so" "$(DS_POSTBUILD_DEP)" + +!ELSE + +ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_socache_redis.so" "$(DS_POSTBUILD_DEP)" + +!ENDIF + +!IF "$(RECURSE)" == "1" +CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN" +!ELSE +CLEAN : +!ENDIF + -@erase "$(INTDIR)\mod_socache_redis.obj" + -@erase "$(INTDIR)\mod_socache_redis.res" + -@erase "$(INTDIR)\mod_socache_redis_src.idb" + -@erase "$(INTDIR)\mod_socache_redis_src.pdb" + -@erase "$(OUTDIR)\mod_socache_redis.exp" + -@erase "$(OUTDIR)\mod_socache_redis.lib" + -@erase "$(OUTDIR)\mod_socache_redis.pdb" + -@erase "$(OUTDIR)\mod_socache_redis.so" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Zi /Od /I "../../srclib/apr-util/include" /I "../../srclib/apr/include" /I "../../include" /I "../generators" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_socache_redis_src" /FD /EHsc /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\mod_socache_redis.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_socache_redis.so" /d LONG_NAME="socache_redis_module for Apache" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_socache_redis.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\mod_socache_redis.pdb" /debug /out:"$(OUTDIR)\mod_socache_redis.so" /implib:"$(OUTDIR)\mod_socache_redis.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_socache_redis.so +LINK32_OBJS= \ + "$(INTDIR)\mod_socache_redis.obj" \ + "$(INTDIR)\mod_socache_redis.res" \ + "..\..\srclib\apr\Debug\libapr-1.lib" \ + "..\..\srclib\apr-util\Debug\libaprutil-1.lib" \ + "..\..\Debug\libhttpd.lib" + +"$(OUTDIR)\mod_socache_redis.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +TargetPath=.\Debug\mod_socache_redis.so +SOURCE="$(InputPath)" +PostBuild_Desc=Embed .manifest +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +"$(DS_POSTBUILD_DEP)" : "$(OUTDIR)\mod_socache_redis.so" + if exist .\Debug\mod_socache_redis.so.manifest mt.exe -manifest .\Debug\mod_socache_redis.so.manifest -outputresource:.\Debug\mod_socache_redis.so;2 + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("mod_socache_redis.dep") +!INCLUDE "mod_socache_redis.dep" +!ELSE +!MESSAGE Warning: cannot find "mod_socache_redis.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "mod_socache_redis - Win32 Release" || "$(CFG)" == "mod_socache_redis - Win32 Debug" + +!IF "$(CFG)" == "mod_socache_redis - Win32 Release" + +"libapr - Win32 Release" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" + cd "..\..\modules\cache" + +"libapr - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\cache" + +!ELSEIF "$(CFG)" == "mod_socache_redis - Win32 Debug" + +"libapr - Win32 Debug" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" + cd "..\..\modules\cache" + +"libapr - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr" + $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\cache" + +!ENDIF + +!IF "$(CFG)" == "mod_socache_redis - Win32 Release" + +"libaprutil - Win32 Release" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" + cd "..\..\modules\cache" + +"libaprutil - Win32 ReleaseCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release" RECURSE=1 CLEAN + cd "..\..\modules\cache" + +!ELSEIF "$(CFG)" == "mod_socache_redis - Win32 Debug" + +"libaprutil - Win32 Debug" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" + cd "..\..\modules\cache" + +"libaprutil - Win32 DebugCLEAN" : + cd ".\..\..\srclib\apr-util" + $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug" RECURSE=1 CLEAN + cd "..\..\modules\cache" + +!ENDIF + +!IF "$(CFG)" == "mod_socache_redis - Win32 Release" + +"libhttpd - Win32 Release" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" + cd ".\modules\cache" + +"libhttpd - Win32 ReleaseCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release" RECURSE=1 CLEAN + cd ".\modules\cache" + +!ELSEIF "$(CFG)" == "mod_socache_redis - Win32 Debug" + +"libhttpd - Win32 Debug" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" + cd ".\modules\cache" + +"libhttpd - Win32 DebugCLEAN" : + cd ".\..\.." + $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug" RECURSE=1 CLEAN + cd ".\modules\cache" + +!ENDIF + +SOURCE=..\..\build\win32\httpd.rc + +!IF "$(CFG)" == "mod_socache_redis - Win32 Release" + + +"$(INTDIR)\mod_socache_redis.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_socache_redis.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "NDEBUG" /d BIN_NAME="mod_socache_redis.so" /d LONG_NAME="socache_redis_module for Apache" $(SOURCE) + + +!ELSEIF "$(CFG)" == "mod_socache_redis - Win32 Debug" + + +"$(INTDIR)\mod_socache_redis.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)\mod_socache_redis.res" /i "../../include" /i "../../srclib/apr/include" /i "../../build\win32" /d "_DEBUG" /d BIN_NAME="mod_socache_redis.so" /d LONG_NAME="socache_redis_module for Apache" $(SOURCE) + + +!ENDIF + +SOURCE=.\mod_socache_redis.c + +"$(INTDIR)\mod_socache_redis.obj" : $(SOURCE) "$(INTDIR)" + + + +!ENDIF + diff --git a/modules/cache/mod_socache_shmcb.c b/modules/cache/mod_socache_shmcb.c index 2750f25..1785839 100644 --- a/modules/cache/mod_socache_shmcb.c +++ b/modules/cache/mod_socache_shmcb.c @@ -105,6 +105,7 @@ typedef struct { } SHMCBIndex; struct ap_socache_instance_t { + apr_pool_t *pool; const char *data_file; apr_size_t shm_size; apr_shm_t *shm; @@ -295,6 +296,7 @@ static const char *socache_shmcb_create(ap_socache_instance_t **context, /* Allocate the context. */ *context = ctx = apr_pcalloc(p, sizeof *ctx); + ctx->pool = p; ctx->shm_size = 1024*512; /* 512KB */ @@ -340,6 +342,16 @@ static const char *socache_shmcb_create(ap_socache_instance_t **context, return NULL; } +static apr_status_t socache_shmcb_cleanup(void *arg) +{ + ap_socache_instance_t *ctx = arg; + if (ctx->shm) { + apr_shm_destroy(ctx->shm); + ctx->shm = NULL; + } + return APR_SUCCESS; +} + static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, const char *namespace, const struct ap_socache_hints *hints, @@ -368,8 +380,9 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, * above will return NULL for invalid paths. */ if (ctx->data_file == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00818) - "Could not use default path '%s' for shmcb socache", - ctx->data_file); + "Could not use anonymous shm for '%s' cache", + namespace); + ctx->shm = NULL; return APR_EINVAL; } @@ -384,8 +397,11 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00819) "Could not allocate shared memory segment for shmcb " "socache"); + ctx->shm = NULL; return rv; } + apr_pool_cleanup_register(ctx->pool, ctx, socache_shmcb_cleanup, + apr_pool_cleanup_null); shm_segment = apr_shm_baseaddr_get(ctx->shm); shm_segsize = apr_shm_size_get(ctx->shm); @@ -473,9 +489,8 @@ static apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx, static void socache_shmcb_destroy(ap_socache_instance_t *ctx, server_rec *s) { - if (ctx && ctx->shm) { - apr_shm_destroy(ctx->shm); - ctx->shm = NULL; + if (ctx) { + apr_pool_cleanup_run(ctx->pool, ctx, socache_shmcb_cleanup); } } @@ -778,7 +793,6 @@ static int shmcb_subcache_store(server_rec *s, SHMCBHeader *header, */ if (header->subcache_data_size - subcache->data_used < total_len || subcache->idx_used == header->index_num) { - unsigned int loop = 0; idx = SHMCB_INDEX(subcache, subcache->idx_pos); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00845) @@ -805,7 +819,6 @@ static int shmcb_subcache_store(server_rec *s, SHMCBHeader *header, header->stat_scrolled++; /* Loop admin */ idx = idx2; - loop++; } while (header->subcache_data_size - subcache->data_used < total_len); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00846) |