summaryrefslogtreecommitdiffstats
path: root/modules/cache
diff options
context:
space:
mode:
Diffstat (limited to 'modules/cache')
-rw-r--r--modules/cache/cache_storage.c5
-rw-r--r--modules/cache/cache_util.c2
-rw-r--r--modules/cache/config.m41
-rw-r--r--modules/cache/mod_cache.c27
-rw-r--r--modules/cache/mod_cache_disk.c41
-rw-r--r--modules/cache/mod_cache_socache.c98
-rw-r--r--modules/cache/mod_file_cache.c2
-rw-r--r--modules/cache/mod_socache_dbm.c171
-rw-r--r--modules/cache/mod_socache_dc.c2
-rw-r--r--modules/cache/mod_socache_memcache.c13
-rw-r--r--modules/cache/mod_socache_redis.c486
-rw-r--r--modules/cache/mod_socache_redis.dep5
-rw-r--r--modules/cache/mod_socache_redis.dsp111
-rw-r--r--modules/cache/mod_socache_redis.mak353
-rw-r--r--modules/cache/mod_socache_shmcb.c27
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)