On Mon, Aug 08, 2005 at 12:04:44AM +0100, Colm MacCarthaigh wrote:
> Well that's a pretty each race to solve within httpd. It won't be able
> to create the headers, or the body. The patch I've submitted cleans up
> that slight race. The file won't be cached on that serve, but I don't
> think that's a big deal :-)

And since nothing says it like code, here's a patch to htcacheclean
which adds a -t option to clean out empty directories.

-- 
Colm MacCárthaigh                        Public Key: [EMAIL PROTECTED]
Index: docs/man/htcacheclean.8
===================================================================
--- docs/man/htcacheclean.8     (revision 230717)
+++ docs/man/htcacheclean.8     (working copy)
@@ -19,7 +19,7 @@
 .el .ne 3
 .IP "\\$1" \\$2
 ..
-.TH "HTCACHECLEAN" 8 "2004-11-10" "Apache HTTP Server" "htcacheclean"
+.TH "HTCACHECLEAN" 8 "2005-08-08" "Apache HTTP Server" "htcacheclean"
 
 .SH NAME
 htcacheclean \- Clean up the disk cache
@@ -27,10 +27,10 @@
 .SH "SYNOPSIS"
  
 .PP
-\fBhtcacheclean\fR [ -\fBD\fR ] [ -\fBv\fR ] [ -\fBr\fR ] [ -\fBn\fR ] 
-\fBp\fR\fIpath\fR -\fBl\fR\fIlimit\fR
+\fBhtcacheclean\fR [ -\fBD\fR ] [ -\fBv\fR ] [ -\fBt\fR ] [ -\fBr\fR ] [ 
-\fBn\fR ] -\fBp\fR\fIpath\fR -\fBl\fR\fIlimit\fR
  
 .PP
-\fBhtcacheclean\fR -\fBb\fR [ -\fBn\fR ] [ -\fBi\fR ] -\fBd\fR\fIinterval\fR 
-\fBp\fR\fIpath\fR -\fBl\fR\fIlimit\fR
+\fBhtcacheclean\fR -\fBb\fR [ -\fBn\fR ] [ -\fBt\fR ] [ -\fBi\fR ] 
-\fBd\fR\fIinterval\fR -\fBp\fR\fIpath\fR -\fBl\fR\fIlimit\fR
  
 
 .SH "SUMMARY"
@@ -53,11 +53,14 @@
 Be verbose and print statistics\&. This option is mutually exclusive with the 
-d option\&.  
 .TP
 -r
-Clean thoroughly\&. This assumes that the Apache web server is not running 
(otherwise you may get garbage in the cache)\&. This option is mutually 
exclusive with the -d option\&.  
+Clean thoroughly\&. This assumes that the Apache web server is not running 
(otherwise you may get garbage in the cache)\&. This option is mutually 
exclusive with the -d option and implies the -t option\&.  
 .TP
 -n
 Be nice\&. This causes slower processing in favour of other processes\&. 
htcacheclean will sleep from time to time so that (a) the disk IO will be 
delayed and (b) the kernel can schedule other processes in the meantime\&.  
 .TP
+-t
+Delete all empty directories\&. By default only cache files are removed, 
however with some configurations the large number of directories created may 
require attention\&. If your configuration requires a very large number of 
directories, to the point that inode or file allocation table exhaustion may 
become an issue, use of this option is advised\&.  
+.TP
 -p\fIpath\fR
 Specify \fIpath\fR as the root directory of the disk cache\&. This should be 
the same value as specified with the CacheRoot directive\&.  
 .TP
Index: docs/manual/programs/htcacheclean.html.en
===================================================================
--- docs/manual/programs/htcacheclean.html.en   (revision 230717)
+++ docs/manual/programs/htcacheclean.html.en   (working copy)
@@ -39,6 +39,7 @@
     <p><code><strong>htcacheclean</strong>
     [ -<strong>D</strong> ]
     [ -<strong>v</strong> ]
+    [ -<strong>t</strong> ]
     [ -<strong>r</strong> ]
     [ -<strong>n</strong> ]
     -<strong>p</strong><var>path</var>
@@ -46,6 +47,7 @@
 
     <p><code><strong>htcacheclean</strong> -<strong>b</strong>
     [ -<strong>n</strong> ]
+    [ -<strong>t</strong> ]
     [ -<strong>i</strong> ]
     -<strong>d</strong><var>interval</var>
     -<strong>p</strong><var>path</var>
@@ -71,7 +73,8 @@
     <dt><code>-r</code></dt>
     <dd>Clean thoroughly. This assumes that the Apache web server is
     not running (otherwise you may get garbage in the cache). This option
-    is mutually exclusive with the <code>-d</code> option.</dd>
+    is mutually exclusive with the <code>-d</code> option and implies
+    the <code>-t</code> option.</dd>
 
     <dt><code>-n</code></dt>
     <dd>Be nice. This causes slower processing in favour of other
@@ -79,6 +82,14 @@
     so that (a) the disk IO will be delayed and (b) the kernel can schedule
     other processes in the meantime.</dd>
 
+    <dt><code>-t</code></dt>
+    <dd>Delete all empty directories. By default only cache files are
+    removed, however with some configurations the large number of
+    directories created may require attention. If your configuration
+    requires a very large number of directories, to the point that
+    inode or file allocation table exhaustion may become an issue, use 
+    of this option is advised.</dd>
+
     <dt><code>-p<var>path</var></code></dt>
     <dd>Specify <var>path</var> as the root directory of the disk cache. This
     should be the same value as specified with the <code class="directive"><a 
href="../mod/mod_disk_cache.html#cacheroot">CacheRoot</a></code> directive.</dd>
Index: docs/manual/programs/htcacheclean.xml
===================================================================
--- docs/manual/programs/htcacheclean.xml       (revision 230717)
+++ docs/manual/programs/htcacheclean.xml       (working copy)
@@ -39,6 +39,7 @@
     <p><code><strong>htcacheclean</strong>
     [ -<strong>D</strong> ]
     [ -<strong>v</strong> ]
+    [ -<strong>t</strong> ]
     [ -<strong>r</strong> ]
     [ -<strong>n</strong> ]
     -<strong>p</strong><var>path</var>
@@ -46,6 +47,7 @@
 
     <p><code><strong>htcacheclean</strong> -<strong>b</strong>
     [ -<strong>n</strong> ]
+    [ -<strong>t</strong> ]
     [ -<strong>i</strong> ]
     -<strong>d</strong><var>interval</var>
     -<strong>p</strong><var>path</var>
@@ -71,7 +73,8 @@
     <dt><code>-r</code></dt>
     <dd>Clean thoroughly. This assumes that the Apache web server is
     not running (otherwise you may get garbage in the cache). This option
-    is mutually exclusive with the <code>-d</code> option.</dd>
+    is mutually exclusive with the <code>-d</code> option and implies
+    the <code>-t</code> option.</dd>
 
     <dt><code>-n</code></dt>
     <dd>Be nice. This causes slower processing in favour of other
@@ -79,6 +82,14 @@
     so that (a) the disk IO will be delayed and (b) the kernel can schedule
     other processes in the meantime.</dd>
 
+    <dt><code>-t</code></dt>
+    <dd>Delete all empty directories. By default only cache files are
+    removed, however with some configurations the large number of
+    directories created may require attention. If your configuration
+    requires a very large number of directories, to the point that
+    inode or file allocation table exhaustion may become an issue, use 
+    of this option is advised.</dd>
+
     <dt><code>-p<var>path</var></code></dt>
     <dd>Specify <var>path</var> as the root directory of the disk cache. This
     should be the same value as specified with the <directive
Index: support/htcacheclean.c
===================================================================
--- support/htcacheclean.c      (revision 230717)
+++ support/htcacheclean.c      (working copy)
@@ -143,6 +143,7 @@
 static int benice;      /* flag: true means nice mode is activated */
 static int dryrun;      /* flag: true means dry run, don't actually delete
                                  anything */
+static int deldirs;     /* flag: true means directories should be deleted */
 static int baselen;     /* string length of the path to the proxy directory */
 static apr_time_t now;  /* start time of this processing run */
 
@@ -319,6 +320,32 @@
 }
 
 /*
+ * Determine if a directory is empty
+ */
+static int directory_empty(char *path, apr_pool_t *pool)
+{
+    apr_dir_t *dir;
+    apr_finfo_t info;
+    
+    if (apr_dir_open(&dir, path, pool) != APR_SUCCESS) {
+        return 0;
+    }
+
+    while (apr_dir_read(&info, 0, dir) == APR_SUCCESS && !interrupted) {
+        if (!strcmp(info.name, ".") || !strcmp(info.name, "..")) {
+            continue;
+        }
+        
+        /* If we're here, the directory is not empty */
+        apr_dir_close(dir);
+        return 0;
+    }
+
+    apr_dir_close(dir);
+    return 1;
+}
+
+/*
  * walk the cache directory tree
  */
 static int process_dir(char *path, apr_pool_t *pool)
@@ -332,7 +359,7 @@
     apr_finfo_t info;
     apr_size_t len;
     apr_time_t current, deviation;
-    char *nextpath, *base, *ext;
+    char *nextpath, *base, *ext, *orig_basename;
     APR_RING_ENTRY(_direntry) anchor;
     DIRENTRY *d, *t, *n;
     ENTRY *e;
@@ -413,9 +440,18 @@
         }
 
         if (info.filetype == APR_DIR) {
+            /* Make a copy of the basename, as process_dir modifies it */
+            orig_basename = apr_pstrdup(pool, d->basename);
             if (process_dir(d->basename, pool)) {
                 return 1;
             }
+           
+            /* If, after processing this directory, it is empty. Delete the
+             * directory also. 
+             */
+            if (deldirs && !dryrun && directory_empty(orig_basename, pool)) {
+                apr_dir_remove(orig_basename, pool);
+            }
             continue;
         }
 
@@ -740,8 +776,8 @@
 {
     apr_file_printf(errfile,
     "%s -- program for cleaning the disk cache."                             NL
-    "Usage: %s [-Dvrn] -pPATH -lLIMIT"                                       NL
-    "       %s [-ni] -dINTERVAL -pPATH -lLIMIT"                              NL
+    "Usage: %s [-Dvtrn] -pPATH -lLIMIT"                                      NL
+    "       %s [-nti] -dINTERVAL -pPATH -lLIMIT"                             NL
                                                                              NL
     "Options:"                                                               NL
     "  -d   Daemonize and repeat cache cleaning every INTERVAL minutes."     NL
@@ -756,11 +792,15 @@
                                                                              NL
     "  -r   Clean thoroughly. This assumes that the Apache web server is "   NL
     "       not running. This option is mutually exclusive with the -d"      NL
-    "       option."                                                         NL
+    "       option and implies -t."                                          NL
                                                                              NL
     "  -n   Be nice. This causes slower processing in favour of other"       NL
     "       processes."                                                      NL
                                                                              NL
+    "  -t   Delete all empty directories. By default only cache files are"   NL
+    "       removed, however with some configurations the large number of"   NL
+    "       directories created may require attention."                      NL
+                                                                             NL
     "  -p   Specify PATH as the root directory of the disk cache."           NL
                                                                              NL
     "  -l   Specify LIMIT as the total disk cache size limit. Attach 'K'"    NL
@@ -803,6 +843,7 @@
     verbose = 0;
     realclean = 0;
     benice = 0;
+    deldirs = 0;
     intelligent = 0;
     previous = 0; /* avoid compiler warning */
     proxypath = NULL;
@@ -827,7 +868,7 @@
     apr_getopt_init(&o, pool, argc, argv);
 
     while (1) {
-        status = apr_getopt(o, "iDnvrd:l:L:p:", &opt, &arg);
+        status = apr_getopt(o, "iDnvrtd:l:L:p:", &opt, &arg);
         if (status == APR_EOF) {
             break;
         }
@@ -856,6 +897,13 @@
                 }
                 benice = 1;
                 break;
+               
+            case 't':
+                if (deldirs) {
+                    usage();
+                }
+                deldirs = 1;
+                break;
 
             case 'v':
                 if (verbose) {
@@ -869,6 +917,7 @@
                     usage();
                 }
                 realclean = 1;
+                deldirs = 1;
                 break;
 
             case 'd':

Reply via email to