Index: memcache.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/memcache/memcache.inc,v retrieving revision 1.28.2.15 diff -u -p -r1.28.2.15 memcache.inc --- memcache.inc 1 Oct 2010 14:25:27 -0000 1.28.2.15 +++ memcache.inc 4 Oct 2010 11:15:39 -0000 @@ -164,42 +164,6 @@ class MemCacheDrupal implements DrupalCa } /** - * We hash cids to keep them a consistent, managable length. Alternative algorithms - * can be specified if you're looking for better performance (benchmark first!). - * Hash collissions are not a big deal, simply leads to all collided items being - * flushed together. - */ - function hash_cid($cid) { - static $hashes = array(); - $memcache_hash = variable_get('memcache_hash', 'md5'); - if (function_exists($memcache_hash)) { - $hashes[$cid] = $memcache_hash($cid); - } - else { - $hashes[$cid] = $cid; - } - return $hashes[$cid]; - } - - /** - * Determine all possible hashes that could match our cid. We optimize away - * the overhead of checking all possible matches by using multiget. - */ - private function multihash_cid($cid) { - static $hashes = array(); - if (!isset($hashes[$this->bin])) { - $hashes[$this->bin] = array(); - } - if (!isset($hashes[$this->bin][$cid])) { - for ($i = 0; $i <= strlen($cid); $i++) { - $subcid = substr($cid, 0, $i); - $hashes[$this->bin][$cid][$subcid] = '.wildcard-'. $this->bin . $this->hash_cid($subcid); - } - } - return $hashes[$this->bin][$cid]; - } - - /** * Sum of all matching wildcards. Checking any single cache item's flush value * against this single-value sum tells us whether or not a new wildcard flush * has affected the cached item. @@ -215,46 +179,72 @@ class MemCacheDrupal implements DrupalCa */ private function wildcards($cid, $flush = FALSE) { static $wildcards = array(); + $result = array(); - // If this bin has never had a wildcard flush, or the last wildcard flush - // was more than a month ago, simply return an empty array to indicate that - // it has never been flushed and to avoid the overhead of a wildcard lookup. - if (!$flush && (!isset($this->wildcard_timestamps[$this->bin]) || - $this->wildcard_timestamps[$this->bin] <= (REQUEST_TIME - $this->invalidate))) { - return array(); - } + if (isset($this->wildcard_timestamps[$this->bin]) && is_array($this->wildcard_timestamps[$this->bin])) { + $multihash = array(); + + // Find statically cached wildcards, and generate further possible + // wildcards for this cid from wildcard lengths that are recorded + // as flushed in the past month. + foreach ($this->wildcard_timestamps[$this->bin] as $length => $timestamp) { + if ($timestamp >= (REQUEST_TIME - $this->invalidate)) { + $key = '.wildcard-' . $this->bin . substr($cid, 0, $length); + $wildcard = dmemcache_key($key, $this->bin); + if (isset($wildcards[$this->bin][$wildcard])) { + $result[$wildcard] = $wildcards[$this->bin][$wildcard]; + } + else { + $multihash[$wildcard] = $key; + } + } + } + + // Use getMulti to retrieve any possible but unknown wildcards. + if (!empty($multihash)) { + $multivalues = dmemcache_get_multi($multihash, $this->bin); + if (is_array($multivalues)) { + $result = array_merge($result, $multivalues); + if (isset($wildcards[$this->bin])) { + $wildcards[$this->bin] = array_merge($wildcards[$this->bin], $multivalues); + } + else { + $wildcards[$this->bin] = $multivalues; + } + $multihash = array_diff_key($multihash, $multivalues); + } - if (!isset($wildcards[$this->bin]) || !isset($wildcards[$this->bin][$cid])) { - $multihash = $this->multihash_cid($cid); - $wildcards[$this->bin][$cid] = dmemcache_get_multi($multihash, $this->bin); - if (!is_array($wildcards[$this->bin][$cid])) { - $wildcards[$this->bin][$cid] = array(); + // $multihash now contains only wildcards that were not in the cache. + foreach ($multihash as $wildcard => $key) { + $wildcards[$this->bin][$wildcard] = 0; + // Storing zero cache flushes makes the cache hit ratio look better, + // at the expense of using more cache space. + //dmemcache_set($key, 0, 0, $this->bin); + } } } if ($flush) { - if (!empty($cid)) { - // Avoid too many variable_set() by only recording a flush for - // a fraction of the wildcard invalidation variable. Defaults to - // 28 / 4 = one week. - if (!isset($this->wildcard_timestamps[$this->bin]) || - (REQUEST_TIME - $this->wildcard_timestamps[$this->bin] > $this->invalidate / 4)) { - $this->wildcard_timestamps[$this->bin] = REQUEST_TIME; - variable_set('memcache_wildcard_timestamps', $this->wildcard_timestamps); - } + // Avoid too many variable_set() by only recording a flush for + // a fraction of the wildcard invalidation variable. Defaults to + // 28 / 4 = one week. + $length = strlen($cid); + if (!isset($this->wildcard_timestamps[$this->bin][$length]) || + ($_SERVER['REQUEST_TIME'] - $this->wildcard_timestamps[$this->bin][$length] > $this->invalidate / 4)) { + $this->wildcard_timestamps = variable_get('memcache_wildcard_timestamps', array()); + $this->wildcard_timestamps[$this->bin][$length] = $_SERVER['REQUEST_TIME']; + variable_set('memcache_wildcard_timestamps', $this->wildcard_timestamps); } - $hash = $this->hash_cid($cid); - $wildcard = dmemcache_key('.wildcard-' . $this->bin . $hash, $this->bin); - if (isset($wildcards[$this->bin][$cid][$wildcard])) { - $mc = dmemcache_object($this->bin); - $mc->increment($wildcard); - $wildcards[$this->bin][$cid][$wildcard]++; + $wildcard = dmemcache_key('.wildcard-' . $this->bin . $cid, $this->bin); + if (isset($wildcards[$this->bin][$wildcard]) && $wildcards[$this->bin][$wildcard] != 0) { + $this->memcache->increment($wildcard); + $wildcards[$this->bin][$wildcard]++; } else { - $wildcards[$this->bin][$cid][$wildcard] = 1; - dmemcache_set('.wildcard-' . $this->bin . $hash, 1, 0, $this->bin); + $wildcards[$this->bin][$wildcard] = 1; + dmemcache_set('.wildcard-' . $this->bin . $cid, 1, 0, $this->bin); } } - return $wildcards[$this->bin][$cid]; + return $result; } /**