You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dirk-Willem van Gulik <di...@webweaving.org> on 1999/04/05 19:44:51 UTC

[patch] proxy child management / needless forks

At some moment in the past; this has crept in. We are
forking off a garbage collector after each and every request 
prior to checking if that is actually useful.

See proposed patch. I am not entirely familiar with this;
so cry faul if there was a reason behind this. Otherwise I'll
comit this later today.

Note that there is a bit of a catch; I mark the .time file
prior to being sure that I can actually fork and all that.

Dw.


Index: proxy_cache.c
===================================================================
RCS file: /x3/home/cvs/apache-1.3/src/modules/proxy/proxy_cache.c,v
retrieving revision 1.56
diff -u -r1.56 proxy_cache.c
--- proxy_cache.c	1999/03/23 14:48:09	1.56
+++ proxy_cache.c	1999/04/05 17:41:13
@@ -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();
 
@@ -264,27 +268,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 +294,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;