MemcacheBackend.php in Zircon Profile 8
Same filename and directory in other branches
Contains \Drupal\memcache\MemcacheBackend.
Namespace
Drupal\memcacheFile
modules/memcache/src/MemcacheBackend.phpView source
<?php
/**
* @file
* Contains \Drupal\memcache\MemcacheBackend.
*/
namespace Drupal\memcache;
use Drupal\Core\Site\Settings;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\Core\Lock\LockBackendInterface;
/**
* Defines a Memcache cache backend.
*/
class MemcacheBackend implements CacheBackendInterface {
/**
* The cache bin to use.
*
* @var string
*/
protected $bin;
/**
* The lock count.
*
* @var int
*/
protected $lockCount = 0;
/**
* The memcache wrapper object.
*
* @var \Drupal\memcache\DrupalMemcacheInterface
*/
protected $memcache;
/**
* The lock backend that should be used.
*
* @var \Drupal\Core\Lock\LockBackendInterface
*/
protected $lock;
/**
* The Settings instance.
*
* @var \Drupal\Core\Site\Settings
*/
protected $settings;
/**
* The cache tags checksum provider.
*
* @var \Drupal\Core\Cache\CacheTagsChecksumInterface
*/
protected $checksumProvider;
/**
* Constructs a MemcacheBackend object.
*\Drupal\Core\Site\Settings
* @param string $bin
* The bin name.
* @param \Drupal\memcache\DrupalMemcacheInterface $memcache
* The memcache object.
* @param \Drupal\Core\Lock\LockBackendInterface $lock
* The lock backend.
* @param \Drupal\Core\Site\Settings $settings
* The settings instance.
* @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
* The cache tags checksum service.
*/
public function __construct($bin, DrupalMemcacheInterface $memcache, LockBackendInterface $lock, Settings $settings, CacheTagsChecksumInterface $checksum_provider) {
$this->bin = $bin;
$this->memcache = $memcache;
$this->lock = $lock;
$this->settings = $settings;
$this->checksumProvider = $checksum_provider;
}
/**
* {@inheritdoc}
*/
public function get($cid, $allow_invalid = FALSE) {
$cids = array(
$cid,
);
$cache = $this
->getMultiple($cids, $allow_invalid);
return reset($cache);
}
/**
* {@inheritdoc}
*/
public function getMultiple(&$cids, $allow_invalid = FALSE) {
$cache = $this->memcache
->getMulti($cids);
foreach ($cache as $cid => $result) {
if (!$this
->valid($cid, $result) && !$allow_invalid) {
// This object has expired, so don't return it.
unset($cache[$cid]);
}
}
// Remove items from the referenced $cids array that we are returning,
// per comment in Drupal\Core\Cache\CacheBackendInterface::getMultiple().
$cids = array_diff($cids, array_keys($cache));
return $cache;
}
/**
* {@inheritdoc}
*/
protected function valid($cid, $cache) {
$lock_key = "memcache_{$cid}:{$this->bin}";
$cache->valid = FALSE;
if ($cache) {
// Items that have expired are invalid.
if (isset($cache->expire) && $cache->expire != CacheBackendInterface::CACHE_PERMANENT && $cache->expire <= REQUEST_TIME) {
// If the memcache_stampede_protection variable is set, allow one
// process to rebuild the cache entry while serving expired content to
// the rest.
if ($this->settings
->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->lock
->acquire($lock_key, $this->settings
->get('memcache_stampede_semaphore', 15))) {
$cache->valid = TRUE;
}
}
}
else {
$cache->valid = TRUE;
}
}
else {
if ($this->settings
->get('memcache_stampede_protection', FALSE) && !$this->lock
->acquire($lock_key, $this->settings
->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.
$this->lockCount++;
if ($this->lockCount <= $this->settings
->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).
$this->lock
->wait($lock_key, $this->settings
->get('memcache_stampede_wait_time', 5));
$cache = $this
->get($cid);
}
}
}
// Check if invalidateTags() has been called with any of the items's tags.
if (!$this->checksumProvider
->isValid($cache->checksum, $cache->tags)) {
$cache->valid = FALSE;
}
return (bool) $cache->valid;
}
/**
* {@inheritdoc}
*/
public function set($cid, $data, $expire = CacheBackendInterface::CACHE_PERMANENT, array $tags = array()) {
Cache::validateTags($tags);
$tags = array_unique($tags);
// Sort the cache tags so that they are stored consistently.
sort($tags);
// Create new cache object.
$cache = new \stdClass();
$cache->cid = $cid;
$cache->data = is_object($data) ? clone $data : $data;
$cache->created = round(microtime(TRUE), 3);
$cache->expire = $expire;
$cache->tags = $tags;
$cache->checksum = $this->checksumProvider
->getCurrentChecksum($tags);
// Cache all items permanently. We handle expiration in our own logic.
return $this->memcache
->set($cid, $cache);
}
/**
* {@inheritdoc}
*/
public function setMultiple(array $items) {
foreach ($items as $cid => $item) {
$item += array(
'expire' => CacheBackendInterface::CACHE_PERMANENT,
'tags' => array(),
);
$this
->set($cid, $item['data'], $item['expire'], $item['tags']);
}
}
/**
* {@inheritdoc}
*/
public function delete($cid) {
$this->memcache
->delete($cid);
}
/**
* {@inheritdoc}
*/
public function deleteMultiple(array $cids) {
foreach ($cids as $cid) {
$this->memcache
->delete($cid);
}
}
/**
* {@inheritdoc}
*/
public function deleteAll() {
// Invalidate all keys, as we can't actually delete all?
$this
->invalidateAll();
}
/**
* {@inheritdoc}
*/
public function invalidate($cid) {
$this
->invalidateMultiple((array) $cid);
}
/**
* Marks cache items as invalid.
*
* Invalid items may be returned in later calls to get(), if the
* $allow_invalid argument is TRUE.
*
* @param string $cids
* An array of cache IDs to invalidate.
*
* @see Drupal\Core\Cache\CacheBackendInterface::deleteMultiple()
* @see Drupal\Core\Cache\CacheBackendInterface::invalidate()
* @see Drupal\Core\Cache\CacheBackendInterface::invalidateTags()
* @see Drupal\Core\Cache\CacheBackendInterface::invalidateAll()
*/
public function invalidateMultiple(array $cids) {
foreach ($cids as $cid) {
if ($item = $this
->get($cid)) {
$item->expire = REQUEST_TIME - 1;
$this->memcache
->set($cid, $item);
}
}
}
/**
* {@inheritdoc}
*/
public function invalidateAll() {
$this->memcache
->flush();
}
/**
* {@inheritdoc}
*/
public function invalidateTags(array $tags) {
$this->checksumProvider
->invalidateTags($tags);
}
/**
* {@inheritdoc}
*/
public function removeBin() {
// Do nothing here too?
}
/**
* {@inheritdoc}
*/
public function garbageCollection() {
// Memcache will invalidate items; That items memory allocation is then
// freed up and reused. So nothing needs to be deleted/cleaned up here.
}
/**
* (@inheritdoc)
*/
public function isEmpty() {
// We do not know so err on the safe side? Not sure if we can know this?
return TRUE;
}
}
Classes
Name | Description |
---|---|
MemcacheBackend | Defines a Memcache cache backend. |