? d7_memcache.patch
? d7_review.txt
? memcache.install
Index: dmemcache.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/memcache/dmemcache.inc,v
retrieving revision 1.1.2.7.2.5
diff -u -p -r1.1.2.7.2.5 dmemcache.inc
--- dmemcache.inc	15 Sep 2009 17:33:46 -0000	1.1.2.7.2.5
+++ dmemcache.inc	3 Dec 2009 15:49:03 -0000
@@ -30,11 +30,11 @@ $_memcache_statistics = array('get' => a
  *
  * @return bool
  */
-function dmemcache_set($key, $value, $exp = 0, $bin = 'cache') {
+function dmemcache_set($key, $value, $exp = 0, $bin = 'cache', $mc = NULL) {
   global $_memcache_statistics;
   $_memcache_statistics['set'][] = $key;
   $_memcache_statistics['bins'][] = $bin;
-  if ($mc = dmemcache_object($bin)) {
+  if ($mc || ($mc = dmemcache_object($bin))) {
     $full_key = dmemcache_key($key, $bin);
     if (!$mc->set($full_key, $value, MEMCACHE_COMPRESSED, $exp)) {
       return FALSE;
@@ -54,11 +54,11 @@ function dmemcache_set($key, $value, $ex
  *
  * @return The item which was originally saved or FALSE
  */
-function dmemcache_get($key, $bin = 'cache') {
+function dmemcache_get($key, $bin = 'cache', $mc = NULL) {
   global $_memcache_statistics;
   $_memcache_statistics['get'][] = $key;
   $_memcache_statistics['bins'][] = $bin;
-  if ($mc = dmemcache_object($bin)) {
+  if ($mc || ($mc = dmemcache_object($bin))) {
     $full_key = dmemcache_key($key, $bin);
     $result = $mc->get($full_key);
     if ($result) {
@@ -90,8 +90,8 @@ function dmemcache_get($key, $bin = 'cac
  *
  * @return Returns TRUE on success or FALSE on failure.
  */
-function dmemcache_delete($key, $bin = 'cache') {
-  if ($mc = dmemcache_object($bin)) {
+function dmemcache_delete($key, $bin = 'cache', $mc = NULL) {
+  if ($mc || ($mc = dmemcache_object($bin))) {
     $full_key = dmemcache_key($key, $bin);
     return $mc->delete($full_key);
   }
@@ -108,8 +108,8 @@ function dmemcache_delete($key, $bin = '
  *
  * @return Returns TRUE on success or FALSE on failure.
  */
-function dmemcache_flush($bin = 'cache') {
-  if ($mc = dmemcache_object($bin)) {
+function dmemcache_flush($bin = 'cache', $mc = NULL) {
+  if ($mc || ($mc = dmemcache_object($bin))) {
     return $mc->flush();
   }
 }
Index: memcache.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/memcache/memcache.inc,v
retrieving revision 1.15.2.8.2.8
diff -u -p -r1.15.2.8.2.8 memcache.inc
--- memcache.inc	4 Aug 2009 20:41:12 -0000	1.15.2.8.2.8
+++ memcache.inc	3 Dec 2009 15:49:04 -0000
@@ -5,169 +5,119 @@ require_once 'dmemcache.inc';
 
 /** Implementation of cache.inc with memcache logic included **/
 
-/**
- * Return data from the persistent cache.
- * 
- * Data may be stored as either plain text or as serialized data.
- * cache_get() will automatically return unserialized objects and arrays.
- *
- * @param $cid
- *   The cache ID of the data to retrieve.
- * @param $table
- *   The table $table to store the data in. Valid core values are 'cache_filter',
- *   'cache_menu', 'cache_page', or 'cache' for the default cache.
- */
-function cache_get($cid, $table = 'cache') {
-  // Determine when the current table was last flushed.
-  $cache_flush = variable_get("cache_flush_$table", 0);
-  // Retrieve the item from the cache.
-  $cache = dmemcache_get($cid, $table);
-  if (is_object($cache)) {
-    $cache_tables = isset($_SESSION['cache_flush']) ? $_SESSION['cache_flush'] : NULL;
-    // Items cached before the cache was last flushed are no longer valid.
-    $cache_lifetime = variable_get('cache_lifetime', 0);
-    if ($cache_lifetime && $cache->created && $cache_flush &&
-        ($cache->created < $cache_flush) &&
-        ((time() - $cache->created >= $cache_lifetime)) ||
-        (is_array($cache_tables) && $cache_tables[$table] &&
-        $cache_tables[$table] > $cache->created)) {
-      // Cache item expired, return NULL.
-      return 0;
+class MemCacheDrupal implements DrupalCacheInterface {
+  function __construct($bin) {
+    $this->memcache = dmemcache_object($bin);
+    $this->bin = $bin;
+  }
+  function get($cid) {
+    // Determine when the current bin was last flushed.
+    $cache_flush = variable_get("cache_flush_$this->bin", 0);
+    // Retrieve the item from the cache.
+    $cache = dmemcache_get($cid, $this->bin, $this->memcache);
+    if (is_object($cache)) {
+      $cache_bins = isset($_SESSION['cache_flush']) ? $_SESSION['cache_flush'] : NULL;
+      // Items cached before the cache was last flushed are no longer valid.
+      $cache_lifetime = variable_get('cache_lifetime', 0);
+      if ($cache_lifetime && $cache->created && $cache_flush &&
+          ($cache->created < $cache_flush) &&
+          ((time() - $cache->created >= $cache_lifetime)) ||
+          (is_array($cache_bins) && $cache_bins[$this->bin] &&
+          $cache_bins[$this->bin] > $cache->created)) {
+        // Cache item expired, return NULL.
+        return 0;
+      }
+      return $cache;
     }
-    return $cache;
+    return 0;
   }
-  return 0;
-}
-
-/**
- * Store data in memcache.
- *
- * @param $cid
- *   The cache ID of the data to store.
- * @param $data
- *   The data to store in the cache. Complex data types will be automatically
- *   serialized before insertion. Strings will be stored as plain text and 
- *   not serialized.
- * @param $table
- *   The table $table to store the data in. Valid core values are 'cache_filter',
- *   'cache_menu', 'cache_page', or 'cache'.
- * @param $expire
- *   One of the following values:
- *   - CACHE_PERMANENT: Indicates that the item should never be removed unless
- *     explicitly told to using cache_clear_all() with a cache ID.
- *   - CACHE_TEMPORARY: Indicates that the item should be removed at the next
- *     general cache wipe.
- *   - A Unix timestamp: Indicates that the item should be kept at least until
- *     the given time, after which it behaves like CACHE_TEMPORARY.
- * @param $headers
- *   A string containing HTTP header information for cached pages.
- */
-function cache_set($cid, $data, $table = 'cache', $expire = CACHE_PERMANENT, $headers = NULL) {
-  $created = time();
-
-  // Create new cache object.
-  $cache = new stdClass;
-  $cache->cid = $cid;
-  $cache->data = is_object($data) ? memcache_clone($data) : $data;
-  $cache->created = $created;
-  $cache->headers = $headers;
-  if ($expire == CACHE_TEMPORARY) {
-    // Convert CACHE_TEMPORARY (-1) into something that will live in memcache
-    // until the next flush.
-    $cache->expire = time() + 2591999;
-  }
-  // Expire time is in seconds if less than 30 days, otherwise is a timestamp.
-  else if ($expire != CACHE_PERMANENT && $expire < 2592000) {
-    // Expire is expressed in seconds, convert to the proper future timestamp
-    // as expected in dmemcache_get().
-    $cache->expire = time() + $expire;
-  }
-  else {
-    $cache->expire = $expire;
-  }
-
-  // We manually track the expire time in $cache->expire.  When the object
-  // expires, we only allow one request to rebuild it to avoid cache stampedes.
-  // Other requests for the expired object while it is still being rebuilt get
-  // the expired object.
-  dmemcache_set($cid, $cache, 0, $table);
-}
 
-/**
- *
- * Expire data from the cache. If called without arguments, expirable
- * entries will be cleared from the cache_page and cache_block tables.
- *
- * Memcache logic is simpler than the core cache because memcache doesn't have
- * a minimum cache lifetime consideration (it handles it internally), and 
- * doesn't support wildcards.  Wildcard flushes result in the entire table
- * being flushed.
- *
- * @param $cid
- *   If set, the cache ID to delete. Otherwise, all cache entries that can
- *   expire are deleted.
- *
- * @param $table
- *   If set, the table $table to delete from. Mandatory
- *   argument if $cid is set.
- *
- * @param $wildcard
- *   If set to TRUE, the $cid is treated as a substring
- *   to match rather than a complete ID. The match is a right hand
- *   match. If '*' is given as $cid, the table $table will be emptied.
- */
-function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
-  // Default behavior for when cache_clear_all() is called without parameters
-  // is to clear all of the expirable entries in the block and page caches.
-  if (!isset($cid) && !isset($table)) {
-    cache_clear_all('*', 'cache_block', TRUE);
-    cache_clear_all('*', 'cache_page', TRUE);
-    return;
-  }
-  if (empty($cid) || ($cid == '*' && $wildcard !== TRUE)) {
-    // don't do anything if cid is unset. this matches the default drupal behavior...
-    if ($wildcard && $cid != '*') {
-      if (variable_get('memcache_debug', FALSE)) {
-        // call watchdog, since you probably didn't want to flush the entire bin.
-        watchdog('memcache', "illegal wildcard in cache_clear_all - not flushing entire bin. table: $table. cid: $cid", WATCHDOG_WARNING);
+function getMultiple(&$cids) {
+    // With cache flushes and stampede protection it's impossible to do use
+    // the multiple get. Pity.
+    foreach ($cids as $key => $cid) {
+      if ($result = $this->get($cid)) {
+        $results[$key] = $result;
+        unset($cids[$key]);
       }
     }
   }
-  else if ($cid == '*' || $wildcard === TRUE) {
-    if (variable_get('cache_lifetime', 0)) {
-      // Update the timestamp of the last global flushing of this table.  When
-      // retrieving data from this table, we will compare the cache creation
-      // time minus the cache_flush time to the cache_lifetime to determine
-      // whether or not the cached item is still valid.
-      variable_set("cache_flush_$table", time());
-
-      // We store the time in the current user's session which is saved into
-      // the sessions table by sess_write().  We then simulate that the cache
-      // was flushed for this user by not returning cached data to this user
-      // that was cached before the timestamp.
-      if (is_array($_SESSION['cache_flush'])) {
-        $cache_tables = $_SESSION['cache_flush'];
+  function set($cid, $data, $expire = CACHE_PERMANENT, array $headers = NULL) {
+    $created = time();
+
+    // Create new cache object.
+    $cache = new stdClass;
+    $cache->cid = $cid;
+    $cache->data = is_object($data) ? clone $data : $data;
+    $cache->created = $created;
+    $cache->headers = $headers;
+    if ($expire == CACHE_TEMPORARY) {
+      // Convert CACHE_TEMPORARY (-1) into something that will live in memcache
+      // until the next flush.
+      $cache->expire = time() + 2591999;
+    }
+    // Expire time is in seconds if less than 30 days, otherwise is a timestamp.
+    else if ($expire != CACHE_PERMANENT && $expire < 2592000) {
+      // Expire is expressed in seconds, convert to the proper future timestamp
+      // as expected in dmemcache_get().
+      $cache->expire = time() + $expire;
+    }
+    else {
+      $cache->expire = $expire;
+    }
+
+    // We manually track the expire time in $cache->expire.  When the object
+    // expires, we only allow one request to rebuild it to avoid cache stampedes.
+    // Other requests for the expired object while it is still being rebuilt get
+    // the expired object.
+    dmemcache_set($cid, $cache, 0, $bin, $this->memcache);
+  }
+
+  function clear($cid = NULL, $wildcard = FALSE) {
+    // Default behavior for when cache_clear_all() is called without parameters
+    // is to clear all of the expirable entries in the block and page caches.
+    if (empty($cid) || ($cid == '*' && $wildcard !== TRUE)) {
+      // don't do anything if cid is unset. this matches the default drupal behavior...
+      if ($wildcard && $cid != '*') {
+        if (variable_get('memcache_debug', FALSE)) {
+          // call watchdog, since you probably didn't want to flush the entire bin.
+          watchdog('memcache', "illegal wildcard in cache_clear_all - not flushing entire bin. bin: $this->bin. cid: $cid", WATCHDOG_WARNING);
+        }
+      }
+    }
+    else if ($cid == '*' || $wildcard === TRUE) {
+      if (variable_get('cache_lifetime', 0)) {
+        // Update the timestamp of the last global flushing of this bin.  When
+        // retrieving data from this bin, we will compare the cache creation
+        // time minus the cache_flush time to the cache_lifetime to determine
+        // whether or not the cached item is still valid.
+        variable_set("cache_flush_$this->bin", time());
+
+        // We store the time in the current user's session which is saved into
+        // the sessions table by sess_write().  We then simulate that the cache
+        // was flushed for this user by not returning cached data to this user
+        // that was cached before the timestamp.
+        if (is_array($_SESSION['cache_flush'])) {
+          $cache_bins = $_SESSION['cache_flush'];
+        }
+        else {
+          $cache_bins = array();
+        }
+        $cache_bins[$this->bin] = time();
+        $_SESSION['cache_flush'] = $cache_bins;
       }
       else {
-        $cache_tables = array();
+        dmemcache_flush($this->bin, $this->memcache);
       }
-      $cache_tables[$table] = time();
-      $_SESSION['cache_flush'] = $cache_tables;
     }
     else {
-      dmemcache_flush($table);
+      dmemcache_delete($cid, $this->bin, $this->memcache);
     }
   }
-  else {
-    dmemcache_delete($cid, $table);
+  
+  function isEmpty() {
+    // We do not know so err on the safe side?
+    return FALSE;
   }
 }
 
-/**
- * Provide a substitute clone() function for PHP4. This is a copy of drupal_clone
- * because common.inc isn't included early enough in the bootstrap process to
- * be able to depend on drupal_clone.
- */
-function memcache_clone($object) {
-  return version_compare(phpversion(), '5.0') < 0 ? $object : clone($object);
-}
