From bb227c01e1127263a6e02ccff822e9e749f85a4b Mon Sep 17 00:00:00 2001 From: Ryan Bloom Date: Fri, 17 Nov 2000 18:33:33 +0000 Subject: [PATCH] First pass at a set of caching filters and handlers. This implements a working disk cache. There are a lot of improvements to be made to this, but this is a pretty good start to a dynamic cache. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86995 13f79535-47bb-0310-9956-ffa450edef68 --- modules/experimental/config.m4 | 2 + modules/experimental/mod_cache.c | 130 ++++++++++++++++++++ modules/experimental/mod_cache.h | 67 ++++++++++ modules/experimental/mod_disk_cache.c | 171 ++++++++++++++++++++++++++ 4 files changed, 370 insertions(+) create mode 100644 modules/experimental/mod_cache.c create mode 100644 modules/experimental/mod_cache.h create mode 100644 modules/experimental/mod_disk_cache.c diff --git a/modules/experimental/config.m4 b/modules/experimental/config.m4 index 665fc5db74..fcead70960 100644 --- a/modules/experimental/config.m4 +++ b/modules/experimental/config.m4 @@ -3,5 +3,7 @@ APACHE_MODPATH_INIT(experimental) APACHE_MODULE(mmap_static, memory mapped file caching, , , no) APACHE_MODULE(charset_lite, character set translation, , , no) +APACHE_MODULE(cache, dynamic file caching, , , no) +APACHE_MODULE(disk_cache, disk caching module, , , no) APACHE_MODPATH_FINISH diff --git a/modules/experimental/mod_cache.c b/modules/experimental/mod_cache.c new file mode 100644 index 0000000000..003156dc26 --- /dev/null +++ b/modules/experimental/mod_cache.c @@ -0,0 +1,130 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * Portions of this software are based upon public domain software + * originally written at the National Center for Supercomputing Applications, + * University of Illinois, Urbana-Champaign. + */ + +#include "apr_strings.h" +#include "ap_config.h" +#include "util_filter.h" +#include "httpd.h" +#include "http_config.h" +#include "http_request.h" +#include "http_core.h" +#include "http_protocol.h" +#include "http_log.h" +#include "http_main.h" +#include "util_script.h" +#include "http_core.h" +#include "mod_cache.h" +#include "ap_hooks.h" + +module MODULE_VAR_EXPORT cache_module; + +AP_HOOK_STRUCT( + AP_HOOK_LINK(serve_cache) + AP_HOOK_LINK(store_cache) +) + +AP_IMPLEMENT_HOOK_RUN_FIRST(int,serve_cache,(request_rec *r),(r),DECLINED) +AP_IMPLEMENT_HOOK_RUN_FIRST(int,store_cache,(request_rec *r, ap_bucket_brigade *bb, void **cf), + (r, bb, cf),DECLINED) + +static int cache_handler(request_rec *r) +{ + /* I am sure there is common error checking that belongs in this function, + * but I'm not sure what it is. + */ + return ap_run_serve_cache(r); +} + +typedef struct cache_struct { + void *cf; +} cache_struct; + +static int cache_filter(ap_filter_t *f, ap_bucket_brigade *bb) +{ + cache_struct *ctx = f->ctx; + + if (ctx == NULL) { + f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx)); + } + + ap_run_store_cache(f->r, bb, &ctx->cf); + ap_pass_brigade(f->next, bb); + return APR_SUCCESS; +} + +static void cache_register_hook(void) +{ + ap_register_output_filter("CACHE", cache_filter, AP_FTYPE_HTTP_HEADER); +} + +static const handler_rec cache_handlers[] = +{ + {"*/*", cache_handler}, + {NULL} +}; + +module MODULE_VAR_EXPORT cache_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + NULL, /* command apr_table_t */ + cache_handlers, /* handlers */ + cache_register_hook /* register hooks */ +}; diff --git a/modules/experimental/mod_cache.h b/modules/experimental/mod_cache.h new file mode 100644 index 0000000000..81a4d37512 --- /dev/null +++ b/modules/experimental/mod_cache.h @@ -0,0 +1,67 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * Portions of this software are based upon public domain software + * originally written at the National Center for Supercomputing Applications, + * University of Illinois, Urbana-Champaign. + */ + +#include "ap_buckets.h" +#include "ap_hooks.h" +#include "httpd.h" + +typedef struct cache_funcs cache_funcs; + +AP_DECLARE_HOOK(int,serve_cache,(request_rec *r)); +AP_DECLARE_HOOK(int,store_cache,(request_rec *r, ap_bucket_brigade *bb, void **cf)); + diff --git a/modules/experimental/mod_disk_cache.c b/modules/experimental/mod_disk_cache.c new file mode 100644 index 0000000000..f0c916530e --- /dev/null +++ b/modules/experimental/mod_disk_cache.c @@ -0,0 +1,171 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" must + * not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * nor may "Apache" appear in their name, without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * Portions of this software are based upon public domain software + * originally written at the National Center for Supercomputing Applications, + * University of Illinois, Urbana-Champaign. + */ + +#include "mod_cache.h" +#include "apr_file_io.h" +#include "apr_strings.h" +#include "http_config.h" +#include "http_log.h" +#include "util_filter.h" + +module MODULE_VAR_EXPORT disk_cache_module; + +static int disk_serve(request_rec *r) +{ + ap_bucket *e; + ap_bucket_brigade *bb = ap_brigade_create(r->pool); + const char *filename; + apr_file_t *fd = NULL; + apr_status_t rv; + ap_filter_t *f; + char str[256]; + apr_off_t offset = 0; + + filename = ap_server_root_relative(r->pool, + apr_pstrcat(r->pool, "proxy", r->uri, NULL)); + if ((rv = apr_open(&fd, filename, APR_READ, + APR_UREAD, r->connection->pool)) != APR_SUCCESS) { + return DECLINED; + } + + /* skip the cached headers. */ + do { + apr_fgets(str, 256, fd); + offset += strlen(str); + } while (strcmp(str, CRLF)); + + /* If we are serving from the cache, we don't want to try to cache it + * again. + */ + for ((f = r->output_filters); (f = f->next);) { + if (!strcmp(f->frec->name, "CACHE")) { + ap_remove_output_filter(f); + } + } + + e = ap_bucket_create_file(fd, offset, r->finfo.size); + + AP_BRIGADE_INSERT_HEAD(bb, e); + e = ap_bucket_create_eos(); + AP_BRIGADE_INSERT_TAIL(bb, e); + + ap_pass_brigade(r->output_filters, bb); + return OK; +} + +typedef struct cache_struct { + const char *filename; + apr_file_t *fd; + int state; +} cache_struct; + +static int disk_cache(request_rec *r, ap_bucket_brigade *bb, void **cf) +{ + cache_struct *ctx = *cf; + ap_bucket *e; + + if (ctx == NULL) { + *cf = ctx = apr_pcalloc(r->pool, sizeof(*ctx)); + } + if (ctx->filename == NULL) { + apr_status_t rv; + apr_make_dir(ap_server_root_relative(r->pool, "proxy"), APR_UREAD | APR_UWRITE | APR_UEXECUTE | APR_GREAD | APR_GWRITE, r->pool); + + /* currently, we are using the uri as the cache key. This is + * probably wrong, but it is much better than a hard-coded filename. + */ + ctx->filename = ap_server_root_relative(r->pool, + apr_pstrcat(r->pool, "proxy", r->uri, NULL)); + if ((rv = apr_open(&ctx->fd, ctx->filename, + APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, + APR_UREAD | APR_UWRITE, r->pool)) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "Could not create cache file"); + *cf = NULL; + return DECLINED; + } + } + AP_BRIGADE_FOREACH(e, bb) { + const char *str; + apr_ssize_t length; + + ap_bucket_read(e, &str, &length, 0); + apr_write(ctx->fd, str, &length); + } + if (AP_BUCKET_IS_EOS(AP_BRIGADE_LAST(bb))) { + apr_close(ctx->fd); + } + return OK; +} + +static void disk_cache_register_hook(void) +{ + ap_hook_store_cache(disk_cache, NULL, NULL, AP_HOOK_MIDDLE); + ap_hook_serve_cache(disk_serve, NULL, NULL, AP_HOOK_MIDDLE); +} + +module MODULE_VAR_EXPORT disk_cache_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + NULL, /* command apr_table_t */ + NULL, /* handlers */ + disk_cache_register_hook /* register hooks */ +}; -- 2.50.1