'Way back in May 2001, Phil Dietz proposed adding the ability
to control whether the file inode should be included in the
formulation of a document's ETag.  He originally proposed it
as an extension to the Options directive, but said he'd re-do
it as its own directive.  I can't find any record of that
actually happening, though, so here's a patch to do it.

Reason: Systems that fan out their content onto multiple back-end
servers with identical filesystem contents would nevertheless
produce cache-hammering responses because the same content would
have a different inode on each back-end server.  Taking the inode
out of the equation allows their content to be cached as identical.
The reduced ETag is based on only the last-modified time and the
file size, rather than those plus the inode.

The directive added by this patch is a FLAG UseInodesInETags.
It can be used wherever FileInfo directives can appear.  The
core per-dir config structure is extended by an int at the end,
used only by http_core.c and http_protocol.c.

If no-one has any complaints about this in the next couple of days,
I'll commit to 1.3 and then bring it forward to 2.0.  The concept
has already received the necessary +1s, so any issues *should*
only relate to implementation or names..

Index: src/CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1742
diff -u -r1.1742 CHANGES
--- src/CHANGES 2001/11/26 17:26:53     1.1742
+++ src/CHANGES 2001/11/27 20:46:29
@@ -1,4 +1,13 @@
 Changes with Apache 1.3.23
+  *) Add UseInodesInETags directive to control whether a file's
+     inode number can be used when constructing an ETag.  We
+     always have in the past, but it breaks caching for systems
+     with content fan-out across multiple back-end servers.
+     'UseInodesinETags Off' will result in only the last-modified
+     time and file size being used, which should allow such
+     fanned-out files to be cached.
+     [Ken Coar, from a patch by Phil Dietz]
+
   *) Win32: Do not allow threads to continue handling keepalive
      requests after a shutdown or restart has ben signaled.
      [Bill Stoddard]
Index: src/include/http_core.h
===================================================================
RCS file: /home/cvs/apache-1.3/src/include/http_core.h,v
retrieving revision 1.64
diff -u -r1.64 http_core.h
--- src/include/http_core.h     2001/03/09 10:10:20     1.64
+++ src/include/http_core.h     2001/11/27 20:46:29
@@ -309,6 +309,12 @@
 #endif
 #endif /* CHARSET_EBCDIC */
 
+    /*
+     * Should file inodes be included in ETag generation?  Doing so
+     * can defeat caching of back-end fanned-out content.
+     */
+    int inode_etag;
+
 } core_dir_config;
 
 /* Per-server core configuration */
Index: src/main/http_core.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_core.c,v
retrieving revision 1.299
diff -u -r1.299 http_core.c
--- src/main/http_core.c        2001/11/16 01:32:20     1.299
+++ src/main/http_core.c        2001/11/27 20:46:29
@@ -170,6 +170,11 @@
 #endif
 #endif /* CHARSET_EBCDIC */
 
+    /*
+     * Flag for use of inodes in ETags.
+     */
+    conf->inode_etag = OPT_UNSET;
+
     return (void *)conf;
 }
 
@@ -319,6 +324,13 @@
 #endif
 #endif /* CHARSET_EBCDIC */
 
+    /*
+     * Use the closer setting if it was explicit.
+     */
+    conf->inode_etag = (new->inode_etag == OPT_UNSET)
+        ? base->inode_etag
+        : new->inode_etag;
+
     return (void*)conf;
 }
 
@@ -2985,6 +2997,18 @@
 #endif
 #endif /* CHARSET_EBCDIC */
 
+/*
+ * Note whether file inodes may be used when forming ETag values.
+ */
+static const char *set_inode_etag(cmd_parms *cmd, void *mconfig, int bool)
+{
+    core_dir_config *cfg;
+
+    cfg = (core_dir_config *) mconfig;
+    cfg->inode_etag = bool;
+    return NULL;
+}
+
 /* Note --- ErrorDocument will now work from .htaccess files.  
  * The AllowOverride of Fileinfo allows webmasters to turn it off
  */
@@ -3276,6 +3300,8 @@
 #endif
 #endif /* CHARSET_EBCDIC */
 
+{ "UseInodesInETags", set_inode_etag, NULL, OR_FILEINFO, FLAG,
+  "Use file number (inode) when generating ETag values"},
 { NULL }
 };
 
Index: src/main/http_protocol.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/main/http_protocol.c,v
retrieving revision 1.301
diff -u -r1.301 http_protocol.c
--- src/main/http_protocol.c    2001/06/22 12:43:54     1.301
+++ src/main/http_protocol.c    2001/11/27 20:46:29
@@ -649,7 +649,10 @@
 {
     char *etag;
     char *weak;
+    core_dir_config *cfg;
 
+    cfg = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+                                                  &core_module);
     /*
      * Make an ETag header out of various pieces of information. We use
      * the last-modified date and, if we have a real file, the
@@ -666,11 +669,24 @@
     weak = ((r->request_time - r->mtime > 1) && !force_weak) ? "" : "W/";
 
     if (r->finfo.st_mode != 0) {
-        etag = ap_psprintf(r->pool,
-                    "%s\"%lx-%lx-%lx\"", weak,
-                    (unsigned long) r->finfo.st_ino,
-                    (unsigned long) r->finfo.st_size,
-                    (unsigned long) r->mtime);
+        if (cfg->inode_etag != 0) {
+            /*
+             * This picks up both the explicit 'yes, use inodes' and the
+             * 'didn't bother to set it so use backward-compatible behaviour'
+             * settings.
+             */
+            etag = ap_psprintf(r->pool,
+                               "%s\"%lx-%lx-%lx\"", weak,
+                               (unsigned long) r->finfo.st_ino,
+                               (unsigned long) r->finfo.st_size,
+                               (unsigned long) r->mtime);
+        }
+        else {
+            etag = ap_psprintf(r->pool,
+                               "%s\"%lx-%lx\"", weak,
+                               (unsigned long) r->finfo.st_size,
+                               (unsigned long) r->mtime);
+        }
     }
     else {
         etag = ap_psprintf(r->pool, "%s\"%lx\"", weak,

-- 
#ken    P-)}

Ken Coar, Sanagendamgagwedweinini  http://Golux.Com/coar/
Author, developer, opinionist      http://Apache-Server.Com/

"All right everyone!  Step away from the glowing hamburger!"

Reply via email to