<?php if (!defined('VB_ENTRY')) die('Access denied.'); class vB_Cache_APC extends vB_Cache { const LOCK_PREFIX = 'lock_'; protected static $instance; protected $events = array(); protected function __construct($cachetype) { parent::__construct($cachetype); $config = vB::getConfig(); if (empty($config['Cache']['apcprefix'])) { $this->prefix = TABLE_PREFIX; } else { $this->prefix = $config['Cache']['apcprefix']; } } public static function instance($type = NULL) { if (!isset(self::$instance)) { $class = __CLASS__; self::$instance = new $class($type); } return self::$instance; } protected function getEventTime($event) { return apc_fetch($this->prefix . $event); } protected function setEventTime($event, $time) { if ($time == 0) { apc_add($this->prefix . $event, $time); } else { apc_store($this->prefix . $event, $time); } } protected function writeCache($cache) { $ptitle = $this->prefix . $cache['key']; try { $this->lock($cache['key']); if (!apc_store($ptitle, $cache, $cache['expires'])) { $this->unlock($cache['key']); return; } if (!empty($cache['events'])) { foreach ($cache['events'] AS $event) { if (empty ($this->events[$event])) { $this->events[$event] = array(); } $this->events[$event][$cache['key']] = $cache['key']; if (!$this->getEventTime($event)) { apc_store($this->prefix . $event, 0); } } } } catch(Exception $e) { $this->unlock($cache['key']); } } protected function readCache($key) { $ptitle = $this->prefix . $key; $entry = apc_fetch($ptitle); if ($entry === false) { return false; } $lock = apc_fetch($this->prefix . self::LOCK_PREFIX . $key); if (!empty($entry['events'])) { foreach ($entry['events'] AS $event) { if (($time = $this->getEventTime($event)) !== false) { if ($time >= $entry['created']) { $this->expireCache($key); return false; } return $entry; } else { $this->expireCache($key); return false; } } } return $entry; } protected function purgeCache($key) { $ptitle = $this->prefix . $key; apc_delete($ptitle); return true; } protected function expireCache($keys) { if (!is_array($keys)) { $keys = array($keys); } foreach ($keys AS $key) { apc_delete($key); if (!empty($this->events[$key])) { foreach ($this->events[$key] AS $cacheKey) { unset($this->values_read[$cacheKey]); } } } } public function event($events) { $events = (array)$events; foreach ($events AS $key => $event) { $strEvent = strval($event); $events[$key] = $strEvent; $this->setEventTime($strEvent, $this->timeNow); if (!empty($this->events[$strEvent])) { foreach ($this->events[$strEvent] AS $cacheKey) { unset($this->values_read[$cacheKey]); } } } return $this; } public function lock($key) { $lock_expiration = max(array(ini_get('max_execution_time'),30)); return (apc_add($this->prefix . self::LOCK_PREFIX . $key, self::LOCK_PREFIX . $this->timeNow, $lock_expiration)); } public function unlock($key) { return (apc_delete($this->prefix . self::LOCK_PREFIX . $key)); } public function clean($only_expired = true) { if (!$only_expired) { $regex = '#^' . $this->prefix . '#'; apc_delete(new APCIterator('user', $regex, APC_ITER_VALUE)); $this->cleanNow(); $this->events = array(); if (self::$cacheLogging) { $this->logCacheAction(0, self::CACHE_LOG_CLEAR, $this->cachetype); } } } public function shutdown() { parent::shutdown(); } } 