default specific -> localhost port 11211 if (isset($conf['cacherouter'][$bin]['server'])) { $this->settings['servers'] = $conf['cacherouter'][$bin]['server']; $this->settings['compress'] = isset($conf['cacherouter'][$bin]['compress']) ? MEMCACHE_COMPRESSED : 0; $this->settings['shared'] = isset($conf['cacherouter'][$bin]['shared']) ? $conf['cacherouter'][$bin]['shared'] : TRUE; } else { if (isset($conf['cacherouter']['default']['server'])) { $this->settings['servers'] = $conf['cacherouter']['default']['server']; $this->settings['compress'] = isset($conf['cacherouter']['default']['compress']) ? MEMCACHE_COMPRESSED : 0; $this->settings['shared'] = isset($conf['cacherouter']['default']['shared']) ? $conf['cacherouter']['default']['shared'] : TRUE; } else { $this->settings['servers'] = array('localhost:11211'); $this->settings['compress'] = 0; $this->settings['shared'] = TRUE; } } parent::__construct($bin); $this->connect(); } function get($key) { // Attempt to pull from static cache. $cache = parent::get($key); if (isset($cache)) { return $cache; } // Get from memcache $cache = $this->memcache->get($this->key($key)); // Update static cache parent::set($key, $cache); return $cache; } function set($key, $value, $expire = CACHE_PERMENANT, $headers = NULL) { if ($expire == CACHE_TEMPORARY) { $expire = 180; } // Create new cache object. $cache = new stdClass; $cache->cid = $key; $cache->created = time(); $cache->expire = $expire; $cache->headers = $headers; $cache->data = $value; if (!empty($key) && !empty($value)) { if ($this->settings['shared']) { $this->lock(); // Get lookup table to be able to keep track of bins $lookup = $this->memcache->get($this->lookup); // If the lookup table is empty, initialize table if (empty($lookup)) { $lookup = array(); } // Get full key for storage and set it to 1 so we can keep track of the bin $full_key = $this->key($key); $lookup[$full_key] = 1; // Attempt to store full key and value if (!$this->memcache->set($full_key, $cache, $this->settings['compress'], $expire)) { unset($lookup[$full_key]); $return = FALSE; } else { // Update static cache parent::set($key, $cache); $return = TRUE; } // Resave the lookup table (even on failure) $this->memcache->set($this->lookup, $lookup, $this->settings['compress'], $expire); // Remove lock. $this->unlock(); } else { // Update memcache return $this->memcache->set($this->key($key), $cache, $this->settings['compress'], $expire); } } } function delete($key) { // Delete from static cache parent::delete($key); // Remove from memcache. return $this->memcache->delete($this->key($key)); } function flush() { // Flush static cache parent::flush(); // If this is a shared cache, we need to cycle through the lookup table and remove individual // items directly if ($this->settings['shared']) { $this->lock(); // Get lookup table to be able to keep track of bins $lookup = $this->memcache->get($this->lookup); // If the lookup table is empty, remove lock and return if (empty($lookup)) { $this->unlock(); return TRUE; } // Cycle through keys and remove each entry from the cache foreach ($lookup as $k => $v) { if ($this->memcache->delete($k)) { unset($lookup[$k]); } } // Resave the lookup table (even on failure) $this->memcache->set($this->lookup, $lookup, $this->settings['compress'], 0); // Remove lock $this->unlock(); } else { // Flush memcache return $this->memcache->flush(); } } function lock() { // Lock once by trying to add lock file, if we can't get the lock, we will loop // for 3 seconds attempting to get lock. If we still can't get it at that point, // then we give up and return FALSE. if ($this->memcache->add($this->lock, $this->settings['compress'], 0) === FALSE) { $time = time(); while ($this->memcache->add($this->lock, $this->settings['compress'], 0) === FALSE) { if (time() - $time >= 3) { return FALSE; } } } return TRUE; } function unlock() { return $this->memcache->delete($this->lock); } function connect() { $this->memcache =& new Memcache; foreach ($this->settings['servers'] as $server) { list($host, $port) = explode(':', $server); if (!$this->memcache->addServer($host, $port)) { drupal_set_message("Unable to connect to memcache server $host:$port"); } } } function close() { $this->memcache->close(); } }