You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2010/02/09 04:43:18 UTC

svn commit: r907917 - in /httpd/httpd/trunk: include/ap_mmn.h include/ap_socache.h modules/cache/mod_socache_dbm.c modules/cache/mod_socache_dc.c modules/cache/mod_socache_memcache.c modules/cache/mod_socache_shmcb.c

Author: wrowe
Date: Tue Feb  9 03:43:18 2010
New Revision: 907917

URL: http://svn.apache.org/viewvc?rev=907917&view=rev
Log:
distcache already demonstrates sub-second resolutions, but much more
importantly, let us not introduce more Y2k38 bugs?

Changes the ->store method to take expiry as an apr_time_t, and introduce
a placeholder to implement provider-specific iterators of the current
elements of an socache store.

Cleans up confusion where expiry might be confused with a timeout-period.

Finally clean up some hUngarian noteAtion.  Someones' hands need to be slapped.

Modified:
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/include/ap_socache.h
    httpd/httpd/trunk/modules/cache/mod_socache_dbm.c
    httpd/httpd/trunk/modules/cache/mod_socache_dc.c
    httpd/httpd/trunk/modules/cache/mod_socache_memcache.c
    httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=907917&r1=907916&r2=907917&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Tue Feb  9 03:43:18 2010
@@ -214,15 +214,16 @@
  * 20091230.2 (2.3.5-dev)  add ap_get_server_name_for_url()
  * 20091230.3 (2.3.6-dev)  add ap_parse_log_level()
  * 20091230.4 (2.3.6-dev)  export ap_process_request_after_handler() for mod_serf
+ * 20100208.0 (2.3.6-dev)  ap_socache_provider_t API changes to store and iterate
  *
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20091230
+#define MODULE_MAGIC_NUMBER_MAJOR 20100208
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 4                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/include/ap_socache.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?rev=907917&r1=907916&r2=907917&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_socache.h (original)
+++ httpd/httpd/trunk/include/ap_socache.h Tue Feb  9 03:43:18 2010
@@ -29,6 +29,7 @@
 #include "httpd.h"
 #include "ap_provider.h"
 #include "apr_pools.h"
+#include "apr_time.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,7 +38,10 @@
 /** If this flag is set, the store/retrieve/remove/status interfaces
  * of the provider are NOT safe to be called concurrently from
  * multiple processes or threads, and an external global mutex must be
- * used to serialize access to the provider. */
+ * used to serialize access to the provider.
+ * XXX: Even if store/retrieve/remove is atomic, isn't it useful to note
+ * independently that status and iterate may or may not be?
+ */
 #define AP_SOCACHE_FLAG_NOTMPSAFE (0x0001)
 
 /** A cache instance. */
@@ -50,11 +54,31 @@
     apr_size_t avg_id_len;
     /** Approximate average size of objects: */
     apr_size_t avg_obj_size;
-    /** Interval (in seconds) after which an expiry run is
+    /** Interval after which an expiry run is
      * necessary. */
-    time_t expiry_interval;
+    apr_interval_time_t expiry_interval;
 };
 
+/**
+ * Iterator callback prototype for the ap_socache_provider_t->iterate() method
+ * @param instance The cache instance (passed through)
+ * @param s Associated server structure (passed through)
+ * @param id Unique ID for the object; binary blob
+ * @param idlen Length of id blob
+ * @param data Output buffer to place retrievd data (binary blob)
+ * @param datalen Length of data buffer
+ * @param pool Pool for temporary allocations (passed through)
+ * @return APR status value; return APR_SUCCESS or the iteration will halt;
+ * this value is returned to the ap_socache_provider_t->iterate() caller
+ */
+typedef apr_status_t (*ap_socache_iterator_t)(ap_socache_instance_t *instance,
+                                              server_rec *s,
+                                              const unsigned char *id,
+                                              unsigned int idlen,
+                                              unsigned char *data,
+                                              unsigned int *datalen,
+                                              apr_pool_t *pool);
+
 /** A socache provider structure.  socache providers are registered
  * with the ap_provider.h interface using the AP_SOCACHE_PROVIDER_*
  * constants. */
@@ -121,7 +145,7 @@
      */
     apr_status_t (*store)(ap_socache_instance_t *instance, server_rec *s, 
                           const unsigned char *id, unsigned int idlen, 
-                          time_t expiry, 
+                          apr_time_t expiry, 
                           unsigned char *data, unsigned int datalen,
                           apr_pool_t *pool);
 
@@ -156,12 +180,28 @@
 
     /** Dump the status of a cache instance for mod_status.  Will use
      * the ap_r* interfaces to produce appropriate status output.
+     * XXX: apr_r* are deprecated, bad dogfood
      *
      * @param instance The cache instance
      * @param r The request structure
      * @param flags The AP_STATUS_* constants used (see mod_status.h)
      */
     void (*status)(ap_socache_instance_t *instance, request_rec *r, int flags);
+
+    /**
+     * Dump all cached objects through an iterator callback.
+     * @param instance The cache instance
+     * @param s Associated server structure (for logging purposes)
+     * @param iterator The user provided callback which will receive
+     * individual calls for each unexpired id/data pair
+     * @param pool Pool for temporary allocations.
+     * @return APR status value; APR_NOTFOUND if the object was not
+     * found
+     */
+    apr_status_t (*iterate)(ap_socache_instance_t *instance, server_rec *s,
+                            ap_socache_iterator_t *iterator,
+                            apr_pool_t *pool);
+
 } ap_socache_provider_t;
 
 /** The provider group used to register socache providers. */

Modified: httpd/httpd/trunk/modules/cache/mod_socache_dbm.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_dbm.c?rev=907917&r1=907916&r2=907917&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/mod_socache_dbm.c (original)
+++ httpd/httpd/trunk/modules/cache/mod_socache_dbm.c Tue Feb  9 03:43:18 2010
@@ -44,8 +44,8 @@
     const char *data_file;
     /* Pool must only be used with the mutex held. */
     apr_pool_t *pool;
-    time_t last_expiry;
-    time_t expiry_interval;
+    apr_time_t last_expiry;
+    apr_interval_time_t expiry_interval;
 };
 
 /**
@@ -136,7 +136,7 @@
     apr_dbm_close(dbm);
 
     ctx->expiry_interval = (hints && hints->expiry_interval 
-                            ? hints->expiry_interval : 30);
+                            ? hints->expiry_interval : apr_time_from_sec(30));
 
 #if AP_NEED_SET_MUTEX_PERMS
     /*
@@ -183,7 +183,7 @@
 
 static apr_status_t socache_dbm_store(ap_socache_instance_t *ctx, 
                                       server_rec *s, const unsigned char *id, 
-                                      unsigned int idlen, time_t expiry, 
+                                      unsigned int idlen, apr_time_t expiry, 
                                       unsigned char *ucaData, 
                                       unsigned int nData, apr_pool_t *pool)
 {
@@ -196,14 +196,14 @@
 #ifdef PAIRMAX
     if ((idlen + nData) >= PAIRMAX) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "data size too large for DBM session cache: %d >= %d",
+                 "data size too large for DBM socache: %d >= %d",
                  (idlen + nData), PAIRMAX);
         return APR_ENOSPC;
     }
 #else
     if ((idlen + nData) >= 950 /* at least less than approx. 1KB */) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "data size too large for DBM session cache: %d >= %d",
+                 "data size too large for DBM socache: %d >= %d",
                  (idlen + nData), 950);
         return APR_ENOSPC;
     }
@@ -214,15 +214,15 @@
     dbmkey.dsize = idlen;
 
     /* create DBM value */
-    dbmval.dsize = sizeof(time_t) + nData;
+    dbmval.dsize = sizeof(apr_time_t) + nData;
     dbmval.dptr  = (char *)malloc(dbmval.dsize);
     if (dbmval.dptr == NULL) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "malloc error creating DBM value");
         return APR_ENOMEM;
     }
-    memcpy((char *)dbmval.dptr, &expiry, sizeof(time_t));
-    memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData);
+    memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t));
+    memcpy((char *)dbmval.dptr+sizeof(apr_time_t), ucaData, nData);
 
     /* and store it to the DBM file */
     apr_pool_clear(ctx->pool);
@@ -264,8 +264,8 @@
     apr_datum_t dbmkey;
     apr_datum_t dbmval;
     unsigned int nData;
-    time_t expiry;
-    time_t now;
+    apr_time_t expiry;
+    apr_time_t now;
     apr_status_t rc;
 
     /* allow the regular expiring to occur */
@@ -293,26 +293,26 @@
         apr_dbm_close(dbm);
         return rc;
     }
-    if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) {
+    if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) {
         apr_dbm_close(dbm);
         return APR_EGENERAL;
     }
 
     /* parse resulting data */
-    nData = dbmval.dsize-sizeof(time_t);
+    nData = dbmval.dsize-sizeof(apr_time_t);
     if (nData > *destlen) {
         apr_dbm_close(dbm);
         return APR_ENOSPC;
     }    
 
     *destlen = nData;
-    memcpy(&expiry, dbmval.dptr, sizeof(time_t));
-    memcpy(dest, (char *)dbmval.dptr + sizeof(time_t), nData);
+    memcpy(&expiry, dbmval.dptr, sizeof(apr_time_t));
+    memcpy(dest, (char *)dbmval.dptr + sizeof(apr_time_t), nData);
 
     apr_dbm_close(dbm);
 
     /* make sure the stuff is still not expired */
-    now = time(NULL);
+    now = apr_time_now();
     if (expiry <= now) {
         socache_dbm_remove(ctx, s, id, idlen, p);
         return APR_NOTFOUND;
@@ -355,27 +355,27 @@
     apr_dbm_t *dbm;
     apr_datum_t dbmkey;
     apr_datum_t dbmval;
-    time_t tExpiresAt;
-    int nElements = 0;
-    int nDeleted = 0;
-    int bDelete;
+    apr_time_t expiry;
+    int elts = 0;
+    int deleted = 0;
+    int expired;
     apr_datum_t *keylist;
     int keyidx;
     int i;
-    time_t tNow;
+    apr_time_t now;
     apr_status_t rv;
 
     /*
-     * make sure the expiration for still not-accessed session
-     * cache entries is done only from time to time
+     * make sure the expiration for still not-accessed
+     * socache entries is done only from time to time
      */
-    tNow = time(NULL);
+    now = time(NULL);
 
-    if (tNow < ctx->last_expiry + ctx->expiry_interval) {
+    if (now < ctx->last_expiry + ctx->expiry_interval) {
         return;
     }
 
-    ctx->last_expiry = tNow;
+    ctx->last_expiry = now;
 
     /*
      * Here we have to be very carefully: Not all DBM libraries are
@@ -410,17 +410,17 @@
         }
         apr_dbm_firstkey(dbm, &dbmkey);
         while (dbmkey.dptr != NULL) {
-            nElements++;
-            bDelete = FALSE;
+            elts++;
+            expired = FALSE;
             apr_dbm_fetch(dbm, dbmkey, &dbmval);
-            if (dbmval.dsize <= sizeof(time_t) || dbmval.dptr == NULL)
-                bDelete = TRUE;
+            if (dbmval.dsize <= sizeof(apr_time_t) || dbmval.dptr == NULL)
+                expired = TRUE;
             else {
-                memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t));
-                if (tExpiresAt <= tNow)
-                    bDelete = TRUE;
+                memcpy(&expiry, dbmval.dptr, sizeof(apr_time_t));
+                if (expiry <= now)
+                    expired = TRUE;
             }
-            if (bDelete) {
+            if (expired) {
                 if ((keylist[keyidx].dptr = apr_pmemdup(ctx->pool, dbmkey.dptr, dbmkey.dsize)) != NULL) {
                     keylist[keyidx].dsize = dbmkey.dsize;
                     keyidx++;
@@ -443,7 +443,7 @@
         }
         for (i = 0; i < keyidx; i++) {
             apr_dbm_delete(dbm, keylist[i]);
-            nDeleted++;
+            deleted++;
         }
         apr_dbm_close(dbm);
 
@@ -454,7 +454,7 @@
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "Inter-Process Session Cache (DBM) Expiry: "
                  "old: %d, new: %d, removed: %d",
-                 nElements, nElements-nDeleted, nDeleted);
+                 elts, elts-deleted, deleted);
 }
 
 static void socache_dbm_status(ap_socache_instance_t *ctx, request_rec *r, 
@@ -463,13 +463,13 @@
     apr_dbm_t *dbm;
     apr_datum_t dbmkey;
     apr_datum_t dbmval;
-    int nElem;
-    int nSize;
-    int nAverage;
+    int elts;
+    long size;
+    int avg;
     apr_status_t rv;
 
-    nElem = 0;
-    nSize = 0;
+    elts = 0;
+    size = 0;
 
     apr_pool_clear(ctx->pool);
     if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, 
@@ -488,20 +488,28 @@
         apr_dbm_fetch(dbm, dbmkey, &dbmval);
         if (dbmval.dptr == NULL)
             continue;
-        nElem += 1;
-        nSize += dbmval.dsize;
+        elts += 1;
+        size += dbmval.dsize;
     }
     apr_dbm_close(dbm);
-    if (nSize > 0 && nElem > 0)
-        nAverage = nSize / nElem;
+    if (size > 0 && elts > 0)
+        avg = (int)(size / (long)elts);
     else
-        nAverage = 0;
+        avg = 0;
     ap_rprintf(r, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>");
-    ap_rprintf(r, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize);
-    ap_rprintf(r, "average session size: <b>%d</b> bytes<br>", nAverage);
+    ap_rprintf(r, "current entries: <b>%d</b>, current size: <b>%ld</b> bytes<br>", elts, size);
+    ap_rprintf(r, "average entry size: <b>%d</b> bytes<br>", avg);
     return;
 }
 
+apr_status_t socache_dbm_iterate(ap_socache_instance_t *instance,
+                                 server_rec *s,
+                                 ap_socache_iterator_t *iterator,
+                                 apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
 static const ap_socache_provider_t socache_dbm = {
     "dbm",
     AP_SOCACHE_FLAG_NOTMPSAFE,
@@ -511,7 +519,8 @@
     socache_dbm_store,
     socache_dbm_retrieve,
     socache_dbm_remove,
-    socache_dbm_status
+    socache_dbm_status,
+    socache_dbm_iterate
 };
 
 static void register_hooks(apr_pool_t *p)

Modified: httpd/httpd/trunk/modules/cache/mod_socache_dc.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_dc.c?rev=907917&r1=907916&r2=907917&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/mod_socache_dc.c (original)
+++ httpd/httpd/trunk/modules/cache/mod_socache_dc.c Tue Feb  9 03:43:18 2010
@@ -92,15 +92,18 @@
 
 static apr_status_t socache_dc_store(ap_socache_instance_t *ctx, server_rec *s, 
                                      const unsigned char *id, unsigned int idlen,
-                                     time_t timeout,
+                                     time_t expiry,
                                      unsigned char *der, unsigned int der_len,
                                      apr_pool_t *p)
 {
-    /* !@#$%^ - why do we deal with *absolute* time anyway??? */
-    timeout -= time(NULL);
+    /* !@#$%^ - why do we deal with *absolute* time anyway??? 
+     * Uhm - because most things expire things at a specific time?
+     * Were the API were thought out expiry - r->request_time is a good approximation
+     */
+    expiry -= apr_time_t(NULL);
     /* Send the serialised session to the distributed cache context */
     if (!DC_CTX_add_session(ctx->dc, id, idlen, der, der_len,
-                            (unsigned long)timeout * 1000)) {
+                            apr_time_in_msec(expiry)) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'add_session' failed");
         return APR_EGENERAL;
     }
@@ -151,6 +154,14 @@
                " target: <b>%s</b><br>", ctx->target);
 }
 
+apr_status_t socache_dc_iterate(ap_socache_instance_t *instance,
+                                server_rec *s,
+                                ap_socache_iterator_t *iterator,
+                                apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
 static const ap_socache_provider_t socache_dc = {
     "distcache",
     0,
@@ -160,7 +171,8 @@
     socache_dc_store,
     socache_dc_retrieve,
     socache_dc_remove,
-    socache_dc_status
+    socache_dc_status,
+    socache_dc_iterate
 };
 
 static void register_hooks(apr_pool_t *p)

Modified: httpd/httpd/trunk/modules/cache/mod_socache_memcache.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_memcache.c?rev=907917&r1=907916&r2=907917&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/mod_socache_memcache.c (original)
+++ httpd/httpd/trunk/modules/cache/mod_socache_memcache.c Tue Feb  9 03:43:18 2010
@@ -200,7 +200,7 @@
 
 static apr_status_t socache_mc_store(ap_socache_instance_t *ctx, server_rec *s, 
                                      const unsigned char *id, unsigned int idlen,
-                                     time_t timeout,
+                                     apr_time_t expiry,
                                      unsigned char *ucaData, unsigned int nData,
                                      apr_pool_t *p)
 {
@@ -211,7 +211,8 @@
         return APR_EINVAL;
     }
 
-    rv = apr_memcache_set(ctx->mc, buf, (char*)ucaData, nData, timeout, 0);
+    /* In APR-util - unclear what 'timeout' is, as it was not implemented */
+    rv = apr_memcache_set(ctx->mc, buf, (char*)ucaData, nData, 0, 0);
 
     if (rv != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
@@ -286,6 +287,14 @@
     /* TODO: Make a mod_status handler. meh. */
 }
 
+apr_status_t socache_mc_iterate(ap_socache_instance_t *instance,
+                                server_rec *s,
+                                ap_socache_iterator_t *iterator,
+                                apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
 static const ap_socache_provider_t socache_mc = {
     "memcache",
     0,
@@ -295,7 +304,8 @@
     socache_mc_store,
     socache_mc_retrieve,
     socache_mc_remove,
-    socache_mc_status
+    socache_mc_status,
+    socache_mc_iterate
 };
 
 #endif /* HAVE_APU_MEMCACHE */

Modified: httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c?rev=907917&r1=907916&r2=907917&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c (original)
+++ httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c Tue Feb  9 03:43:18 2010
@@ -80,14 +80,14 @@
  */
 typedef struct {
     /* absolute time this entry expires */
-    time_t expires;
+    apr_time_t expires;
     /* location within the subcache's data area */
     unsigned int data_pos;
     /* size (most logic ignores this, we keep it only to minimise memcpy) */
     unsigned int data_used;
     /* length of the used data which contains the id */
     unsigned int id_len;
-    /* Used to mark explicitly-removed sessions */
+    /* Used to mark explicitly-removed socache entries */
     unsigned char removed;
 } SHMCBIndex;
 
@@ -147,7 +147,7 @@
                         sizeof(SHMCBHeader) + \
                         (num) * ((pHeader)->subcache_size))
 
-/* This macro takes a pointer to the header and a session id and returns a
+/* This macro takes a pointer to the header and an id and returns a
  * pointer to the corresponding subcache. */
 #define SHMCB_MASK(pHeader, id) \
                 SHMCB_SUBCACHE((pHeader), *(id) & ((pHeader)->subcache_num - 1))
@@ -239,13 +239,14 @@
 
 
 /* Prototypes for low-level subcache operations */
-static void shmcb_subcache_expire(server_rec *, SHMCBHeader *, SHMCBSubcache *);
+static void shmcb_subcache_expire(server_rec *, SHMCBHeader *, SHMCBSubcache *,
+                                  apr_time_t);
 /* Returns zero on success, non-zero on failure. */   
 static int shmcb_subcache_store(server_rec *s, SHMCBHeader *header,
                                 SHMCBSubcache *subcache, 
                                 unsigned char *data, unsigned int data_len,
                                 const unsigned char *id, unsigned int id_len,
-                                time_t expiry);
+                                apr_time_t expiry);
 /* Returns zero on success, non-zero on failure. */   
 static int shmcb_subcache_retrieve(server_rec *, SHMCBHeader *, SHMCBSubcache *,
                                    const unsigned char *id, unsigned int idlen,
@@ -437,7 +438,7 @@
         subcache->data_pos = subcache->data_used = 0;
     }
     ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
-                 "Shared memory session cache initialised");
+                 "Shared memory socache initialised");
     /* Success ... */
 
     return APR_SUCCESS;
@@ -453,7 +454,7 @@
 
 static apr_status_t socache_shmcb_store(ap_socache_instance_t *ctx, 
                                         server_rec *s, const unsigned char *id, 
-                                        unsigned int idlen, time_t timeout, 
+                                        unsigned int idlen, apr_time_t expiry, 
                                         unsigned char *encoded,
                                         unsigned int len_encoded,
                                         apr_pool_t *p)
@@ -464,15 +465,16 @@
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "socache_shmcb_store (0x%02x -> subcache %d)",
                  SHMCB_MASK_DBG(header, id));
+    /* XXX: Says who?  Why shouldn't this be acceptable, or padded if not? */
     if (idlen < 4) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided "
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short id provided "
                 "(%u bytes)", idlen);
         return APR_EINVAL;
     }
     if (shmcb_subcache_store(s, header, subcache, encoded,
-                             len_encoded, id, idlen, timeout)) {
+                             len_encoded, id, idlen, expiry)) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "can't store a session!");
+                     "can't store an socache entry!");
         return APR_ENOSPC;
     }
     header->stat_stores++;
@@ -495,7 +497,7 @@
                  "socache_shmcb_retrieve (0x%02x -> subcache %d)",
                  SHMCB_MASK_DBG(header, id));
 
-    /* Get the session corresponding to the session_id, if it exists. */
+    /* Get the entry corresponding to the id, if it exists. */
     rv = shmcb_subcache_retrieve(s, header, subcache, id, idlen,
                                  dest, destlen);
     if (rv == 0)
@@ -520,7 +522,7 @@
                  "socache_shmcb_remove (0x%02x -> subcache %d)",
                  SHMCB_MASK_DBG(header, id));
     if (idlen < 4) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided "
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short id provided "
                 "(%u bytes)", idlen);
         return APR_EINVAL;
     }
@@ -543,8 +545,8 @@
     server_rec *s = r->server;
     SHMCBHeader *header = ctx->header;
     unsigned int loop, total = 0, cache_total = 0, non_empty_subcaches = 0;
-    time_t idx_expiry, min_expiry = 0, max_expiry = 0, average_expiry = 0;
-    time_t now = time(NULL);
+    apr_time_t idx_expiry, min_expiry = 0, max_expiry = 0, average_expiry = 0;
+    apr_time_t now = apr_time_now();
     double expiry_total = 0;
     int index_pct, cache_pct;
 
@@ -555,7 +557,7 @@
     /* Iterate over the subcaches */
     for (loop = 0; loop < header->subcache_num; loop++) {
         SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
-        shmcb_subcache_expire(s, header, subcache);
+        shmcb_subcache_expire(s, header, subcache, now);
         total += subcache->idx_used;
         cache_total += subcache->data_used;
         if (subcache->idx_used) {
@@ -576,29 +578,29 @@
                                        header->subcache_num);
     /* Generate HTML */
     ap_rprintf(r, "cache type: <b>SHMCB</b>, shared memory: <b>%" APR_SIZE_T_FMT "</b> "
-               "bytes, current sessions: <b>%d</b><br>",
+               "bytes, current entries: <b>%d</b><br>",
                ctx->shm_size, total);
     ap_rprintf(r, "subcaches: <b>%d</b>, indexes per subcache: <b>%d</b><br>",
                header->subcache_num, header->index_num);
     if (non_empty_subcaches) {
-        average_expiry = (time_t)(expiry_total / (double)non_empty_subcaches);
+        average_expiry = (apr_time_t)(expiry_total / (double)non_empty_subcaches);
         ap_rprintf(r, "time left on oldest entries' objects: ");
         if (now < average_expiry)
             ap_rprintf(r, "avg: <b>%d</b> seconds, (range: %d...%d)<br>",
-                       (int)(average_expiry - now),
-                       (int)(min_expiry - now),
-                       (int)(max_expiry - now));
+                       (int)apr_time_sec(average_expiry - now),
+                       (int)apr_time_sec(min_expiry - now),
+                       (int)apr_time_sec(max_expiry - now));
         else
             ap_rprintf(r, "expiry_threshold: <b>Calculation error!</b><br>");
     }
 
     ap_rprintf(r, "index usage: <b>%d%%</b>, cache usage: <b>%d%%</b><br>",
                index_pct, cache_pct);
-    ap_rprintf(r, "total sessions stored since starting: <b>%lu</b><br>",
+    ap_rprintf(r, "total entries stored since starting: <b>%lu</b><br>",
                header->stat_stores);
-    ap_rprintf(r, "total sessions expired since starting: <b>%lu</b><br>",
+    ap_rprintf(r, "total entries expired since starting: <b>%lu</b><br>",
                header->stat_expiries);
-    ap_rprintf(r, "total (pre-expiry) sessions scrolled out of the cache: "
+    ap_rprintf(r, "total (pre-expiry) entries scrolled out of the cache: "
                "<b>%lu</b><br>", header->stat_scrolled);
     ap_rprintf(r, "total retrieves since starting: <b>%lu</b> hit, "
                "<b>%lu</b> miss<br>", header->stat_retrieves_hit,
@@ -614,9 +616,8 @@
  */
 
 static void shmcb_subcache_expire(server_rec *s, SHMCBHeader *header,
-                                  SHMCBSubcache *subcache)
+                                  SHMCBSubcache *subcache, apr_time_t now)
 {
-    time_t now = time(NULL);
     unsigned int loop = 0;
     unsigned int new_idx_pos = subcache->idx_pos;
     SHMCBIndex *idx = NULL;
@@ -633,7 +634,7 @@
         /* Nothing to do */
         return;
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "will be expiring %u sessions", loop);
+                 "will be expiring %u socache entries", loop);
     if (loop == subcache->idx_used) {
         /* We're expiring everything, piece of cake */
         subcache->idx_used = 0;
@@ -652,14 +653,56 @@
     }
     header->stat_expiries += loop;
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                 "we now have %u sessions", subcache->idx_used);
+                 "we now have %u socache entries", subcache->idx_used);
+}
+
+static void shmcb_subcache_iterate(server_rec *s, SHMCBHeader *header,
+                                   SHMCBSubcache *subcache)
+{
+    apr_time_t now = apr_time_now();
+    unsigned int loop = 0;
+    unsigned int new_idx_pos = subcache->idx_pos;
+    SHMCBIndex *idx = NULL;
+
+    while (loop < subcache->idx_used) {
+        idx = SHMCB_INDEX(subcache, new_idx_pos);
+        if (idx->expires > now)
+            /* it hasn't expired yet, we're done iterating */
+            break;
+        loop++;
+        new_idx_pos = SHMCB_CYCLIC_INCREMENT(new_idx_pos, 1, header->index_num);
+    }
+    if (!loop)
+        /* Nothing to do */
+        return;
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                 "will be expiring %u socache entries", loop);
+    if (loop == subcache->idx_used) {
+        /* We're expiring everything, piece of cake */
+        subcache->idx_used = 0;
+        subcache->data_used = 0;
+    } else {
+        /* There remain other indexes, so we can use idx to adjust 'data' */
+        unsigned int diff = SHMCB_CYCLIC_SPACE(subcache->data_pos,
+                                               idx->data_pos,
+                                               header->subcache_data_size);
+        /* Adjust the indexes */
+        subcache->idx_used -= loop;
+        subcache->idx_pos = new_idx_pos;
+        /* Adjust the data area */
+        subcache->data_used -= diff;
+        subcache->data_pos = idx->data_pos;
+    }
+    header->stat_expiries += loop;
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
+                 "we now have %u socache entries", subcache->idx_used);
 }
 
 static int shmcb_subcache_store(server_rec *s, SHMCBHeader *header,
                                 SHMCBSubcache *subcache, 
                                 unsigned char *data, unsigned int data_len,
                                 const unsigned char *id, unsigned int id_len,
-                                time_t expiry)
+                                apr_time_t expiry)
 {
     unsigned int data_offset, new_idx, id_offset;
     SHMCBIndex *idx;
@@ -668,13 +711,13 @@
     /* Sanity check the input */
     if (total_len > header->subcache_data_size) {
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
-                     "inserting session larger (%d) than subcache data area (%d)",
+                     "inserting socache entry larger (%d) than subcache data area (%d)",
                      total_len, header->subcache_data_size);
         return -1;
     }
 
     /* If there are entries to expire, ditch them first. */
-    shmcb_subcache_expire(s, header, subcache);
+    shmcb_subcache_expire(s, header, subcache, apr_time_now());
 
     /* Loop until there is enough space to insert */
     if (header->subcache_data_size - subcache->data_used < total_len
@@ -718,11 +761,15 @@
      * CHECKING WHETHER IT SHOULD BE GENUINELY "INSERTED" SOMEWHERE.
      *
      * We either fix that, or find out at a "higher" (read "mod_ssl")
-     * level whether it is possible to have distinct session caches for
-     * any attempted tomfoolery to do with different session timeouts.
-     * Knowing in advance that we can have a cache-wide constant timeout
+     * level whether it is possible to have distinct socaches for
+     * any attempted tomfoolery to do with different socache entry expirys.
+     * Knowing in advance that we can have a cache-wide constant expiry
      * would make this stuff *MUCH* more efficient. Mind you, it's very
      * efficient right now because I'm ignoring this problem!!!
+     *
+     * XXX: Author didn't consider that httpd doesn't promise to perform
+     * any processing in date order (c.f. FAQ "My log entries are not in
+     * date order!")
      */
     /* Insert the id */
     id_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used,
@@ -767,8 +814,11 @@
     unsigned int pos;
     unsigned int loop = 0;
 
-    /* If there are entries to expire, ditch them first. */
-    shmcb_subcache_expire(s, header, subcache);
+    /* If there are entries to expire, ditch them first.
+     * XXX: Horribly inefficient to double the work, why not simply 
+     * upon store when free space might be useful?
+     */
+    shmcb_subcache_expire(s, header, subcache, apr_time_now());
     pos = subcache->idx_pos;
 
     while (loop < subcache->idx_used) {
@@ -823,7 +873,7 @@
      * consistent statistics where a "remove" operation may actually be the
      * higher layer spotting an expiry issue prior to us. Our caller is
      * handling stats, so a failure return would be inconsistent if the
-     * intended session was in fact removed by an expiry run. */
+     * intended socache entry was in fact removed by an expiry run. */
 
     pos = subcache->idx_pos;
     while (loop < subcache->idx_used) {
@@ -837,10 +887,10 @@
                                    idx->data_pos, id, idx->id_len) == 0) {
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                          "possible match at idx=%d, data=%d", pos, idx->data_pos);
-            /* Found the matching session, remove it quietly. */
+            /* Found the matching entry, remove it quietly. */
             idx->removed = 1;
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
-                             "shmcb_subcache_remove removing matching session");
+                             "shmcb_subcache_remove removing matching entry");
             return 0;
         }
         /* Increment */
@@ -851,6 +901,14 @@
     return -1; /* failure */
 }
 
+apr_status_t socache_shmcb_iterate(ap_socache_instance_t *instance,
+                                   server_rec *s,
+                                   ap_socache_iterator_t *iterator,
+                                   apr_pool_t *pool)
+{
+    return APR_ENOTIMPL;
+}
+
 static const ap_socache_provider_t socache_shmcb = {
     "shmcb",
     AP_SOCACHE_FLAG_NOTMPSAFE,
@@ -860,7 +918,8 @@
     socache_shmcb_store,
     socache_shmcb_retrieve,
     socache_shmcb_remove,
-    socache_shmcb_status
+    socache_shmcb_status,
+    socache_shmcb_iterate
 };
 
 static void register_hooks(apr_pool_t *p)



Re: svn commit: r907917 - in /httpd/httpd/trunk: include/ap_mmn.h include/ap_socache.h modules/cache/mod_socache_dbm.c modules/cache/mod_socache_dc.c modules/cache/mod_socache_memcache.c modules/cache/mod_socache_shmcb.c

Posted by Joe Orton <jo...@redhat.com>.
On Tue, Feb 09, 2010 at 03:43:18AM -0000, William Rowe wrote:
> Author: wrowe
> Date: Tue Feb  9 03:43:18 2010
> New Revision: 907917
> 
> URL: http://svn.apache.org/viewvc?rev=907917&view=rev
> Log:
> distcache already demonstrates sub-second resolutions, but much more
> importantly, let us not introduce more Y2k38 bugs?
> 
> Changes the ->store method to take expiry as an apr_time_t, and introduce
> a placeholder to implement provider-specific iterators of the current
> elements of an socache store.
> 
> Cleans up confusion where expiry might be confused with a timeout-period.

Thanks Bill!

> Finally clean up some hUngarian noteAtion.  Someones' hands need to be slapped.

It's all Ben's fault, he started it :)

One minor comment:

> @@ -156,12 +180,28 @@
>  
>      /** Dump the status of a cache instance for mod_status.  Will use
>       * the ap_r* interfaces to produce appropriate status output.
> +     * XXX: apr_r* are deprecated, bad dogfood

$ grep -i deprecated http_protocol.h 
$

No they aren't ;) ... and I don't think they should be either, they are 
fine interfaces which have worked forever.

joe