Index: memcache.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/memcache/memcache.inc,v
retrieving revision 1.15.2.8.2.22
diff -u -p -r1.15.2.8.2.22 memcache.inc
--- memcache.inc	16 Nov 2010 21:23:38 -0000	1.15.2.8.2.22
+++ memcache.inc	19 Nov 2010 08:09:08 -0000
@@ -30,7 +30,8 @@ function cache_get($cid, $table = 'cache
   }
 
   // Determine when the current table was last flushed.
-  $cache_flush = variable_get("cache_flush_$table", 0);
+  $table_flushes = memcache_variable_get('cache_flush', array());
+  $cache_flush = isset($table_flushes[$table]) ? $table_flushes[$table] : 0;
   // Retrieve the item from the cache.
   $cache = dmemcache_get($cid, $table);
 
@@ -38,7 +39,7 @@ function cache_get($cid, $table = 'cache
     return FALSE;
   }
 
-  $wildcard_flushes = variable_get('memcache_wildcard_flushes', array());
+  $wildcard_flushes = memcache_variable_get('memcache_wildcard_flushes', array());
   $wildcard_invalidate = variable_get('memcache_wildcard_invalidate', MEMCACHE_WILDCARD_INVALIDATE);
 
   // Only validate against wildcard flushes if this table has seen a recent
@@ -218,7 +219,7 @@ function memcache_wildcards($cid, $table
   static $wildcards = array();
   $matching = array();
 
-  $wildcard_flushes = variable_get('memcache_wildcard_flushes', array());
+  $wildcard_flushes = memcache_variable_get('memcache_wildcard_flushes', array());
   $wildcard_invalidate = variable_get('memcache_wildcard_invalidate', MEMCACHE_WILDCARD_INVALIDATE);
   if (isset($wildcard_flushes[$table]) &&
       is_array($wildcard_flushes[$table])) {
@@ -317,10 +318,12 @@ function _cache_get($cid, $table = 'cach
   global $user;
 
   // Garbage collection necessary when enforcing a minimum cache lifetime
-  $cache_flush = variable_get('cache_flush_'. $table, 0);
+  $table_flushes = memcache_variable_get('cache_flush', array());
+  $cache_flush = isset($table_flushes[$table]) ? $table_flushes[$table] : 0;
   if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= time())) {
     // Reset the variable immediately to prevent a meltdown in heavy load situations.
-    variable_set('cache_flush_'. $table, 0);
+    $table_flushes[$table] = 0;
+    memcache_variable_set('cache_flush', $table_flushes);
     // Time to flush old cache data
     db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire <= %d", CACHE_PERMANENT, $cache_flush);
   }
@@ -451,16 +454,19 @@ function _cache_clear_all($cid = NULL, $
       // cached data that was cached before the timestamp.
       $user->cache = time();
 
-      $cache_flush = variable_get('cache_flush_'. $table, 0);
+      $table_flushes = memcache_variable_get('cache_flush', array());
+      $cache_flush = isset($table_flushes[$table]) ? $table_flushes[$table] : 0;
       if ($cache_flush == 0) {
         // This is the first request to clear the cache, start a timer.
-        variable_set('cache_flush_'. $table, time());
+        $table_flushes[$table] = time();
+        memcache_variable_set('cache_flush', $table_flushes);
       }
       else if (time() > ($cache_flush + variable_get('cache_lifetime', 0))) {
         // Clear the cache for everyone, cache_lifetime seconds have
         // passed since the first request to clear the cache.
         db_query("DELETE FROM {". $table ."} WHERE expire != %d AND expire < %d", CACHE_PERMANENT, time());
-        variable_set('cache_flush_'. $table, 0);
+        $table_flushes[$table] = time();
+        memcache_variable_set('cache_flush', $table_flushes);
       }
     }
     else {
@@ -482,3 +488,49 @@ function _cache_clear_all($cid = NULL, $
     }
   }
 }
+
+/**
+ * Implementation of variable_get() that avoids writing to the database.
+ *
+ * This should only be used for data that can be safely discarded if there is
+ * a full memcache flush in the case of a restart or similar, and which are
+ * volatile (and hence prone to stampedes).
+  Also note that each variable requested using this function will add an additional
+ * dmemcache_get() to the request.
+ *
+ * @param $name
+ *   The name of the variable to return.
+ * @param $default
+ *   The default value to use if this variable has never been set.
+ */
+function memcache_variable_get($name, $value) {
+  global $memcache_conf;
+  if (!isset($memcache_conf[$name]) && !array_key_exists($memcache_conf[$name])) {
+    // Store the variable as array('value' => $value); to differentiate between
+    // variables that aren't set, and variables set to FALSE.
+    $result = dmemcache_get($name, 'semaphore');
+    if ($result) {
+      $memcache_conf[$name] = $result['value'];
+    }
+    else {
+      $memcache_conf[$name] = $value;
+    }
+  }
+}
+
+/**
+ * Implementation of variable_set() that avoids writing to the database or clearing the variables cache.
+ *
+ * This should only be used for data that can be safely discarded if there is a
+ * full memcache flush in the case of a restart or similar.
+ *
+ * @param $name
+ *   The name of the variable.
+ * @param $default
+ *   The default value to use if this variable has never been set.
+ */
+function memcache_variable_set($name, $value) {
+  global $memcache_conf;
+  dmemcache_set($name, array('value' => $value, 'semaphore'));
+  $memcache_conf[$name] = $value;
+}
