summaryrefslogtreecommitdiff
path: root/system/libraries/drivers/Cache
diff options
context:
space:
mode:
Diffstat (limited to 'system/libraries/drivers/Cache')
-rw-r--r--system/libraries/drivers/Cache/Apc.php64
-rw-r--r--system/libraries/drivers/Cache/Eaccelerator.php66
-rw-r--r--system/libraries/drivers/Cache/File.php261
-rw-r--r--system/libraries/drivers/Cache/Memcache.php191
-rw-r--r--system/libraries/drivers/Cache/Sqlite.php257
-rw-r--r--system/libraries/drivers/Cache/Xcache.php119
6 files changed, 958 insertions, 0 deletions
diff --git a/system/libraries/drivers/Cache/Apc.php b/system/libraries/drivers/Cache/Apc.php
new file mode 100644
index 00000000..f7be048f
--- /dev/null
+++ b/system/libraries/drivers/Cache/Apc.php
@@ -0,0 +1,64 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * APC-based Cache driver.
+ *
+ * $Id: Apc.php 4046 2009-03-05 19:23:29Z Shadowhand $
+ *
+ * @package Cache
+ * @author Kohana Team
+ * @copyright (c) 2007-2008 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Cache_Apc_Driver implements Cache_Driver {
+
+ public function __construct()
+ {
+ if ( ! extension_loaded('apc'))
+ throw new Kohana_Exception('cache.extension_not_loaded', 'apc');
+ }
+
+ public function get($id)
+ {
+ return (($return = apc_fetch($id)) === FALSE) ? NULL : $return;
+ }
+
+ public function set($id, $data, array $tags = NULL, $lifetime)
+ {
+ if ( ! empty($tags))
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+ }
+
+ return apc_store($id, $data, $lifetime);
+ }
+
+ public function find($tag)
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+
+ return array();
+ }
+
+ public function delete($id, $tag = FALSE)
+ {
+ if ($tag === TRUE)
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
+ return FALSE;
+ }
+ elseif ($id === TRUE)
+ {
+ return apc_clear_cache('user');
+ }
+ else
+ {
+ return apc_delete($id);
+ }
+ }
+
+ public function delete_expired()
+ {
+ return TRUE;
+ }
+
+} // End Cache APC Driver \ No newline at end of file
diff --git a/system/libraries/drivers/Cache/Eaccelerator.php b/system/libraries/drivers/Cache/Eaccelerator.php
new file mode 100644
index 00000000..a45616d5
--- /dev/null
+++ b/system/libraries/drivers/Cache/Eaccelerator.php
@@ -0,0 +1,66 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Eaccelerator-based Cache driver.
+ *
+ * $Id: Eaccelerator.php 4046 2009-03-05 19:23:29Z Shadowhand $
+ *
+ * @package Cache
+ * @author Kohana Team
+ * @copyright (c) 2007-2008 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Cache_Eaccelerator_Driver implements Cache_Driver {
+
+ public function __construct()
+ {
+ if ( ! extension_loaded('eaccelerator'))
+ throw new Kohana_Exception('cache.extension_not_loaded', 'eaccelerator');
+ }
+
+ public function get($id)
+ {
+ return eaccelerator_get($id);
+ }
+
+ public function find($tag)
+ {
+ Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+
+ return array();
+ }
+
+ public function set($id, $data, array $tags = NULL, $lifetime)
+ {
+ if ( ! empty($tags))
+ {
+ Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+ }
+
+ return eaccelerator_put($id, $data, $lifetime);
+ }
+
+ public function delete($id, $tag = FALSE)
+ {
+ if ($tag === TRUE)
+ {
+ Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
+ return FALSE;
+ }
+ elseif ($id === TRUE)
+ {
+ return eaccelerator_clean();
+ }
+ else
+ {
+ return eaccelerator_rm($id);
+ }
+ }
+
+ public function delete_expired()
+ {
+ eaccelerator_gc();
+
+ return TRUE;
+ }
+
+} // End Cache eAccelerator Driver \ No newline at end of file
diff --git a/system/libraries/drivers/Cache/File.php b/system/libraries/drivers/Cache/File.php
new file mode 100644
index 00000000..cc9d48d3
--- /dev/null
+++ b/system/libraries/drivers/Cache/File.php
@@ -0,0 +1,261 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * File-based Cache driver.
+ *
+ * $Id: File.php 4046 2009-03-05 19:23:29Z Shadowhand $
+ *
+ * @package Cache
+ * @author Kohana Team
+ * @copyright (c) 2007-2008 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Cache_File_Driver implements Cache_Driver {
+
+ protected $directory = '';
+
+ /**
+ * Tests that the storage location is a directory and is writable.
+ */
+ public function __construct($directory)
+ {
+ // Find the real path to the directory
+ $directory = str_replace('\\', '/', realpath($directory)).'/';
+
+ // Make sure the cache directory is writable
+ if ( ! is_dir($directory) OR ! is_writable($directory))
+ throw new Kohana_Exception('cache.unwritable', $directory);
+
+ // Directory is valid
+ $this->directory = $directory;
+ }
+
+ /**
+ * Finds an array of files matching the given id or tag.
+ *
+ * @param string cache id or tag
+ * @param bool search for tags
+ * @return array of filenames matching the id or tag
+ */
+ public function exists($id, $tag = FALSE)
+ {
+ if ($id === TRUE)
+ {
+ // Find all the files
+ return glob($this->directory.'*~*~*');
+ }
+ elseif ($tag === TRUE)
+ {
+ // Find all the files that have the tag name
+ $paths = glob($this->directory.'*~*'.$id.'*~*');
+
+ // Find all tags matching the given tag
+ $files = array();
+ foreach ($paths as $path)
+ {
+ // Split the files
+ $tags = explode('~', basename($path));
+
+ // Find valid tags
+ if (count($tags) !== 3 OR empty($tags[1]))
+ continue;
+
+ // Split the tags by plus signs, used to separate tags
+ $tags = explode('+', $tags[1]);
+
+ if (in_array($tag, $tags))
+ {
+ // Add the file to the array, it has the requested tag
+ $files[] = $path;
+ }
+ }
+
+ return $files;
+ }
+ else
+ {
+ // Find the file matching the given id
+ return glob($this->directory.$id.'~*');
+ }
+ }
+
+ /**
+ * Sets a cache item to the given data, tags, and lifetime.
+ *
+ * @param string cache id to set
+ * @param string data in the cache
+ * @param array cache tags
+ * @param integer lifetime
+ * @return bool
+ */
+ public function set($id, $data, array $tags = NULL, $lifetime)
+ {
+ // Remove old cache files
+ $this->delete($id);
+
+ // Cache File driver expects unix timestamp
+ if ($lifetime !== 0)
+ {
+ $lifetime += time();
+ }
+
+ if ( ! empty($tags))
+ {
+ // Convert the tags into a string list
+ $tags = implode('+', $tags);
+ }
+
+ // Write out a serialized cache
+ return (bool) file_put_contents($this->directory.$id.'~'.$tags.'~'.$lifetime, serialize($data));
+ }
+
+ /**
+ * Finds an array of ids for a given tag.
+ *
+ * @param string tag name
+ * @return array of ids that match the tag
+ */
+ public function find($tag)
+ {
+ // An array will always be returned
+ $result = array();
+
+ if ($paths = $this->exists($tag, TRUE))
+ {
+ // Length of directory name
+ $offset = strlen($this->directory);
+
+ // Find all the files with the given tag
+ foreach ($paths as $path)
+ {
+ // Get the id from the filename
+ list($id, $junk) = explode('~', basename($path), 2);
+
+ if (($data = $this->get($id)) !== FALSE)
+ {
+ // Add the result to the array
+ $result[$id] = $data;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Fetches a cache item. This will delete the item if it is expired or if
+ * the hash does not match the stored hash.
+ *
+ * @param string cache id
+ * @return mixed|NULL
+ */
+ public function get($id)
+ {
+ if ($file = $this->exists($id))
+ {
+ // Use the first file
+ $file = current($file);
+
+ // Validate that the cache has not expired
+ if ($this->expired($file))
+ {
+ // Remove this cache, it has expired
+ $this->delete($id);
+ }
+ else
+ {
+ // Turn off errors while reading the file
+ $ER = error_reporting(0);
+
+ if (($data = file_get_contents($file)) !== FALSE)
+ {
+ // Unserialize the data
+ $data = unserialize($data);
+ }
+ else
+ {
+ // Delete the data
+ unset($data);
+ }
+
+ // Turn errors back on
+ error_reporting($ER);
+ }
+ }
+
+ // Return NULL if there is no data
+ return isset($data) ? $data : NULL;
+ }
+
+ /**
+ * Deletes a cache item by id or tag
+ *
+ * @param string cache id or tag, or TRUE for "all items"
+ * @param boolean use tags
+ * @return boolean
+ */
+ public function delete($id, $tag = FALSE)
+ {
+ $files = $this->exists($id, $tag);
+
+ if (empty($files))
+ return FALSE;
+
+ // Disable all error reporting while deleting
+ $ER = error_reporting(0);
+
+ foreach ($files as $file)
+ {
+ // Remove the cache file
+ if ( ! unlink($file))
+ Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
+ }
+
+ // Turn on error reporting again
+ error_reporting($ER);
+
+ return TRUE;
+ }
+
+ /**
+ * Deletes all cache files that are older than the current time.
+ *
+ * @return void
+ */
+ public function delete_expired()
+ {
+ if ($files = $this->exists(TRUE))
+ {
+ // Disable all error reporting while deleting
+ $ER = error_reporting(0);
+
+ foreach ($files as $file)
+ {
+ if ($this->expired($file))
+ {
+ // The cache file has already expired, delete it
+ if ( ! unlink($file))
+ Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
+ }
+ }
+
+ // Turn on error reporting again
+ error_reporting($ER);
+ }
+ }
+
+ /**
+ * Check if a cache file has expired by filename.
+ *
+ * @param string filename
+ * @return bool
+ */
+ protected function expired($file)
+ {
+ // Get the expiration time
+ $expires = (int) substr($file, strrpos($file, '~') + 1);
+
+ // Expirations of 0 are "never expire"
+ return ($expires !== 0 AND $expires <= time());
+ }
+
+} // End Cache File Driver \ No newline at end of file
diff --git a/system/libraries/drivers/Cache/Memcache.php b/system/libraries/drivers/Cache/Memcache.php
new file mode 100644
index 00000000..d801de9c
--- /dev/null
+++ b/system/libraries/drivers/Cache/Memcache.php
@@ -0,0 +1,191 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Memcache-based Cache driver.
+ *
+ * $Id: Memcache.php 4102 2009-03-19 12:55:54Z Shadowhand $
+ *
+ * @package Cache
+ * @author Kohana Team
+ * @copyright (c) 2007-2008 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Cache_Memcache_Driver implements Cache_Driver {
+
+ const TAGS_KEY = 'memcache_tags_array';
+
+ // Cache backend object and flags
+ protected $backend;
+ protected $flags;
+
+ // Tags array
+ protected static $tags;
+
+ // Have the tags been changed?
+ protected static $tags_changed = FALSE;
+
+ public function __construct()
+ {
+ if ( ! extension_loaded('memcache'))
+ throw new Kohana_Exception('cache.extension_not_loaded', 'memcache');
+
+ $this->backend = new Memcache;
+ $this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : FALSE;
+
+ $servers = Kohana::config('cache_memcache.servers');
+
+ foreach ($servers as $server)
+ {
+ // Make sure all required keys are set
+ $server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => FALSE);
+
+ // Add the server to the pool
+ $this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'])
+ or Kohana::log('error', 'Cache: Connection failed: '.$server['host']);
+ }
+
+ // Load tags
+ self::$tags = $this->backend->get(self::TAGS_KEY);
+
+ if ( ! is_array(self::$tags))
+ {
+ // Create a new tags array
+ self::$tags = array();
+
+ // Tags have been created
+ self::$tags_changed = TRUE;
+ }
+ }
+
+ public function __destruct()
+ {
+ if (self::$tags_changed === TRUE)
+ {
+ // Save the tags
+ $this->backend->set(self::TAGS_KEY, self::$tags, $this->flags, 0);
+
+ // Tags are now unchanged
+ self::$tags_changed = FALSE;
+ }
+ }
+
+ public function find($tag)
+ {
+ if (isset(self::$tags[$tag]) AND $results = $this->backend->get(self::$tags[$tag]))
+ {
+ // Return all the found caches
+ return $results;
+ }
+ else
+ {
+ // No matching tags
+ return array();
+ }
+ }
+
+ public function get($id)
+ {
+ return (($return = $this->backend->get($id)) === FALSE) ? NULL : $return;
+ }
+
+ public function set($id, $data, array $tags = NULL, $lifetime)
+ {
+ if ( ! empty($tags))
+ {
+ // Tags will be changed
+ self::$tags_changed = TRUE;
+
+ foreach ($tags as $tag)
+ {
+ // Add the id to each tag
+ self::$tags[$tag][$id] = $id;
+ }
+ }
+
+ if ($lifetime !== 0)
+ {
+ // Memcache driver expects unix timestamp
+ $lifetime += time();
+ }
+
+ // Set a new value
+ return $this->backend->set($id, $data, $this->flags, $lifetime);
+ }
+
+ public function delete($id, $tag = FALSE)
+ {
+ // Tags will be changed
+ self::$tags_changed = TRUE;
+
+ if ($id === TRUE)
+ {
+ if ($status = $this->backend->flush())
+ {
+ // Remove all tags, all items have been deleted
+ self::$tags = array();
+
+ // We must sleep after flushing, or overwriting will not work!
+ // @see http://php.net/manual/en/function.memcache-flush.php#81420
+ sleep(1);
+ }
+
+ return $status;
+ }
+ elseif ($tag === TRUE)
+ {
+ if (isset(self::$tags[$id]))
+ {
+ foreach (self::$tags[$id] as $_id)
+ {
+ // Delete each id in the tag
+ $this->backend->delete($_id);
+ }
+
+ // Delete the tag
+ unset(self::$tags[$id]);
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ foreach (self::$tags as $tag => $_ids)
+ {
+ if (isset(self::$tags[$tag][$id]))
+ {
+ // Remove the id from the tags
+ unset(self::$tags[$tag][$id]);
+ }
+ }
+
+ return $this->backend->delete($id);
+ }
+ }
+
+ public function delete_expired()
+ {
+ // Tags will be changed
+ self::$tags_changed = TRUE;
+
+ foreach (self::$tags as $tag => $_ids)
+ {
+ foreach ($_ids as $id)
+ {
+ if ( ! $this->backend->get($id))
+ {
+ // This id has disappeared, delete it from the tags
+ unset(self::$tags[$tag][$id]);
+ }
+ }
+
+ if (empty(self::$tags[$tag]))
+ {
+ // The tag no longer has any valid ids
+ unset(self::$tags[$tag]);
+ }
+ }
+
+ // Memcache handles garbage collection internally
+ return TRUE;
+ }
+
+} // End Cache Memcache Driver
diff --git a/system/libraries/drivers/Cache/Sqlite.php b/system/libraries/drivers/Cache/Sqlite.php
new file mode 100644
index 00000000..9458d851
--- /dev/null
+++ b/system/libraries/drivers/Cache/Sqlite.php
@@ -0,0 +1,257 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * SQLite-based Cache driver.
+ *
+ * $Id: Sqlite.php 4046 2009-03-05 19:23:29Z Shadowhand $
+ *
+ * @package Cache
+ * @author Kohana Team
+ * @copyright (c) 2007-2008 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Cache_Sqlite_Driver implements Cache_Driver {
+
+ // SQLite database instance
+ protected $db;
+
+ // Database error messages
+ protected $error;
+
+ /**
+ * Logs an SQLite error.
+ */
+ protected static function log_error($code)
+ {
+ // Log an error
+ Kohana::log('error', 'Cache: SQLite error: '.sqlite_error_string($error));
+ }
+
+ /**
+ * Tests that the storage location is a directory and is writable.
+ */
+ public function __construct($filename)
+ {
+ // Get the directory name
+ $directory = str_replace('\\', '/', realpath(pathinfo($filename, PATHINFO_DIRNAME))).'/';
+
+ // Set the filename from the real directory path
+ $filename = $directory.basename($filename);
+
+ // Make sure the cache directory is writable
+ if ( ! is_dir($directory) OR ! is_writable($directory))
+ throw new Kohana_Exception('cache.unwritable', $directory);
+
+ // Make sure the cache database is writable
+ if (is_file($filename) AND ! is_writable($filename))
+ throw new Kohana_Exception('cache.unwritable', $filename);
+
+ // Open up an instance of the database
+ $this->db = new SQLiteDatabase($filename, '0666', $error);
+
+ // Throw an exception if there's an error
+ if ( ! empty($error))
+ throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
+
+ $query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'";
+ $tables = $this->db->query($query, SQLITE_BOTH, $error);
+
+ // Throw an exception if there's an error
+ if ( ! empty($error))
+ throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
+
+ if ($tables->numRows() == 0)
+ {
+ Kohana::log('error', 'Cache: Initializing new SQLite cache database');
+
+ // Issue a CREATE TABLE command
+ $this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema'));
+ }
+ }
+
+ /**
+ * Checks if a cache id is already set.
+ *
+ * @param string cache id
+ * @return boolean
+ */
+ public function exists($id)
+ {
+ // Find the id that matches
+ $query = "SELECT id FROM caches WHERE id = '$id'";
+
+ return ($this->db->query($query)->numRows() > 0);
+ }
+
+ /**
+ * Sets a cache item to the given data, tags, and lifetime.
+ *
+ * @param string cache id to set
+ * @param string data in the cache
+ * @param array cache tags
+ * @param integer lifetime
+ * @return bool
+ */
+ public function set($id, $data, array $tags = NULL, $lifetime)
+ {
+ // Serialize and escape the data
+ $data = sqlite_escape_string(serialize($data));
+
+ if ( ! empty($tags))
+ {
+ // Escape the tags, adding brackets so the tag can be explicitly matched
+ $tags = sqlite_escape_string('<'.implode('>,<', $tags).'>');
+ }
+
+ // Cache Sqlite driver expects unix timestamp
+ if ($lifetime !== 0)
+ {
+ $lifetime += time();
+ }
+
+ $query = $this->exists($id)
+ ? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
+ : "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')";
+
+ // Run the query
+ $this->db->unbufferedQuery($query, SQLITE_BOTH, $error);
+
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ /**
+ * Finds an array of ids for a given tag.
+ *
+ * @param string tag name
+ * @return array of ids that match the tag
+ */
+ public function find($tag)
+ {
+ $query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'";
+ $query = $this->db->query($query, SQLITE_BOTH, $error);
+
+ // An array will always be returned
+ $result = array();
+
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ }
+ elseif ($query->numRows() > 0)
+ {
+ // Disable notices for unserializing
+ $ER = error_reporting(~E_NOTICE);
+
+ while ($row = $query->fetchObject())
+ {
+ // Add each cache to the array
+ $result[$row->id] = unserialize($row->cache);
+ }
+
+ // Turn notices back on
+ error_reporting($ER);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Fetches a cache item. This will delete the item if it is expired or if
+ * the hash does not match the stored hash.
+ *
+ * @param string cache id
+ * @return mixed|NULL
+ */
+ public function get($id)
+ {
+ $query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1";
+ $query = $this->db->query($query, SQLITE_BOTH, $error);
+
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ }
+ elseif ($cache = $query->fetchObject())
+ {
+ // Make sure the expiration is valid and that the hash matches
+ if ($cache->expiration != 0 AND $cache->expiration <= time())
+ {
+ // Cache is not valid, delete it now
+ $this->delete($cache->id);
+ }
+ else
+ {
+ // Disable notices for unserializing
+ $ER = error_reporting(~E_NOTICE);
+
+ // Return the valid cache data
+ $data = $cache->cache;
+
+ // Turn notices back on
+ error_reporting($ER);
+ }
+ }
+
+ // No valid cache found
+ return NULL;
+ }
+
+ /**
+ * Deletes a cache item by id or tag
+ *
+ * @param string cache id or tag, or TRUE for "all items"
+ * @param bool delete a tag
+ * @return bool
+ */
+ public function delete($id, $tag = FALSE)
+ {
+ if ($id === TRUE)
+ {
+ // Delete all caches
+ $where = '1';
+ }
+ elseif ($tag === TRUE)
+ {
+ // Delete by tag
+ $where = "tags LIKE '%<{$id}>%'";
+ }
+ else
+ {
+ // Delete by id
+ $where = "id = '$id'";
+ }
+
+ $this->db->unbufferedQuery('DELETE FROM caches WHERE '.$where, SQLITE_BOTH, $error);
+
+ if ( ! empty($error))
+ {
+ self::log_error($error);
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+
+ /**
+ * Deletes all cache files that are older than the current time.
+ */
+ public function delete_expired()
+ {
+ // Delete all expired caches
+ $query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= '.time();
+
+ $this->db->unbufferedQuery($query);
+
+ return TRUE;
+ }
+
+} // End Cache SQLite Driver \ No newline at end of file
diff --git a/system/libraries/drivers/Cache/Xcache.php b/system/libraries/drivers/Cache/Xcache.php
new file mode 100644
index 00000000..6254bbb6
--- /dev/null
+++ b/system/libraries/drivers/Cache/Xcache.php
@@ -0,0 +1,119 @@
+<?php defined('SYSPATH') OR die('No direct access allowed.');
+/**
+ * Xcache Cache driver.
+ *
+ * $Id: Xcache.php 4046 2009-03-05 19:23:29Z Shadowhand $
+ *
+ * @package Cache
+ * @author Kohana Team
+ * @copyright (c) 2007-2008 Kohana Team
+ * @license http://kohanaphp.com/license.html
+ */
+class Cache_Xcache_Driver implements Cache_Driver {
+
+ public function __construct()
+ {
+ if ( ! extension_loaded('xcache'))
+ throw new Kohana_Exception('cache.extension_not_loaded', 'xcache');
+ }
+
+ public function get($id)
+ {
+ if (xcache_isset($id))
+ return xcache_get($id);
+
+ return NULL;
+ }
+
+ public function set($id, $data, array $tags = NULL, $lifetime)
+ {
+ if ( ! empty($tags))
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
+ }
+
+ return xcache_set($id, $data, $lifetime);
+ }
+
+ public function find($tag)
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
+ return FALSE;
+ }
+
+ public function delete($id, $tag = FALSE)
+ {
+ if ($tag !== FALSE)
+ {
+ Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
+ return TRUE;
+ }
+ elseif ($id !== TRUE)
+ {
+ if (xcache_isset($id))
+ return xcache_unset($id);
+
+ return FALSE;
+ }
+ else
+ {
+ // Do the login
+ $this->auth();
+ $result = TRUE;
+ for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++)
+ {
+ if (xcache_clear_cache(XC_TYPE_VAR, $i) !== NULL)
+ {
+ $result = FALSE;
+ break;
+ }
+ }
+
+ // Undo the login
+ $this->auth(TRUE);
+ return $result;
+ }
+
+ return TRUE;
+ }
+
+ public function delete_expired()
+ {
+ return TRUE;
+ }
+
+ private function auth($reverse = FALSE)
+ {
+ static $backup = array();
+
+ $keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW');
+
+ foreach ($keys as $key)
+ {
+ if ($reverse)
+ {
+ if (isset($backup[$key]))
+ {
+ $_SERVER[$key] = $backup[$key];
+ unset($backup[$key]);
+ }
+ else
+ {
+ unset($_SERVER[$key]);
+ }
+ }
+ else
+ {
+ $value = getenv($key);
+
+ if ( ! empty($value))
+ {
+ $backup[$key] = $value;
+ }
+
+ $_SERVER[$key] = Kohana::config('cache_xcache.'.$key);
+ }
+ }
+ }
+
+} // End Cache Xcache Driver