From 1d5a371a5c17ffde244fb62c14828c6c1a43930c Mon Sep 17 00:00:00 2001 From: Bill Stoddard Date: Sun, 3 Feb 2002 06:24:55 +0000 Subject: [PATCH] Support files for mod_disk_cache. Some tweaks to arguments on various hook calls. Still lots of cleanup work to do here... git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93196 13f79535-47bb-0310-9956-ffa450edef68 --- modules/experimental/cache_storage.c | 22 ++-- modules/experimental/cache_util.c | 180 +++++++++++++++++++++++++++ modules/experimental/mod_cache.c | 6 +- modules/experimental/mod_cache.h | 44 ++++++- modules/experimental/mod_mem_cache.c | 12 +- 5 files changed, 239 insertions(+), 25 deletions(-) diff --git a/modules/experimental/cache_storage.c b/modules/experimental/cache_storage.c index 1c3605d347..94f9345146 100644 --- a/modules/experimental/cache_storage.c +++ b/modules/experimental/cache_storage.c @@ -116,7 +116,7 @@ int cache_create_entity(request_rec *r, const char *types, char *url, apr_size_t key = cache_create_key(r); while (next) { type = ap_cache_tokstr(r->pool, next, &next); - switch (rv = cache_run_create_entity(h, type, key, size)) { + switch (rv = cache_run_create_entity(h, r, type, key, size)) { case OK: { cache->handle = h; return OK; @@ -171,7 +171,7 @@ int cache_select_url(request_rec *r, const char *types, char *url) while (next) { type = ap_cache_tokstr(r->pool, next, &next); - switch ((rv = cache_run_open_entity(cache->handle, type, key))) { + switch ((rv = cache_run_open_entity(cache->handle, r->pool, type, key))) { case OK: { info = &(cache->handle->cache_obj->info); /* XXX: @@ -209,10 +209,10 @@ apr_status_t cache_write_entity_headers(cache_handle_t *h, h->write_headers(h, r, info); return APR_SUCCESS; } -apr_status_t cache_write_entity_body(cache_handle_t *h, apr_bucket_brigade *b) +apr_status_t cache_write_entity_body(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b) { apr_status_t rv = APR_SUCCESS; - if (h->write_body(h, b) != OK) { + if (h->write_body(h, r, b) != OK) { } return rv; } @@ -229,9 +229,9 @@ apr_status_t cache_read_entity_headers(cache_handle_t *h, request_rec *r) return APR_SUCCESS; } -apr_status_t cache_read_entity_body(cache_handle_t *h, apr_bucket_brigade *b) +apr_status_t cache_read_entity_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *b) { - h->read_body(h, b); + h->read_body(h, p, b); return APR_SUCCESS; } @@ -240,13 +240,15 @@ const char* cache_create_key( request_rec *r ) return r->uri; } APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, create_entity, - (cache_handle_t *h, const char *type, + (cache_handle_t *h, request_rec *r, const char *type, const char *urlkey, apr_size_t len), - (h,type,urlkey,len),DECLINED) + (h, r, type,urlkey,len),DECLINED) APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, open_entity, - (cache_handle_t *h, const char *type, - const char *urlkey),(h,type,urlkey), + (cache_handle_t *h, apr_pool_t *p, const char *type, + const char *urlkey),(h,p,type,urlkey), DECLINED) APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(cache, CACHE, int, remove_url, (const char *type, const char *urlkey), (type,urlkey),OK,DECLINED) + + diff --git a/modules/experimental/cache_util.c b/modules/experimental/cache_util.c index 41186dd4ed..69b53f0919 100644 --- a/modules/experimental/cache_util.c +++ b/modules/experimental/cache_util.c @@ -209,3 +209,183 @@ const char *ap_cache_tokstr(apr_pool_t *p, const char *list, const char **str) return NULL; } + +/* + * XXX TODO: + * These functions were lifted from mod_proxy + * Consider putting them in APR or some other common accessable + * location. + */ +/* + * Converts apr_time_t hex digits to a time integer + */ +static apr_time_t ap_cache_hex2msec(const char *x) +{ + int i, ch; + apr_time_t j; + for (i = 0, j = 0; i < sizeof(j) * 2; i++) { + ch = x[i]; + j <<= 4; + if (apr_isdigit(ch)) + j |= ch - '0'; + else if (apr_isupper(ch)) + j |= ch - ('A' - 10); + else + j |= ch - ('a' - 10); + } + return j; +} + +/* + * Converts a time integer to apr_time_t hex digits + */ +static void ap_cache_msec2hex(apr_time_t j, char *y) +{ + int i, ch; + + for (i = (sizeof(j) * 2)-1; i >= 0; i--) { + ch = j & 0xF; + j >>= 4; + if (ch >= 10) + y[i] = ch + ('A' - 10); + else + y[i] = ch + '0'; + } + y[sizeof(j) * 2] = '\0'; +} + +int mkdir_structure(char *file, const char *root) +{ + + /* XXX TODO: Use APR to make a root directory. Do some sanity checking... */ + return 0; +} + +cache_info * create_cache_el(apr_pool_t *p, cache_handle_t *h, const char *name) +{ + cache_info *info = apr_pcalloc(p, sizeof(cache_info)); + memset(info, '\0', sizeof(cache_info)); + info->name = (char *)name; + return info; +} + +/* These two functions get and put state information into the data + * file for an ap_cache_el, this state information will be read + * and written transparent to clients of this module + */ +int file_cache_read_mydata(apr_file_t *fd, cache_info *info, request_rec *r) +{ + apr_status_t rv; + char urlbuff[1034]; + int urllen = sizeof(urlbuff); + int offset=0; + char * temp; + + if(!info->hdrsfile) { + return APR_NOTFOUND; + } + + /* read the data from the cache file */ + /* format + * date SP expire SP count CRLF + * dates are stored as hex seconds since 1970 + */ + rv = apr_file_gets(&urlbuff[0], urllen, fd); + if (rv != APR_SUCCESS) + { + return rv; + } + + if ((temp = strchr(&urlbuff[0], '\n')) != NULL) /* trim off new line character */ + *temp = '\0'; /* overlay it with the null terminator */ + + if (!apr_date_checkmask(urlbuff, "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&")) + { + return APR_EGENERAL; + } + + info->date = ap_cache_hex2msec(urlbuff + offset); + offset += (sizeof(info->date)*2) + 1; + info->expire = ap_cache_hex2msec(urlbuff + offset); + offset += (sizeof(info->expire)*2) + 1; + info->version = ap_cache_hex2msec(urlbuff + offset); + + /* check that we have the same URL */ + rv = apr_file_gets(&urlbuff[0], urllen, fd); + if (rv != APR_SUCCESS) + { + return rv; + } + + if ((temp = strchr(&urlbuff[0], '\n')) != NULL) /* trim off new line character */ + *temp = '\0'; /* overlay it with the null terminator */ + + if (strncmp(urlbuff, "X-NAME: ", 7) != 0) + { + return APR_EGENERAL; + } + if (strcmp(urlbuff + 8, info->name) != 0) + { + return APR_EGENERAL; + } + + return APR_SUCCESS; +} + +static void cache_hash(const char *it, char *val, int ndepth, int nlength) +{ + apr_md5_ctx_t context; + unsigned char digest[16]; + char tmp[22]; + int i, k, d; + unsigned int x; + static const char enc_table[64] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@"; + + apr_md5_init(&context); + apr_md5_update(&context, (const unsigned char *) it, strlen(it)); + apr_md5_final(digest, &context); + + /* encode 128 bits as 22 characters, using a modified uuencoding + * the encoding is 3 bytes -> 4 characters* i.e. 128 bits is + * 5 x 3 bytes + 1 byte -> 5 * 4 characters + 2 characters + */ + for (i = 0, k = 0; i < 15; i += 3) { + x = (digest[i] << 16) | (digest[i + 1] << 8) | digest[i + 2]; + tmp[k++] = enc_table[x >> 18]; + tmp[k++] = enc_table[(x >> 12) & 0x3f]; + tmp[k++] = enc_table[(x >> 6) & 0x3f]; + tmp[k++] = enc_table[x & 0x3f]; + } + + /* one byte left */ + x = digest[15]; + tmp[k++] = enc_table[x >> 2]; /* use up 6 bits */ + tmp[k++] = enc_table[(x << 4) & 0x3f]; + + /* now split into directory levels */ + for (i = k = d = 0; d < ndepth; ++d) { + memcpy(&val[i], &tmp[k], nlength); + k += nlength; + val[i + nlength] = '/'; + i += nlength + 1; + } + memcpy(&val[i], &tmp[k], 22 - k); + val[i + 22 - k] = '\0'; +} + +static char *generate_name(apr_pool_t *p, cache_handle_t *h, const char *name) +{ + char hashfile[66], *filebase; + cache_hash(name, hashfile, h->dirlevels, h->dirlength); + filebase = apr_pstrcat(p, h->root, "/", hashfile, "%s", NULL); + return filebase; +} +char *header_file(cache_handle_t *h, apr_pool_t *p, const char *name) +{ + return apr_psprintf(p, generate_name(p, h, name), CACHE_HEADER_SUFFIX); +} +char *data_file(cache_handle_t *h, apr_pool_t *p, const char *name) +{ + return apr_psprintf(p, generate_name(p, h, name), CACHE_DATA_SUFFIX); +} diff --git a/modules/experimental/mod_cache.c b/modules/experimental/mod_cache.c index 263f83650c..7dcf1ea587 100644 --- a/modules/experimental/mod_cache.c +++ b/modules/experimental/mod_cache.c @@ -321,7 +321,7 @@ static int cache_out_filter(ap_filter_t *f, apr_bucket_brigade *bb) * that stored headers and the entity body in seperate files. */ cache_read_entity_headers(cache->handle, r); - cache_read_entity_body(cache->handle, bb); + cache_read_entity_body(cache->handle, r->pool, bb); /* This filter is done once it has served up its content */ ap_remove_output_filter(f); @@ -423,7 +423,7 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in) /* pass the brigades into the cache, then pass them * up the filter stack */ - cache_write_entity_body(cache->handle, in); + cache_write_entity_body(cache->handle, r, in); return ap_pass_brigade(f->next, in); } @@ -706,7 +706,7 @@ static int cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in) * Write away header information to cache. */ cache_write_entity_headers(cache->handle, r, info); - cache_write_entity_body(cache->handle, in); + cache_write_entity_body(cache->handle, r, in); return ap_pass_brigade(f->next, in); } diff --git a/modules/experimental/mod_cache.h b/modules/experimental/mod_cache.h index 5399651d7b..7aef4a6843 100644 --- a/modules/experimental/mod_cache.h +++ b/modules/experimental/mod_cache.h @@ -114,6 +114,12 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif +/* Used by mod_disk_cache + * XXX: Perhaps these should be moved to a mod_disk_cache header + * file? + */ +#define CACHE_HEADER_SUFFIX ".header" +#define CACHE_DATA_SUFFIX ".data" /* default completion is 60% */ #define DEFAULT_CACHE_COMPLETION (60) @@ -167,6 +173,14 @@ struct cache_info { apr_time_t request_time; apr_time_t response_time; apr_size_t len; + + /* Field used by mod_disk_cache */ + char *datafile; /* where the data will go */ + char *hdrsfile; /* where the hdrs will go */ + char *name; + int version; /* update count of the file */ + apr_file_t *fd; /* pointer to apr_file_t structure for the data file */ + apr_off_t file_size; /* File size of the cached data file */ }; /* cache handle information */ @@ -178,6 +192,10 @@ struct cache_object { void *vobj; /* Opaque portion (specific to the cache implementation) of the cache object */ apr_size_t count; /* Number of body bytes written to the cache so far */ int complete; + /* Used by mod_disk_cache: name of the temporary file, + * used for cache element creation + */ + char *tempfile; }; typedef struct cache_handle cache_handle_t; @@ -185,9 +203,16 @@ struct cache_handle { cache_object_t *cache_obj; int (*remove_entity) (cache_handle_t *h); int (*write_headers)(cache_handle_t *h, request_rec *r, cache_info *i); - int (*write_body)(cache_handle_t *h, apr_bucket_brigade *b); + int (*write_body)(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b); int (*read_headers) (cache_handle_t *h, request_rec *r); - int (*read_body) (cache_handle_t *h, apr_bucket_brigade *bb); + int (*read_body) (cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb); + + /* These fields were added for mod_disk_cache but just + * use unnecessary storage in mod_mem_cache. + */ + const char *root; /* the location of the cache directory */ + int dirlevels; /* Number of levels of subdirectories */ + int dirlength; /* Length of subdirectory names */ }; /* per request cache information */ @@ -201,6 +226,13 @@ typedef struct { /* cache_util.c */ +cache_info *create_cache_el(apr_pool_t *p, cache_handle_t *h, const char *name); +char *data_file(cache_handle_t *h, apr_pool_t *p, const char *name); +char *header_file(cache_handle_t *h, apr_pool_t *p, const char *name); +int file_cache_read_mydata(apr_file_t *fd, cache_info *info, request_rec *r); +apr_time_t ap_cache_hex2msec(const char *x); +void ap_cache_msec2hex(apr_time_t j, char *y); + int ap_cache_request_is_conditional(request_rec *r); void ap_cache_reset_output_filters(request_rec *r); const char *ap_cache_get_cachetype(request_rec *r, cache_server_conf *conf, const char *url); @@ -221,10 +253,10 @@ int cache_select_url(request_rec *r, const char *types, char *url); const char* cache_create_key( request_rec*r ); apr_status_t cache_write_entity_headers(cache_handle_t *h, request_rec *r, cache_info *info); -apr_status_t cache_write_entity_body(cache_handle_t *h, apr_bucket_brigade *bb); +apr_status_t cache_write_entity_body(cache_handle_t *h, request_rec *r, apr_bucket_brigade *bb); apr_status_t cache_read_entity_headers(cache_handle_t *h, request_rec *r); -apr_status_t cache_read_entity_body(cache_handle_t *h, apr_bucket_brigade *bb); +apr_status_t cache_read_entity_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb); /* hooks */ @@ -251,10 +283,10 @@ apr_status_t cache_read_entity_body(cache_handle_t *h, apr_bucket_brigade *bb); #endif APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, create_entity, - (cache_handle_t *h, const char *type, + (cache_handle_t *h, request_rec *r, const char *type, const char *urlkey, apr_size_t len)) APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, open_entity, - (cache_handle_t *h, const char *type, + (cache_handle_t *h, apr_pool_t *p, const char *type, const char *urlkey)) APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, remove_url, (const char *type, const char *urlkey)) diff --git a/modules/experimental/mod_mem_cache.c b/modules/experimental/mod_mem_cache.c index 1616171679..a129df2d77 100644 --- a/modules/experimental/mod_mem_cache.c +++ b/modules/experimental/mod_mem_cache.c @@ -118,9 +118,9 @@ static mem_cache_conf *sconf; /* Forward declarations */ static int remove_entity(cache_handle_t *h); static int write_headers(cache_handle_t *h, request_rec *r, cache_info *i); -static int write_body(cache_handle_t *h, apr_bucket_brigade *b); +static int write_body(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b); static int read_headers(cache_handle_t *h, request_rec *r); -static int read_body(cache_handle_t *h, apr_bucket_brigade *bb); +static int read_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb); static void cleanup_cache_object(cache_object_t *obj) { @@ -222,7 +222,7 @@ static void *create_cache_config(apr_pool_t *p, server_rec *s) return sconf; } -static int create_entity(cache_handle_t *h, +static int create_entity(cache_handle_t *h, request_rec *r, const char *type, const char *key, apr_size_t len) @@ -311,7 +311,7 @@ static int create_entity(cache_handle_t *h, return OK; } -static int open_entity(cache_handle_t *h, const char *type, const char *key) +static int open_entity(cache_handle_t *h, apr_pool_t *p, const char *type, const char *key) { cache_object_t *obj; @@ -486,7 +486,7 @@ static int read_headers(cache_handle_t *h, request_rec *r) } -static int read_body(cache_handle_t *h, apr_bucket_brigade *bb) +static int read_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb) { apr_bucket *b; mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj; @@ -557,7 +557,7 @@ static int write_headers(cache_handle_t *h, request_rec *r, cache_info *info) return OK; } -static int write_body(cache_handle_t *h, apr_bucket_brigade *b) +static int write_body(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b) { apr_status_t rv; mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj; -- 2.40.0