dirkx 99/04/08 13:27:46
Modified: src/modules/proxy proxy_cache.c Log: Modified cache garbage control to first check if it actually should run, based on the time of last run, and to try to get a lock; prior to actually forking and doing the real cleanup. This effectively avoids a fork after each and every request; and limites the spawning to just once every few hours. Revision Changes Path 1.57 +77 -46 apache-1.3/src/modules/proxy/proxy_cache.c Index: proxy_cache.c =================================================================== RCS file: /x3/home/cvs/apache-1.3/src/modules/proxy/proxy_cache.c,v retrieving revision 1.56 retrieving revision 1.57 diff -u -r1.56 -r1.57 --- proxy_cache.c 1999/03/23 14:48:09 1.56 +++ proxy_cache.c 1999/04/08 20:27:44 1.57 @@ -102,7 +102,7 @@ #define ROUNDUP2BLOCKS(_bytes) (((_bytes)+block_size-1) & ~(block_size-1)) static long block_size = 512; /* this must be a power of 2 */ static long61_t curbytes, cachesize; -static time_t every, garbage_now, garbage_expire; +static time_t garbage_now, garbage_expire; static char *filename; static mutex *garbage_mutex = NULL; @@ -119,6 +119,7 @@ static int sub_garbage_coll(request_rec *r, array_header *files, const char *cachedir, const char *cachesubdir); static void help_proxy_garbage_coll(request_rec *r); +static int should_proxy_garbage_coll(request_rec *r); #if !defined(WIN32) && !defined(MPE) && !defined(OS2) static void detached_proxy_garbage_coll(request_rec *r); #endif @@ -138,10 +139,11 @@ (void) ap_release_mutex(garbage_mutex); ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */ + if (should_proxy_garbage_coll(r)) #if !defined(WIN32) && !defined(MPE) && !defined(OS2) - detached_proxy_garbage_coll(r); + detached_proxy_garbage_coll(r); #else - help_proxy_garbage_coll(r); + help_proxy_garbage_coll(r); #endif ap_unblock_alarms(); @@ -205,6 +207,10 @@ int status; pid_t pgrp; +#if 0 + ap_log_error(APLOG_MARK, APLOG_DEBUG, r->server, + "proxy: Guess what; we fork() again..."); +#endif switch (pid = fork()) { case -1: ap_log_error(APLOG_MARK, APLOG_ERR, r->server, @@ -264,27 +270,25 @@ } #endif /* ndef WIN32 */ -static void help_proxy_garbage_coll(request_rec *r) +#define DOT_TIME "/.time" /* marker */ + +static int should_proxy_garbage_coll(request_rec *r) { - const char *cachedir; void *sconf = r->server->module_config; proxy_server_conf *pconf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); const struct cache_conf *conf = &pconf->cache; - array_header *files; - struct stat buf; - struct gc_ent *fent; - int i, timefd; - static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */ - cachedir = conf->root; - /* configured size is given in kB. Make it bytes, convert to long61_t: */ - cachesize.lower = cachesize.upper = 0; - add_long61(&cachesize, conf->space << 10); - every = conf->gcinterval; + const char *cachedir = conf->root; + char filename[ strlen(cachedir) + strlen( DOT_TIME ) +1]; + struct stat buf; + int timefd; + time_t every = conf->gcinterval; + static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */ if (cachedir == NULL || every == -1) - return; + return 0; + garbage_now = time(NULL); /* Usually, the modification time of <cachedir>/.time can only increase. * Thus, even with several child processes having their own copy of @@ -292,41 +296,68 @@ * for GC yet. */ if (garbage_now != -1 && lastcheck != BAD_DATE && garbage_now < lastcheck + every) - return; + return 0; - ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */ + strcpy(filename,cachedir); + strcat(filename,DOT_TIME); - filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2); - strcpy(filename, cachedir); - strcat(filename, "/.time"); - if (stat(filename, &buf) == -1) { /* does not exist */ - if (errno != ENOENT) { - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "proxy: stat(%s)", filename); - ap_unblock_alarms(); - return; - } - if ((timefd = creat(filename, 0666)) == -1) { - if (errno != EEXIST) - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "proxy: creat(%s)", filename); - else - lastcheck = garbage_now; /* someone else got in there */ - ap_unblock_alarms(); - return; - } - close(timefd); + /* At this point we have a bit of an engineering compromise. We could either + * create and/or mark the .time file (prior to the fork which might + * fail on a resource issue) or wait until we are safely forked. The + * advantage of doing it now in this process is that we get some + * usefull live out of the global last check variable. (XXX which + * should go scoreboard IMHO.) Note that the actual counting is + * at a later moment. + */ + if (stat(filename, &buf) == -1) { /* does not exist */ + if (errno != ENOENT) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: stat(%s)", filename); + return 0; + } + if ((timefd = creat(filename, 0666)) == -1) { + if (errno != EEXIST) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: creat(%s)", filename); + else + lastcheck = garbage_now; /* someone else got in there */ + return 0; + } + close(timefd); } else { - lastcheck = buf.st_mtime; /* save the time */ - if (garbage_now < lastcheck + every) { - ap_unblock_alarms(); - return; - } - if (utime(filename, NULL) == -1) - ap_log_error(APLOG_MARK, APLOG_ERR, r->server, - "proxy: utimes(%s)", filename); + lastcheck = buf.st_mtime; /* save the time */ + if (garbage_now < lastcheck + every) { + ap_unblock_alarms(); + return 0; + } + if (utime(filename, NULL) == -1) + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: utimes(%s)", filename); } + + return 1; +} + +static void help_proxy_garbage_coll(request_rec *r) +{ + const char *cachedir; + void *sconf = r->server->module_config; + proxy_server_conf *pconf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + const struct cache_conf *conf = &pconf->cache; + array_header *files; + struct gc_ent *fent; + int i; + char filename[ strlen(cachedir) + HASH_LEN + 2]; + + cachedir = conf->root; + /* configured size is given in kB. Make it bytes, convert to long61_t: */ + cachesize.lower = cachesize.upper = 0; + add_long61(&cachesize, conf->space << 10); + + ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */ + files = ap_make_array(r->pool, 100, sizeof(struct gc_ent)); curbytes.upper = curbytes.lower = 0L;