protected function MemCacheDrupal::valid in Memcache API and Integration 7
Checks if a retrieved cache item is valid.
Parameters
string $cid: The cache id of the item
mixed $cache: The cache item, which will be updated if needed.
Return value
bool Whether the item is valid.
2 calls to MemCacheDrupal::valid()
- MemCacheDrupal::get in ./
memcache.inc - Implements DrupalCacheInterface::get().
- MemCacheDrupal::getMultiple in ./
memcache.inc - Implements DrupalCacheInterface::getMultiple().
File
- ./
memcache.inc, line 123
Class
- MemCacheDrupal
- Implementation of cache.inc with memcache logic included
Code
protected function valid($cid, &$cache) {
if ($cache) {
// Legacy support
if (!isset($cache->expire)) {
$cache->expire = CACHE_TEMPORARY;
}
if (!isset($cache->created)) {
$cache->created = 0;
}
// Session storage is used to simulate a cache clear for the current user
// when cache_lifetime is greater than 0.
$cache_tables = isset($_SESSION['cache_flush']) ? $_SESSION['cache_flush'] : NULL;
// Items that have expired are invalid. This includes CACHE_TEMPORARY
// items that were set prior to the last garbage collection, and
// timestamp set items.
//
// Test whether this cache has been garbage collected (general cache
// flush) longer ago than the cache_lifetime setting.
$cache_garbage_collected = $cache->created + $this->cache_lifetime <= $this->cache_temporary_flush;
// Depending on value of memcache_expire_wait_gc, test if a timestamp
// cached item has expired:
// If memcache_expired_wait_gc is true, this includes any timestamp items
// that expired more than cache_lifetime seconds before the last garbage
// collection. If memcache_expire_wait_gc is false, this includes any
// items that expired before present time.
$cache_timestamp_expired = variable_get('memcache_expire_wait_gc', FALSE) ? $cache->expire + $this->cache_lifetime <= $this->cache_temporary_flush : $cache->expire <= REQUEST_TIME;
// Test for expired items.
if ($cache->expire == CACHE_TEMPORARY && $cache_garbage_collected || $cache->expire > 0 && $cache_timestamp_expired) {
// If the memcache_stampede_protection variable is set, allow one
// process to rebuild the cache entry while serving expired content to
// the rest. Note that core happily returns expired cache items as valid
// and relies on cron to expire them, but this is mostly reliant on its
// use of CACHE_TEMPORARY which does not map well to memcache.
// @see http://drupal.org/node/534092
if (variable_get('memcache_stampede_protection', FALSE)) {
// The process that acquires the lock will get a cache miss, all
// others will get a cache hit.
if ($this
->lockInit() && $this
->stampedeProtected($cid) && lock_acquire("memcache_{$cid}:{$this->bin}", variable_get('memcache_stampede_semaphore', 15))) {
$cache = FALSE;
}
}
else {
$cache = FALSE;
}
}
elseif ($cache->created <= $this->cache_flush) {
$cache = FALSE;
}
elseif ($cache->expire != CACHE_PERMANENT && $cache->created + $this->cache_lifetime <= $this->cache_content_flush) {
$cache = FALSE;
}
elseif ($cache->expire != CACHE_PERMANENT && is_array($cache_tables) && isset($cache_tables[$this->bin]) && $cache_tables[$this->bin] >= $cache->created) {
// Cache item expired, return FALSE.
$cache = FALSE;
}
else {
if (!$this
->wildcardValid($cid, $cache)) {
$cache = FALSE;
}
}
}
// On cache misses, attempt to avoid stampedes when the
// memcache_stampede_protection variable is enabled.
if (!$cache) {
if (variable_get('memcache_stampede_protection', FALSE) && $this
->lockInit() && $this
->stampedeProtected($cid) && !lock_acquire("memcache_{$cid}:{$this->bin}", variable_get('memcache_stampede_semaphore', 15))) {
// Prevent any single request from waiting more than three times due to
// stampede protection. By default this is a maximum total wait of 15
// seconds. This accounts for two possibilities - a cache and lock miss
// more than once for the same item. Or a cache and lock miss for
// different items during the same request.
// @todo: it would be better to base this on time waited rather than
// number of waits, but the lock API does not currently provide this
// information. Currently the limit will kick in for three waits of 25ms
// or three waits of 5000ms.
static $lock_count = 0;
$lock_count++;
if ($lock_count <= variable_get('memcache_stampede_wait_limit', 3)) {
// The memcache_stampede_semaphore variable was used in previous
// releases of memcache, but the max_wait variable was not, so by
// default divide the semaphore value by 3 (5 seconds).
lock_wait("memcache_{$cid}:{$this->bin}", variable_get('memcache_stampede_wait_time', 5));
$cache = $this
->get($cid);
}
}
}
$valid = (bool) $cache;
if (variable_get('memcache_pagecache_header', FALSE) && $this->bin == 'cache_page') {
// Per RFC-6648, don't start with X-
$header = t('Drupal-Pagecache-Memcache: !status', array(
'!status' => $valid ? t('HIT') : t('MISS'),
));
if ($valid) {
$header .= t(', age=!age', array(
'!age' => REQUEST_TIME - $cache->created,
));
}
header($header);
}
return $valid;
}