Added Kohana v3.0.9
This commit is contained in:
61
includes/kohana/modules/cache/README.md
vendored
Normal file
61
includes/kohana/modules/cache/README.md
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
Kohana Cache library
|
||||
====================
|
||||
|
||||
The cache library for Kohana 3 provides a simple interface to the most common cache solutions. Developers are free to add their own caching solutions that follow the cache design pattern defined within this module.
|
||||
|
||||
Supported cache solutions
|
||||
-------------------------
|
||||
|
||||
Currently this module supports the following cache methods.
|
||||
|
||||
1. APC
|
||||
2. eAccelerator
|
||||
3. Memcache
|
||||
4. Memcached-tags (Supports tags)
|
||||
5. SQLite (Supports tags)
|
||||
6. File
|
||||
7. Xcache
|
||||
8. Wincache
|
||||
|
||||
Planned support
|
||||
---------------
|
||||
|
||||
In the near future, additional support for the following methods will be included.
|
||||
|
||||
1. Memcached
|
||||
|
||||
Introduction to caching
|
||||
-----------------------
|
||||
|
||||
To use caching to the maximum potential, your application should be designed with caching in mind from the outset. In general, the most effective caches contain lots of small collections of data that are the result of expensive computational operations, such as searching through a large data set.
|
||||
|
||||
There are many different caching methods available for PHP, from the very basic file based caching to opcode caching in eAccelerator and APC. Caching engines that use physical memory over disk based storage are always faster, however many do not support more advanced features such as tagging.
|
||||
|
||||
Using Cache
|
||||
-----------
|
||||
|
||||
To use Kohana Cache, download and extract the latest stable release of Kohana Cache from [Github](http://github.com/samsoir/kohana-cache). Place the module into your Kohana instances modules folder. Finally enable the module within the application bootstrap within the section entitled _modules_.
|
||||
|
||||
Quick example
|
||||
-------------
|
||||
|
||||
The following is a quick example of how to use Kohana Cache. The example is using the SQLite driver.
|
||||
|
||||
<?php
|
||||
// Get a Sqlite Cache instance
|
||||
$mycache = Cache::instance('sqlite');
|
||||
|
||||
// Create some data
|
||||
$data = array('foo' => 'bar', 'apples' => 'pear', 'BDFL' => 'Shadowhand');
|
||||
|
||||
// Save the data to cache, with an id of test_id and a lifetime of 10 minutes
|
||||
$mycache->set('test_id', $data, 600);
|
||||
|
||||
// Retrieve the data from cache
|
||||
$retrieved_data = $mycache->get('test_id');
|
||||
|
||||
// Remove the cache item
|
||||
$mycache->delete('test_id');
|
||||
|
||||
// Clear the cache of all stored items
|
||||
$mycache->delete_all();
|
3
includes/kohana/modules/cache/classes/cache.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
abstract class Cache extends Kohana_Cache {}
|
3
includes/kohana/modules/cache/classes/cache/apc.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/apc.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_Apc extends Kohana_Cache_Apc {}
|
3
includes/kohana/modules/cache/classes/cache/eaccelerator.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/eaccelerator.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_Eaccelerator extends Kohana_Cache_Eaccelerator {}
|
3
includes/kohana/modules/cache/classes/cache/file.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/file.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_File extends Kohana_Cache_File {}
|
3
includes/kohana/modules/cache/classes/cache/memcache.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/memcache.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_Memcache extends Kohana_Cache_Memcache {}
|
3
includes/kohana/modules/cache/classes/cache/memcachetag.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/memcachetag.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_MemcacheTag extends Kohana_Cache_MemcacheTag {}
|
3
includes/kohana/modules/cache/classes/cache/sqlite.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/sqlite.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_Sqlite extends Kohana_Cache_Sqlite {}
|
3
includes/kohana/modules/cache/classes/cache/wincache.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/wincache.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_Wincache extends Kohana_Cache_Wincache {}
|
3
includes/kohana/modules/cache/classes/cache/xcache.php
vendored
Normal file
3
includes/kohana/modules/cache/classes/cache/xcache.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
class Cache_Xcache extends Kohana_Cache_Xcache {}
|
256
includes/kohana/modules/cache/classes/kohana/cache.php
vendored
Normal file
256
includes/kohana/modules/cache/classes/kohana/cache.php
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Kohana Cache provides a common interface to a variety of caching engines. Tags are
|
||||
* supported where available natively to the cache system. Kohana Cache supports multiple
|
||||
* instances of cache engines through a grouped singleton pattern.
|
||||
*
|
||||
* ### Supported cache engines
|
||||
*
|
||||
* * [APC](http://php.net/manual/en/book.apc.php)
|
||||
* * [eAccelerator](http://eaccelerator.net/)
|
||||
* * File
|
||||
* * [Memcache](http://memcached.org/)
|
||||
* * [Memcached-tags](http://code.google.com/p/memcached-tags/)
|
||||
* * [SQLite](http://www.sqlite.org/)
|
||||
* * [Xcache](http://xcache.lighttpd.net/)
|
||||
*
|
||||
* ### Introduction to caching
|
||||
*
|
||||
* Caching should be implemented with consideration. Generally, caching the result of resources
|
||||
* is faster than reprocessing them. Choosing what, how and when to cache is vital. PHP APC is
|
||||
* presently one of the fastest caching systems available, closely followed by Memcache. SQLite
|
||||
* and File caching are two of the slowest cache methods, however usually faster than reprocessing
|
||||
* a complex set of instructions.
|
||||
*
|
||||
* Caching engines that use memory are considerably faster than the file based alternatives. But
|
||||
* memory is limited whereas disk space is plentiful. If caching large datasets it is best to use
|
||||
* file caching.
|
||||
*
|
||||
* ### Configuration settings
|
||||
*
|
||||
* Kohana Cache uses configuration groups to create cache instances. A configuration group can
|
||||
* use any supported driver, with successive groups using the same driver type if required.
|
||||
*
|
||||
* #### Configuration example
|
||||
*
|
||||
* Below is an example of a _memcache_ server configuration.
|
||||
*
|
||||
* return array(
|
||||
* 'default' => array( // Default group
|
||||
* 'driver' => 'memcache', // using Memcache driver
|
||||
* 'servers' => array( // Available server definitions
|
||||
* array(
|
||||
* 'host' => 'localhost',
|
||||
* 'port' => 11211,
|
||||
* 'persistent' => FALSE
|
||||
* )
|
||||
* ),
|
||||
* 'compression' => FALSE, // Use compression?
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* In cases where only one cache group is required, if the group is named `default` there is
|
||||
* no need to pass the group name when instantiating a cache instance.
|
||||
*
|
||||
* #### General cache group configuration settings
|
||||
*
|
||||
* Below are the settings available to all types of cache driver.
|
||||
*
|
||||
* Name | Required | Description
|
||||
* -------------- | -------- | ---------------------------------------------------------------
|
||||
* driver | __YES__ | (_string_) The driver type to use
|
||||
*
|
||||
* Details of the settings specific to each driver are available within the drivers documentation.
|
||||
*
|
||||
* ### System requirements
|
||||
*
|
||||
* * Kohana 3.0.x
|
||||
* * PHP 5.2.4 or greater
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @version 2.0
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Kohana_Cache {
|
||||
|
||||
const DEFAULT_EXPIRE = 3600;
|
||||
|
||||
/**
|
||||
* @var string default driver to use
|
||||
*/
|
||||
public static $default = 'file';
|
||||
|
||||
/**
|
||||
* @var Kohana_Cache instances
|
||||
*/
|
||||
public static $instances = array();
|
||||
|
||||
/**
|
||||
* Creates a singleton of a Kohana Cache group. If no group is supplied
|
||||
* the __default__ cache group is used.
|
||||
*
|
||||
* // Create an instance of the default group
|
||||
* $default_group = Cache::instance();
|
||||
*
|
||||
* // Create an instance of a group
|
||||
* $foo_group = Cache::instance('foo');
|
||||
*
|
||||
* // Access an instantiated group directly
|
||||
* $foo_group = Cache::$instances['default'];
|
||||
*
|
||||
* @param string the name of the cache group to use [Optional]
|
||||
* @return Kohana_Cache
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public static function instance($group = NULL)
|
||||
{
|
||||
// If there is no group supplied
|
||||
if ($group === NULL)
|
||||
{
|
||||
// Use the default setting
|
||||
$group = Cache::$default;
|
||||
}
|
||||
|
||||
if (isset(Cache::$instances[$group]))
|
||||
{
|
||||
// Return the current group if initiated already
|
||||
return Cache::$instances[$group];
|
||||
}
|
||||
|
||||
$config = Kohana::config('cache');
|
||||
|
||||
if ( ! $config->offsetExists($group))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Failed to load Kohana Cache group: :group', array(':group' => $group));
|
||||
}
|
||||
|
||||
$config = $config->get($group);
|
||||
|
||||
// Create a new cache type instance
|
||||
$cache_class = 'Cache_'.ucfirst($config['driver']);
|
||||
Cache::$instances[$group] = new $cache_class($config);
|
||||
|
||||
// Return the instance
|
||||
return Cache::$instances[$group];
|
||||
}
|
||||
|
||||
/**
|
||||
* @var Kohana_Config
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* Ensures singleton pattern is observed, loads the default expiry
|
||||
*
|
||||
* @param array configuration
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
$this->_config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload the __clone() method to prevent cloning
|
||||
*
|
||||
* @return void
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Cloning of Kohana_Cache objects is forbidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value entry by id.
|
||||
*
|
||||
* // Retrieve cache entry from default group
|
||||
* $data = Cache::instance()->get('foo');
|
||||
*
|
||||
* // Retrieve cache entry from default group and return 'bar' if miss
|
||||
* $data = Cache::instance()->get('foo', 'bar');
|
||||
*
|
||||
* // Retrieve cache entry from memcache group
|
||||
* $data = Cache::instance('memcache')->get('foo');
|
||||
*
|
||||
* @param string id of cache to entry
|
||||
* @param string default value to return if cache miss
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
abstract public function get($id, $default = NULL);
|
||||
|
||||
/**
|
||||
* Set a value to cache with id and lifetime
|
||||
*
|
||||
* $data = 'bar';
|
||||
*
|
||||
* // Set 'bar' to 'foo' in default group, using default expiry
|
||||
* Cache::instance()->set('foo', $data);
|
||||
*
|
||||
* // Set 'bar' to 'foo' in default group for 30 seconds
|
||||
* Cache::instance()->set('foo', $data, 30);
|
||||
*
|
||||
* // Set 'bar' to 'foo' in memcache group for 10 minutes
|
||||
* if (Cache::instance('memcache')->set('foo', $data, 600))
|
||||
* {
|
||||
* // Cache was set successfully
|
||||
* return
|
||||
* }
|
||||
*
|
||||
* @param string id of cache entry
|
||||
* @param string data to set to cache
|
||||
* @param integer lifetime in seconds
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function set($id, $data, $lifetime = 3600);
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* // Delete 'foo' entry from the default group
|
||||
* Cache::instance()->delete('foo');
|
||||
*
|
||||
* // Delete 'foo' entry from the memcache group
|
||||
* Cache::instance('memcache')->delete('foo')
|
||||
*
|
||||
* @param string id to remove from cache
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function delete($id);
|
||||
|
||||
/**
|
||||
* Delete all cache entries.
|
||||
*
|
||||
* Beware of using this method when
|
||||
* using shared memory cache systems, as it will wipe every
|
||||
* entry within the system for all clients.
|
||||
*
|
||||
* // Delete all cache entries in the default group
|
||||
* Cache::instance()->delete_all();
|
||||
*
|
||||
* // Delete all cache entries in the memcache group
|
||||
* Cache::instance('memcache')->delete_all();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
abstract public function delete_all();
|
||||
|
||||
/**
|
||||
* Replaces troublesome characters with underscores.
|
||||
*
|
||||
* // Sanitize a cache id
|
||||
* $id = $this->_sanitize_id($id);
|
||||
*
|
||||
* @param string id of cache to sanitize
|
||||
* @return string
|
||||
*/
|
||||
protected function _sanitize_id($id)
|
||||
{
|
||||
// Change slashes and spaces to underscores
|
||||
return str_replace(array('/', '\\', ' '), '_', $id);
|
||||
}
|
||||
}
|
||||
// End Kohana_Cache
|
133
includes/kohana/modules/cache/classes/kohana/cache/apc.php
vendored
Normal file
133
includes/kohana/modules/cache/classes/kohana/cache/apc.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* [Kohana Cache](api/Kohana_Cache) APC driver. Provides an opcode based
|
||||
* driver for the Kohana Cache library.
|
||||
*
|
||||
* ### Configuration example
|
||||
*
|
||||
* Below is an example of an _apc_ server configuration.
|
||||
*
|
||||
* return array(
|
||||
* 'apc' => array( // Driver group
|
||||
* 'driver' => 'apc', // using APC driver
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* In cases where only one cache group is required, if the group is named `default` there is
|
||||
* no need to pass the group name when instantiating a cache instance.
|
||||
*
|
||||
* #### General cache group configuration settings
|
||||
*
|
||||
* Below are the settings available to all types of cache driver.
|
||||
*
|
||||
* Name | Required | Description
|
||||
* -------------- | -------- | ---------------------------------------------------------------
|
||||
* driver | __YES__ | (_string_) The driver type to use
|
||||
*
|
||||
* ### System requirements
|
||||
*
|
||||
* * Kohana 3.0.x
|
||||
* * PHP 5.2.4 or greater
|
||||
* * APC PHP extension
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Apc extends Cache {
|
||||
|
||||
/**
|
||||
* Check for existence of the APC extension This method cannot be invoked externally. The driver must
|
||||
* be instantiated using the `Cache::instance()` method.
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
if ( ! extension_loaded('apc'))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('PHP APC extension is not available.');
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value entry by id.
|
||||
*
|
||||
* // Retrieve cache entry from apc group
|
||||
* $data = Cache::instance('apc')->get('foo');
|
||||
*
|
||||
* // Retrieve cache entry from apc group and return 'bar' if miss
|
||||
* $data = Cache::instance('apc')->get('foo', 'bar');
|
||||
*
|
||||
* @param string id of cache to entry
|
||||
* @param string default value to return if cache miss
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
return (($data = apc_fetch($this->_sanitize_id($id))) === FALSE) ? $default : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value to cache with id and lifetime
|
||||
*
|
||||
* $data = 'bar';
|
||||
*
|
||||
* // Set 'bar' to 'foo' in apc group, using default expiry
|
||||
* Cache::instance('apc')->set('foo', $data);
|
||||
*
|
||||
* // Set 'bar' to 'foo' in apc group for 30 seconds
|
||||
* Cache::instance('apc')->set('foo', $data, 30);
|
||||
*
|
||||
* @param string id of cache entry
|
||||
* @param string data to set to cache
|
||||
* @param integer lifetime in seconds
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = NULL)
|
||||
{
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
$lifetime = Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
return apc_store($this->_sanitize_id($id), $data, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* // Delete 'foo' entry from the apc group
|
||||
* Cache::instance('apc')->delete('foo');
|
||||
*
|
||||
* @param string id to remove from cache
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
return apc_delete($this->_sanitize_id($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries.
|
||||
*
|
||||
* Beware of using this method when
|
||||
* using shared memory cache systems, as it will wipe every
|
||||
* entry within the system for all clients.
|
||||
*
|
||||
* // Delete all cache entries in the apc group
|
||||
* Cache::instance('apc')->delete_all();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
return apc_clear_cache('user');
|
||||
}
|
||||
}
|
133
includes/kohana/modules/cache/classes/kohana/cache/eaccelerator.php
vendored
Normal file
133
includes/kohana/modules/cache/classes/kohana/cache/eaccelerator.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* [Kohana Cache](api/Kohana_Cache) Eaccelerator driver. Provides an opcode based
|
||||
* driver for the Kohana Cache library.
|
||||
*
|
||||
* ### Configuration example
|
||||
*
|
||||
* Below is an example of an _eaccelerator_ server configuration.
|
||||
*
|
||||
* return array(
|
||||
* 'eaccelerator' => array( // Driver group
|
||||
* 'driver' => 'eaccelerator', // using Eaccelerator driver
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* In cases where only one cache group is required, if the group is named `default` there is
|
||||
* no need to pass the group name when instantiating a cache instance.
|
||||
*
|
||||
* #### General cache group configuration settings
|
||||
*
|
||||
* Below are the settings available to all types of cache driver.
|
||||
*
|
||||
* Name | Required | Description
|
||||
* -------------- | -------- | ---------------------------------------------------------------
|
||||
* driver | __YES__ | (_string_) The driver type to use
|
||||
*
|
||||
* ### System requirements
|
||||
*
|
||||
* * Kohana 3.0.x
|
||||
* * PHP 5.2.4 or greater
|
||||
* * Eaccelerator PHP extension
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Eaccelerator extends Cache {
|
||||
|
||||
/**
|
||||
* Check for existence of the eAccelerator extension This method cannot be invoked externally. The driver must
|
||||
* be instantiated using the `Cache::instance()` method.
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
if ( ! extension_loaded('eaccelerator'))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('PHP eAccelerator extension is not available.');
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value entry by id.
|
||||
*
|
||||
* // Retrieve cache entry from eaccelerator group
|
||||
* $data = Cache::instance('eaccelerator')->get('foo');
|
||||
*
|
||||
* // Retrieve cache entry from eaccelerator group and return 'bar' if miss
|
||||
* $data = Cache::instance('eaccelerator')->get('foo', 'bar');
|
||||
*
|
||||
* @param string id of cache to entry
|
||||
* @param string default value to return if cache miss
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
return (($data = eaccelerator_get($this->_sanitize_id($id))) === FALSE) ? $default : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value to cache with id and lifetime
|
||||
*
|
||||
* $data = 'bar';
|
||||
*
|
||||
* // Set 'bar' to 'foo' in eaccelerator group, using default expiry
|
||||
* Cache::instance('eaccelerator')->set('foo', $data);
|
||||
*
|
||||
* // Set 'bar' to 'foo' in eaccelerator group for 30 seconds
|
||||
* Cache::instance('eaccelerator')->set('foo', $data, 30);
|
||||
*
|
||||
* @param string id of cache entry
|
||||
* @param string data to set to cache
|
||||
* @param integer lifetime in seconds
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = NULL)
|
||||
{
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
$lifetime = time() + Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
return eaccelerator_put($this->_sanitize_id($id), $data, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* // Delete 'foo' entry from the eaccelerator group
|
||||
* Cache::instance('eaccelerator')->delete('foo');
|
||||
*
|
||||
* @param string id to remove from cache
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
return eaccelerator_rm($this->_sanitize_id($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries.
|
||||
*
|
||||
* Beware of using this method when
|
||||
* using shared memory cache systems, as it will wipe every
|
||||
* entry within the system for all clients.
|
||||
*
|
||||
* // Delete all cache entries in the eaccelerator group
|
||||
* Cache::instance('eaccelerator')->delete_all();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
return eaccelerator_clean();
|
||||
}
|
||||
}
|
11
includes/kohana/modules/cache/classes/kohana/cache/exception.php
vendored
Normal file
11
includes/kohana/modules/cache/classes/kohana/cache/exception.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Kohana Cache Exception
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Exception extends Kohana_Exception {}
|
463
includes/kohana/modules/cache/classes/kohana/cache/file.php
vendored
Normal file
463
includes/kohana/modules/cache/classes/kohana/cache/file.php
vendored
Normal file
@@ -0,0 +1,463 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* [Kohana Cache](api/Kohana_Cache) File driver. Provides a file based
|
||||
* driver for the Kohana Cache library. This is one of the slowest
|
||||
* caching methods.
|
||||
*
|
||||
* ### Configuration example
|
||||
*
|
||||
* Below is an example of a _file_ server configuration.
|
||||
*
|
||||
* return array(
|
||||
* 'file' => array( // File driver group
|
||||
* 'driver' => 'file', // using File driver
|
||||
* 'cache_dir' => APPPATH.'cache/.kohana_cache', // Cache location
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* In cases where only one cache group is required, if the group is named `default` there is
|
||||
* no need to pass the group name when instantiating a cache instance.
|
||||
*
|
||||
* #### General cache group configuration settings
|
||||
*
|
||||
* Below are the settings available to all types of cache driver.
|
||||
*
|
||||
* Name | Required | Description
|
||||
* -------------- | -------- | ---------------------------------------------------------------
|
||||
* driver | __YES__ | (_string_) The driver type to use
|
||||
* cache_dir | __NO__ | (_string_) The cache directory to use for this cache instance
|
||||
*
|
||||
* ### System requirements
|
||||
*
|
||||
* * Kohana 3.0.x
|
||||
* * PHP 5.2.4 or greater
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_File extends Cache implements Kohana_Cache_GarbageCollect {
|
||||
|
||||
/**
|
||||
* Creates a hashed filename based on the string. This is used
|
||||
* to create shorter unique IDs for each cache filename.
|
||||
*
|
||||
* // Create the cache filename
|
||||
* $filename = Cache_File::filename($this->_sanitize_id($id));
|
||||
*
|
||||
* @param string string to hash into filename
|
||||
* @return string
|
||||
*/
|
||||
protected static function filename($string)
|
||||
{
|
||||
return sha1($string).'.json';
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string the caching directory
|
||||
*/
|
||||
protected $_cache_dir;
|
||||
|
||||
/**
|
||||
* Constructs the file cache driver. This method cannot be invoked externally. The file cache driver must
|
||||
* be instantiated using the `Cache::instance()` method.
|
||||
*
|
||||
* @param array config
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
// Setup parent
|
||||
parent::__construct($config);
|
||||
|
||||
try
|
||||
{
|
||||
$directory = Arr::get($this->_config, 'cache_dir', Kohana::$cache_dir);
|
||||
$this->_cache_dir = new SplFileInfo($directory);
|
||||
}
|
||||
// PHP < 5.3 exception handle
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
$this->_cache_dir = $this->_make_directory($directory, 0777, TRUE);
|
||||
}
|
||||
// PHP >= 5.3 exception handle
|
||||
catch (UnexpectedValueException $e)
|
||||
{
|
||||
$this->_cache_dir = $this->_make_directory($directory, 0777, TRUE);
|
||||
}
|
||||
|
||||
// If the defined directory is a file, get outta here
|
||||
if ($this->_cache_dir->isFile())
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Unable to create cache directory as a file already exists : :resource', array(':resource' => $this->_cache_dir->getRealPath()));
|
||||
}
|
||||
|
||||
// Check the read status of the directory
|
||||
if ( ! $this->_cache_dir->isReadable())
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Unable to read from the cache directory :resource', array(':resource' => $this->_cache_dir->getRealPath()));
|
||||
}
|
||||
|
||||
// Check the write status of the directory
|
||||
if ( ! $this->_cache_dir->isWritable())
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Unable to write to the cache directory :resource', array(':resource' => $this->_cache_dir->getRealPath()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value entry by id.
|
||||
*
|
||||
* // Retrieve cache entry from file group
|
||||
* $data = Cache::instance('file')->get('foo');
|
||||
*
|
||||
* // Retrieve cache entry from file group and return 'bar' if miss
|
||||
* $data = Cache::instance('file')->get('foo', 'bar');
|
||||
*
|
||||
* @param string id of cache to entry
|
||||
* @param string default value to return if cache miss
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
$filename = Cache_File::filename($this->_sanitize_id($id));
|
||||
$directory = $this->_resolve_directory($filename);
|
||||
|
||||
// Wrap operations in try/catch to handle notices
|
||||
try
|
||||
{
|
||||
// Open file
|
||||
$file = new SplFileInfo($directory.$filename);
|
||||
|
||||
// If file does not exist
|
||||
if ( ! $file->isFile())
|
||||
{
|
||||
// Return default value
|
||||
return $default;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open the file and extract the json
|
||||
$json = $file->openFile()->current();
|
||||
|
||||
// Decode the json into PHP object
|
||||
$data = json_decode($json);
|
||||
|
||||
// Test the expiry
|
||||
if ($data->expiry < time())
|
||||
{
|
||||
// Delete the file
|
||||
$this->_delete_file($file, NULL, TRUE);
|
||||
|
||||
// Return default value
|
||||
return $default;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ($data->type === 'string') ? $data->payload : unserialize($data->payload);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
// Handle ErrorException caused by failed unserialization
|
||||
if ($e->getCode() === E_NOTICE)
|
||||
{
|
||||
throw new Kohana_Cache_Exception(__METHOD__.' failed to unserialize cached object with message : '.$e->getMessage());
|
||||
}
|
||||
|
||||
// Otherwise throw the exception
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value to cache with id and lifetime
|
||||
*
|
||||
* $data = 'bar';
|
||||
*
|
||||
* // Set 'bar' to 'foo' in file group, using default expiry
|
||||
* Cache::instance('file')->set('foo', $data);
|
||||
*
|
||||
* // Set 'bar' to 'foo' in file group for 30 seconds
|
||||
* Cache::instance('file')->set('foo', $data, 30);
|
||||
*
|
||||
* @param string id of cache entry
|
||||
* @param string data to set to cache
|
||||
* @param integer lifetime in seconds
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = NULL)
|
||||
{
|
||||
$filename = Cache_File::filename($this->_sanitize_id($id));
|
||||
$directory = $this->_resolve_directory($filename);
|
||||
|
||||
// If lifetime is NULL
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
// Set to the default expiry
|
||||
$lifetime = Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
// Open directory
|
||||
$dir = new SplFileInfo($directory);
|
||||
|
||||
// If the directory path is not a directory
|
||||
if ( ! $dir->isDir())
|
||||
{
|
||||
// Create the directory
|
||||
if ( ! mkdir($directory, 0777, TRUE))
|
||||
{
|
||||
throw new Kohana_Cache_Exception(__METHOD__.' unable to create directory : :directory', array(':directory' => $directory));
|
||||
}
|
||||
|
||||
// chmod to solve potential umask issues
|
||||
chmod($directory, 0777);
|
||||
}
|
||||
|
||||
// Open file to inspect
|
||||
$resouce = new SplFileInfo($directory.$filename);
|
||||
$file = $resouce->openFile('w');
|
||||
|
||||
try
|
||||
{
|
||||
$type = gettype($data);
|
||||
|
||||
// Serialize the data
|
||||
$data = json_encode( (object) array(
|
||||
'payload' => ($type === 'string') ? $data : serialize($data),
|
||||
'expiry' => time() + $lifetime,
|
||||
'type' => $type
|
||||
));
|
||||
|
||||
$size = strlen($data);
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
// If serialize through an error exception
|
||||
if ($e->getCode() === E_NOTICE)
|
||||
{
|
||||
// Throw a caching error
|
||||
throw new Kohana_Cache_Exception(__METHOD__.' failed to serialize data for caching with message : '.$e->getMessage());
|
||||
}
|
||||
|
||||
// Else rethrow the error exception
|
||||
throw $e;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$file->fwrite($data, $size);
|
||||
return (bool) $file->fflush();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* // Delete 'foo' entry from the file group
|
||||
* Cache::instance('file')->delete('foo');
|
||||
*
|
||||
* @param string id to remove from cache
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$filename = Cache_File::filename($this->_sanitize_id($id));
|
||||
$directory = $this->_resolve_directory($filename);
|
||||
|
||||
return $this->_delete_file(new SplFileInfo($directory.$filename), NULL, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries.
|
||||
*
|
||||
* Beware of using this method when
|
||||
* using shared memory cache systems, as it will wipe every
|
||||
* entry within the system for all clients.
|
||||
*
|
||||
* // Delete all cache entries in the file group
|
||||
* Cache::instance('file')->delete_all();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
return $this->_delete_file($this->_cache_dir, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection method that cleans any expired
|
||||
* cache entries from the cache.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function garbage_collect()
|
||||
{
|
||||
$this->_delete_file($this->_cache_dir, TRUE, FALSE, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes files recursively and returns FALSE on any errors
|
||||
*
|
||||
* // Delete a file or folder whilst retaining parent directory and ignore all errors
|
||||
* $this->_delete_file($folder, TRUE, TRUE);
|
||||
*
|
||||
* @param SplFileInfo file
|
||||
* @param boolean retain the parent directory
|
||||
* @param boolean ignore_errors to prevent all exceptions interrupting exec
|
||||
* @param boolean only expired files
|
||||
* @return boolean
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function _delete_file(SplFileInfo $file, $retain_parent_directory = FALSE, $ignore_errors = FALSE, $only_expired = FALSE)
|
||||
{
|
||||
// Allow graceful error handling
|
||||
try
|
||||
{
|
||||
// If is file
|
||||
if ($file->isFile())
|
||||
{
|
||||
try
|
||||
{
|
||||
// If only expired is not set
|
||||
if ($only_expired === FALSE)
|
||||
{
|
||||
// We want to delete the file
|
||||
$delete = TRUE;
|
||||
}
|
||||
// Otherwise...
|
||||
else
|
||||
{
|
||||
// Assess the file expiry to flag it for deletion
|
||||
$json = $file->openFile('r')->current();
|
||||
$data = json_decode($json);
|
||||
$delete = $data->expiry < time();
|
||||
}
|
||||
|
||||
// If the delete flag is set
|
||||
if ($delete === TRUE)
|
||||
{
|
||||
// Try to delete
|
||||
unlink($file->getRealPath());
|
||||
}
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
// Catch any delete file warnings
|
||||
if ($e->getCode() === E_WARNING)
|
||||
{
|
||||
throw new Kohana_Cache_Exception(__METHOD__.' failed to delete file : :file', array(':file' => $file->getRealPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else, is directory
|
||||
elseif ($file->isDir())
|
||||
{
|
||||
// Create new DirectoryIterator
|
||||
$files = new DirectoryIterator($file->getPathname());
|
||||
|
||||
// Iterate over each entry
|
||||
while ($files->valid())
|
||||
{
|
||||
// Extract the entry name
|
||||
$name = $files->getFilename();
|
||||
|
||||
// If the name is not a dot
|
||||
if ($name != '.' and $name != '..')
|
||||
{
|
||||
// Create new file resource
|
||||
$fp = new SplFileInfo($files->getRealPath());
|
||||
// Delete the file
|
||||
$this->_delete_file($fp);
|
||||
}
|
||||
|
||||
// Move the file pointer on
|
||||
$files->next();
|
||||
}
|
||||
|
||||
// If set to retain parent directory, return now
|
||||
if ($retain_parent_directory)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Remove the files iterator
|
||||
// (fixes Windows PHP which has permission issues with open iterators)
|
||||
unset($files);
|
||||
|
||||
// Try to remove the parent directory
|
||||
return rmdir($file->getRealPath());
|
||||
}
|
||||
catch (ErrorException $e)
|
||||
{
|
||||
// Catch any delete directory warnings
|
||||
if ($e->getCode() === E_WARNING)
|
||||
{
|
||||
throw new Kohana_Cache_Exception(__METHOD__.' failed to delete directory : :directory', array(':directory' => $file->getRealPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Catch all exceptions
|
||||
catch (Exception $e)
|
||||
{
|
||||
// If ignore_errors is on
|
||||
if ($ignore_errors === TRUE)
|
||||
{
|
||||
// Return
|
||||
return FALSE;
|
||||
}
|
||||
// Throw exception
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the cache directory real path from the filename
|
||||
*
|
||||
* // Get the realpath of the cache folder
|
||||
* $realpath = $this->_resolve_directory($filename);
|
||||
*
|
||||
* @param string filename to resolve
|
||||
* @return string
|
||||
*/
|
||||
protected function _resolve_directory($filename)
|
||||
{
|
||||
return $this->_cache_dir->getRealPath().DIRECTORY_SEPARATOR.$filename[0].$filename[1].DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the cache directory if it doesn't exist. Simply a wrapper for
|
||||
* `mkdir` to ensure DRY principles
|
||||
*
|
||||
* @see http://php.net/manual/en/function.mkdir.php
|
||||
* @param string directory
|
||||
* @param string mode
|
||||
* @param string recursive
|
||||
* @param string context
|
||||
* @return SplFileInfo
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function _make_directory($directory, $mode = 0777, $recursive = FALSE, $context = NULL)
|
||||
{
|
||||
if ( ! mkdir($directory, $mode, $recursive, $context))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Failed to create the defined cache directory : :directory', array(':directory' => $directory));
|
||||
}
|
||||
chmod($directory, $mode);
|
||||
|
||||
return new SplFileInfo($directory);;
|
||||
}
|
||||
}
|
23
includes/kohana/modules/cache/classes/kohana/cache/garbagecollect.php
vendored
Normal file
23
includes/kohana/modules/cache/classes/kohana/cache/garbagecollect.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Garbage Collection interface for caches that have no GC methods
|
||||
* of their own, such as [Cache_File] and [Cache_Sqlite]. Memory based
|
||||
* cache systems clean their own caches periodically.
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @version 2.0
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
* @since 3.0.8
|
||||
*/
|
||||
interface Kohana_Cache_GarbageCollect {
|
||||
/**
|
||||
* Garbage collection method that cleans any expired
|
||||
* cache entries from the cache.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function garbage_collect();
|
||||
}
|
324
includes/kohana/modules/cache/classes/kohana/cache/memcache.php
vendored
Normal file
324
includes/kohana/modules/cache/classes/kohana/cache/memcache.php
vendored
Normal file
@@ -0,0 +1,324 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* [Kohana Cache](api/Kohana_Cache) Memcache driver,
|
||||
*
|
||||
* ### Supported cache engines
|
||||
*
|
||||
* * [Memcache](http://www.php.net/manual/en/book.memcache.php)
|
||||
* * [Memcached-tags](http://code.google.com/p/memcached-tags/)
|
||||
*
|
||||
* ### Configuration example
|
||||
*
|
||||
* Below is an example of a _memcache_ server configuration.
|
||||
*
|
||||
* return array(
|
||||
* 'default' => array( // Default group
|
||||
* 'driver' => 'memcache', // using Memcache driver
|
||||
* 'servers' => array( // Available server definitions
|
||||
* // First memcache server server
|
||||
* array(
|
||||
* 'host' => 'localhost',
|
||||
* 'port' => 11211,
|
||||
* 'persistent' => FALSE
|
||||
* 'weight' => 1,
|
||||
* 'timeout' => 1,
|
||||
* 'retry_interval' => 15,
|
||||
* 'status' => TRUE,
|
||||
* 'instant_death' => TRUE,
|
||||
* 'failure_callback' => array('className', 'classMethod')
|
||||
* ),
|
||||
* // Second memcache server
|
||||
* array(
|
||||
* 'host' => '192.168.1.5',
|
||||
* 'port' => 22122,
|
||||
* 'persistent' => TRUE
|
||||
* )
|
||||
* ),
|
||||
* 'compression' => FALSE, // Use compression?
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* In cases where only one cache group is required, if the group is named `default` there is
|
||||
* no need to pass the group name when instantiating a cache instance.
|
||||
*
|
||||
* #### General cache group configuration settings
|
||||
*
|
||||
* Below are the settings available to all types of cache driver.
|
||||
*
|
||||
* Name | Required | Description
|
||||
* -------------- | -------- | ---------------------------------------------------------------
|
||||
* driver | __YES__ | (_string_) The driver type to use
|
||||
* servers | __YES__ | (_array_) Associative array of server details, must include a __host__ key. (see _Memcache server configuration_ below)
|
||||
* compression | __NO__ | (_boolean_) Use data compression when caching
|
||||
*
|
||||
* #### Memcache server configuration
|
||||
*
|
||||
* The following settings should be used when defining each memcache server
|
||||
*
|
||||
* Name | Required | Description
|
||||
* ---------------- | -------- | ---------------------------------------------------------------
|
||||
* host | __YES__ | (_string_) The host of the memcache server, i.e. __localhost__; or __127.0.0.1__; or __memcache.domain.tld__
|
||||
* port | __NO__ | (_integer_) Point to the port where memcached is listening for connections. Set this parameter to 0 when using UNIX domain sockets. Default __11211__
|
||||
* persistent | __NO__ | (_boolean_) Controls the use of a persistent connection. Default __TRUE__
|
||||
* weight | __NO__ | (_integer_) Number of buckets to create for this server which in turn control its probability of it being selected. The probability is relative to the total weight of all servers. Default __1__
|
||||
* timeout | __NO__ | (_integer_) Value in seconds which will be used for connecting to the daemon. Think twice before changing the default value of 1 second - you can lose all the advantages of caching if your connection is too slow. Default __1__
|
||||
* retry_interval | __NO__ | (_integer_) Controls how often a failed server will be retried, the default value is 15 seconds. Setting this parameter to -1 disables automatic retry. Default __15__
|
||||
* status | __NO__ | (_boolean_) Controls if the server should be flagged as online. Default __TRUE__
|
||||
* failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback)_) Allows the user to specify a callback function to run upon encountering an error. The callback is run before failover is attempted. The function takes two parameters, the hostname and port of the failed server. Default __NULL__
|
||||
*
|
||||
* ### System requirements
|
||||
*
|
||||
* * Kohana 3.0.x
|
||||
* * PHP 5.2.4 or greater
|
||||
* * Memcache (plus Memcached-tags for native tagging support)
|
||||
* * Zlib
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @version 2.0
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Memcache extends Cache {
|
||||
|
||||
// Memcache has a maximum cache lifetime of 30 days
|
||||
const CACHE_CEILING = 2592000;
|
||||
|
||||
/**
|
||||
* Memcache resource
|
||||
*
|
||||
* @var Memcache
|
||||
*/
|
||||
protected $_memcache;
|
||||
|
||||
/**
|
||||
* Flags to use when storing values
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_flags;
|
||||
|
||||
/**
|
||||
* The default configuration for the memcached server
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_default_config = array();
|
||||
|
||||
/**
|
||||
* Constructs the memcache Kohana_Cache object
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
// Check for the memcache extention
|
||||
if ( ! extension_loaded('memcache'))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Memcache PHP extention not loaded');
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
|
||||
// Setup Memcache
|
||||
$this->_memcache = new Memcache;
|
||||
|
||||
// Load servers from configuration
|
||||
$servers = Arr::get($this->_config, 'servers', NULL);
|
||||
|
||||
if ( ! $servers)
|
||||
{
|
||||
// Throw an exception if no server found
|
||||
throw new Kohana_Cache_Exception('No Memcache servers defined in configuration');
|
||||
}
|
||||
|
||||
// Setup default server configuration
|
||||
$this->_default_config = array(
|
||||
'host' => 'localhost',
|
||||
'port' => 11211,
|
||||
'persistent' => FALSE,
|
||||
'weight' => 1,
|
||||
'timeout' => 1,
|
||||
'retry_interval' => 15,
|
||||
'status' => TRUE,
|
||||
'instant_death' => TRUE,
|
||||
'failure_callback' => array($this, '_failed_request'),
|
||||
);
|
||||
|
||||
// Add the memcache servers to the pool
|
||||
foreach ($servers as $server)
|
||||
{
|
||||
// Merge the defined config with defaults
|
||||
$server += $this->_default_config;
|
||||
|
||||
if ( ! $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'], $server['weight'], $server['timeout'], $server['retry_interval'], $server['status'], $server['failure_callback']))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Memcache could not connect to host \':host\' using port \':port\'', array(':host' => $server['host'], ':port' => $server['port']));
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the flags
|
||||
$this->_flags = Arr::get($this->_config, 'compression', FALSE) ? MEMCACHE_COMPRESSED : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value entry by id.
|
||||
*
|
||||
* // Retrieve cache entry from memcache group
|
||||
* $data = Cache::instance('memcache')->get('foo');
|
||||
*
|
||||
* // Retrieve cache entry from memcache group and return 'bar' if miss
|
||||
* $data = Cache::instance('memcache')->get('foo', 'bar');
|
||||
*
|
||||
* @param string id of cache to entry
|
||||
* @param string default value to return if cache miss
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
// Get the value from Memcache
|
||||
$value = $this->_memcache->get($this->_sanitize_id($id));
|
||||
|
||||
// If the value wasn't found, normalise it
|
||||
if ($value === FALSE)
|
||||
{
|
||||
$value = (NULL === $default) ? NULL : $default;
|
||||
}
|
||||
|
||||
// Return the value
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value to cache with id and lifetime
|
||||
*
|
||||
* $data = 'bar';
|
||||
*
|
||||
* // Set 'bar' to 'foo' in memcache group for 10 minutes
|
||||
* if (Cache::instance('memcache')->set('foo', $data, 600))
|
||||
* {
|
||||
* // Cache was set successfully
|
||||
* return
|
||||
* }
|
||||
*
|
||||
* @param string id of cache entry
|
||||
* @param mixed data to set to cache
|
||||
* @param integer lifetime in seconds, maximum value 2592000
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = 3600)
|
||||
{
|
||||
// If the lifetime is greater than the ceiling
|
||||
if ($lifetime > Cache_Memcache::CACHE_CEILING)
|
||||
{
|
||||
// Set the lifetime to maximum cache time
|
||||
$lifetime = Cache_Memcache::CACHE_CEILING + time();
|
||||
}
|
||||
// Else if the lifetime is greater than zero
|
||||
elseif ($lifetime > 0)
|
||||
{
|
||||
$lifetime += time();
|
||||
}
|
||||
// Else
|
||||
else
|
||||
{
|
||||
// Normalise the lifetime
|
||||
$lifetime = 0;
|
||||
}
|
||||
|
||||
// Set the data to memcache
|
||||
return $this->_memcache->set($this->_sanitize_id($id), $data, $this->_flags, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* // Delete the 'foo' cache entry immediately
|
||||
* Cache::instance('memcache')->delete('foo');
|
||||
*
|
||||
* // Delete the 'bar' cache entry after 30 seconds
|
||||
* Cache::instance('memcache')->delete('bar', 30);
|
||||
*
|
||||
* @param string id of entry to delete
|
||||
* @param integer timeout of entry, if zero item is deleted immediately, otherwise the item will delete after the specified value in seconds
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id, $timeout = 0)
|
||||
{
|
||||
// Delete the id
|
||||
return $this->_memcache->delete($this->_sanitize_id($id), $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries.
|
||||
*
|
||||
* Beware of using this method when
|
||||
* using shared memory cache systems, as it will wipe every
|
||||
* entry within the system for all clients.
|
||||
*
|
||||
* // Delete all cache entries in the default group
|
||||
* Cache::instance('memcache')->delete_all();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
$result = $this->_memcache->flush();
|
||||
|
||||
// We must sleep after flushing, or overwriting will not work!
|
||||
// @see http://php.net/manual/en/function.memcache-flush.php#81420
|
||||
sleep(1);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method for Memcache::failure_callback to use if any Memcache call
|
||||
* on a particular server fails. This method switches off that instance of the
|
||||
* server if the configuration setting `instant_death` is set to `TRUE`.
|
||||
*
|
||||
* @param string hostname
|
||||
* @param integer port
|
||||
* @return void|boolean
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public function _failed_request($hostname, $port)
|
||||
{
|
||||
if ( ! $this->_config['instant_death'])
|
||||
return;
|
||||
|
||||
// Setup non-existent host
|
||||
$host = FALSE;
|
||||
|
||||
// Get host settings from configuration
|
||||
foreach ($this->_config['servers'] as $server)
|
||||
{
|
||||
// Merge the defaults, since they won't always be set
|
||||
$server += $this->_default_config;
|
||||
// We're looking at the failed server
|
||||
if ($hostname == $server['host'] and $port == $server['port'])
|
||||
{
|
||||
// Server to disable, since it failed
|
||||
$host = $server;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $host)
|
||||
return;
|
||||
else
|
||||
{
|
||||
return $this->_memcache->setServerParams(
|
||||
$host['host'],
|
||||
$host['port'],
|
||||
$host['timeout'],
|
||||
$host['retry_interval'],
|
||||
FALSE, // Server is offline
|
||||
array($this, '_failed_request'
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
76
includes/kohana/modules/cache/classes/kohana/cache/memcachetag.php
vendored
Normal file
76
includes/kohana/modules/cache/classes/kohana/cache/memcachetag.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* See [Kohana_Cache_Memcache]
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @version 2.0
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_MemcacheTag extends Cache_Memcache implements Kohana_Cache_Tagging {
|
||||
|
||||
/**
|
||||
* Constructs the memcache object
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
if ( ! method_exists($this->_memcache, 'tag_add'))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Memcached-tags PHP plugin not present. Please see http://code.google.com/p/memcached-tags/ for more information');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value based on an id with tags
|
||||
*
|
||||
* @param string id
|
||||
* @param mixed data
|
||||
* @param integer lifetime [Optional]
|
||||
* @param array tags [Optional]
|
||||
* @return boolean
|
||||
*/
|
||||
public function set_with_tags($id, $data, $lifetime = NULL, array $tags = NULL)
|
||||
{
|
||||
$result = $this->set($id, $data, $lifetime);
|
||||
|
||||
if ($result and $tags)
|
||||
{
|
||||
foreach ($tags as $tag)
|
||||
{
|
||||
$this->_memcache->tag_add($tag, $id);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cache entries based on a tag
|
||||
*
|
||||
* @param string tag
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_tag($tag)
|
||||
{
|
||||
return $this->_memcache->tag_delete($tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find cache entries based on a tag
|
||||
*
|
||||
* @param string tag
|
||||
* @return void
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Memcached-tags does not support finding by tag');
|
||||
}
|
||||
}
|
336
includes/kohana/modules/cache/classes/kohana/cache/sqlite.php
vendored
Normal file
336
includes/kohana/modules/cache/classes/kohana/cache/sqlite.php
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Kohana Cache Sqlite Driver
|
||||
*
|
||||
* Requires SQLite3 and PDO
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Sqlite extends Cache implements Kohana_Cache_Tagging, Kohana_Cache_GarbageCollect {
|
||||
|
||||
/**
|
||||
* Database resource
|
||||
*
|
||||
* @var PDO
|
||||
*/
|
||||
protected $_db;
|
||||
|
||||
/**
|
||||
* Sets up the PDO SQLite table and
|
||||
* initialises the PDO connection
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
$database = Arr::get($this->_config, 'database', NULL);
|
||||
|
||||
if ($database === NULL)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Database path not available in Kohana Cache configuration');
|
||||
}
|
||||
|
||||
// Load new Sqlite DB
|
||||
$this->_db = new PDO('sqlite:'.$database);
|
||||
|
||||
// Test for existing DB
|
||||
$result = $this->_db->query("SELECT * FROM sqlite_master WHERE name = 'caches' AND type = 'table'")->fetchAll();
|
||||
|
||||
// If there is no table, create a new one
|
||||
if (0 == count($result))
|
||||
{
|
||||
$database_schema = Arr::get($this->_config, 'schema', NULL);
|
||||
|
||||
if ($database_schema === NULL)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Database schema not found in Kohana Cache configuration');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Create the caches table
|
||||
$this->_db->query(Arr::get($this->_config, 'schema', NULL));
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('Failed to create new SQLite caches table with the following error : :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a value based on an id
|
||||
*
|
||||
* @param string id
|
||||
* @param string default [Optional] Default value to return if id not found
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
// Prepare statement
|
||||
$statement = $this->_db->prepare('SELECT id, expiration, cache FROM caches WHERE id = :id LIMIT 0, 1');
|
||||
|
||||
// Try and load the cache based on id
|
||||
try
|
||||
{
|
||||
$statement->execute(array(':id' => $this->_sanitize_id($id)));
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
if ( ! $result = $statement->fetch(PDO::FETCH_OBJ))
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
// If the cache has expired
|
||||
if ($result->expiration != 0 and $result->expiration <= time())
|
||||
{
|
||||
// Delete it and return default value
|
||||
$this->delete($id);
|
||||
return $default;
|
||||
}
|
||||
// Otherwise return cached object
|
||||
else
|
||||
{
|
||||
// Disable notices for unserializing
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
|
||||
// Return the valid cache data
|
||||
$data = unserialize($result->cache);
|
||||
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
|
||||
// Return the resulting data
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value based on an id. Optionally add tags.
|
||||
*
|
||||
* @param string id
|
||||
* @param mixed data
|
||||
* @param integer lifetime [Optional]
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = NULL)
|
||||
{
|
||||
return (bool) $this->set_with_tags($id, $data, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* @param string id
|
||||
* @param integer timeout [Optional]
|
||||
* @return boolean
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
// Prepare statement
|
||||
$statement = $this->_db->prepare('DELETE FROM caches WHERE id = :id');
|
||||
|
||||
// Remove the entry
|
||||
try
|
||||
{
|
||||
$statement->execute(array(':id' => $this->_sanitize_id($id)));
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
return (bool) $statement->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
// Prepare statement
|
||||
$statement = $this->_db->prepare('DELETE FROM caches');
|
||||
|
||||
// Remove the entry
|
||||
try
|
||||
{
|
||||
$statement->execute();
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
return (bool) $statement->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value based on an id. Optionally add tags.
|
||||
*
|
||||
* @param string id
|
||||
* @param mixed data
|
||||
* @param integer lifetime [Optional]
|
||||
* @param array tags [Optional]
|
||||
* @return boolean
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function set_with_tags($id, $data, $lifetime = NULL, array $tags = NULL)
|
||||
{
|
||||
// Serialize the data
|
||||
$data = serialize($data);
|
||||
|
||||
// Normalise tags
|
||||
$tags = (NULL === $tags) ? NULL : ('<'.implode('>,<', $tags).'>');
|
||||
|
||||
// Setup lifetime
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
$lifetime = (0 === Arr::get('default_expire', NULL)) ? 0 : (Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE) + time());
|
||||
}
|
||||
else
|
||||
{
|
||||
$lifetime = (0 === $lifetime) ? 0 : ($lifetime + time());
|
||||
}
|
||||
|
||||
// Prepare statement
|
||||
// $this->exists() may throw Kohana_Cache_Exception, no need to catch/rethrow
|
||||
$statement = $this->exists($id) ? $this->_db->prepare('UPDATE caches SET expiration = :expiration, cache = :cache, tags = :tags WHERE id = :id') : $this->_db->prepare('INSERT INTO caches (id, cache, expiration, tags) VALUES (:id, :cache, :expiration, :tags)');
|
||||
|
||||
// Try to insert
|
||||
try
|
||||
{
|
||||
$statement->execute(array(':id' => $this->_sanitize_id($id), ':cache' => $data, ':expiration' => $lifetime, ':tags' => $tags));
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
return (bool) $statement->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cache entries based on a tag
|
||||
*
|
||||
* @param string tag
|
||||
* @param integer timeout [Optional]
|
||||
* @return boolean
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function delete_tag($tag)
|
||||
{
|
||||
// Prepare the statement
|
||||
$statement = $this->_db->prepare('DELETE FROM caches WHERE tags LIKE :tag');
|
||||
|
||||
// Try to delete
|
||||
try
|
||||
{
|
||||
$statement->execute(array(':tag' => "%<{$tag}>%"));
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
return (bool) $statement->rowCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find cache entries based on a tag
|
||||
*
|
||||
* @param string tag
|
||||
* @return array
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
// Prepare the statement
|
||||
$statement = $this->_db->prepare('SELECT id, cache FROM caches WHERE tags LIKE :tag');
|
||||
|
||||
// Try to find
|
||||
try
|
||||
{
|
||||
if ( ! $statement->execute(array(':tag' => "%<{$tag}>%")))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
$result = array();
|
||||
|
||||
while ($row = $statement->fetchObject())
|
||||
{
|
||||
// Disable notices for unserializing
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
|
||||
$result[$row->id] = unserialize($row->cache);
|
||||
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collection method that cleans any expired
|
||||
* cache entries from the cache.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function garbage_collect()
|
||||
{
|
||||
// Create the sequel statement
|
||||
$statement = $this->_db->prepare('DELETE FROM caches WHERE expiration < :expiration');
|
||||
|
||||
try
|
||||
{
|
||||
$statement->execute(array(':expiration' => time()));
|
||||
}
|
||||
catch (PDOException $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether an id exists or not
|
||||
*
|
||||
* @param string id
|
||||
* @return boolean
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function exists($id)
|
||||
{
|
||||
$statement = $this->_db->prepare('SELECT id FROM caches WHERE id = :id');
|
||||
try
|
||||
{
|
||||
$statement->execute(array(':id' => $this->_sanitize_id($id)));
|
||||
}
|
||||
catch (PDOExeption $e)
|
||||
{
|
||||
throw new Kohana_Cache_Exception('There was a problem querying the local SQLite3 cache. :error', array(':error' => $e->getMessage()));
|
||||
}
|
||||
|
||||
return (bool) $statement->fetchAll();
|
||||
}
|
||||
}
|
42
includes/kohana/modules/cache/classes/kohana/cache/tagging.php
vendored
Normal file
42
includes/kohana/modules/cache/classes/kohana/cache/tagging.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Kohana Cache Tagging Interface
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
interface Kohana_Cache_Tagging {
|
||||
|
||||
/**
|
||||
* Set a value based on an id. Optionally add tags.
|
||||
*
|
||||
* Note : Some caching engines do not support
|
||||
* tagging
|
||||
*
|
||||
* @param string id
|
||||
* @param mixed data
|
||||
* @param integer lifetime [Optional]
|
||||
* @param array tags [Optional]
|
||||
* @return boolean
|
||||
*/
|
||||
public function set_with_tags($id, $data, $lifetime = NULL, array $tags = NULL);
|
||||
|
||||
/**
|
||||
* Delete cache entries based on a tag
|
||||
*
|
||||
* @param string tag
|
||||
* @param integer timeout [Optional]
|
||||
*/
|
||||
public function delete_tag($tag);
|
||||
|
||||
/**
|
||||
* Find cache entries based on a tag
|
||||
*
|
||||
* @param string tag
|
||||
* @return array
|
||||
*/
|
||||
public function find($tag);
|
||||
}
|
140
includes/kohana/modules/cache/classes/kohana/cache/wincache.php
vendored
Normal file
140
includes/kohana/modules/cache/classes/kohana/cache/wincache.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* [Kohana Cache](api/Kohana_Cache) Wincache driver. Provides an opcode based
|
||||
* driver for the Kohana Cache library.
|
||||
*
|
||||
* ### Configuration example
|
||||
*
|
||||
* Below is an example of an _wincache_ server configuration.
|
||||
*
|
||||
* return array(
|
||||
* 'wincache' => array( // Driver group
|
||||
* 'driver' => 'wincache', // using wincache driver
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* In cases where only one cache group is required, if the group is named `default` there is
|
||||
* no need to pass the group name when instantiating a cache instance.
|
||||
*
|
||||
* #### General cache group configuration settings
|
||||
*
|
||||
* Below are the settings available to all types of cache driver.
|
||||
*
|
||||
* Name | Required | Description
|
||||
* -------------- | -------- | ---------------------------------------------------------------
|
||||
* driver | __YES__ | (_string_) The driver type to use
|
||||
*
|
||||
* ### System requirements
|
||||
*
|
||||
* * Windows XP SP3 with IIS 5.1 and » FastCGI Extension
|
||||
* * Windows Server 2003 with IIS 6.0 and » FastCGI Extension
|
||||
* * Windows Vista SP1 with IIS 7.0 and FastCGI Module
|
||||
* * Windows Server 2008 with IIS 7.0 and FastCGI Module
|
||||
* * Windows 7 with IIS 7.5 and FastCGI Module
|
||||
* * Windows Server 2008 R2 with IIS 7.5 and FastCGI Module
|
||||
* * PHP 5.2.X, Non-thread-safe build
|
||||
* * PHP 5.3 X86, Non-thread-safe VC9 build
|
||||
*
|
||||
* @package Kohana/Cache
|
||||
* @category Base
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Wincache extends Cache {
|
||||
|
||||
/**
|
||||
* Check for existence of the wincache extension This method cannot be invoked externally. The driver must
|
||||
* be instantiated using the `Cache::instance()` method.
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
if ( ! extension_loaded('wincache'))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('PHP wincache extension is not available.');
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a cached value entry by id.
|
||||
*
|
||||
* // Retrieve cache entry from wincache group
|
||||
* $data = Cache::instance('wincache')->get('foo');
|
||||
*
|
||||
* // Retrieve cache entry from wincache group and return 'bar' if miss
|
||||
* $data = Cache::instance('wincache')->get('foo', 'bar');
|
||||
*
|
||||
* @param string id of cache to entry
|
||||
* @param string default value to return if cache miss
|
||||
* @return mixed
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
$data = wincache_ucache_get($this->_sanitize_id($id), $success);
|
||||
|
||||
return $success ? $data : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value to cache with id and lifetime
|
||||
*
|
||||
* $data = 'bar';
|
||||
*
|
||||
* // Set 'bar' to 'foo' in wincache group, using default expiry
|
||||
* Cache::instance('wincache')->set('foo', $data);
|
||||
*
|
||||
* // Set 'bar' to 'foo' in wincache group for 30 seconds
|
||||
* Cache::instance('wincache')->set('foo', $data, 30);
|
||||
*
|
||||
* @param string id of cache entry
|
||||
* @param string data to set to cache
|
||||
* @param integer lifetime in seconds
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = NULL)
|
||||
{
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
$lifetime = Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
return wincache_ucache_set($this->_sanitize_id($id), $data, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* // Delete 'foo' entry from the wincache group
|
||||
* Cache::instance('wincache')->delete('foo');
|
||||
*
|
||||
* @param string id to remove from cache
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
return wincache_ucache_delete($this->_sanitize_id($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries.
|
||||
*
|
||||
* Beware of using this method when
|
||||
* using shared memory cache systems, as it will wipe every
|
||||
* entry within the system for all clients.
|
||||
*
|
||||
* // Delete all cache entries in the wincache group
|
||||
* Cache::instance('wincache')->delete_all();
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
return wincache_ucache_clear();
|
||||
}
|
||||
}
|
84
includes/kohana/modules/cache/classes/kohana/cache/xcache.php
vendored
Normal file
84
includes/kohana/modules/cache/classes/kohana/cache/xcache.php
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Kohana Cache Xcache Driver
|
||||
*
|
||||
* Requires Xcache
|
||||
* http://xcache.lighttpd.net/
|
||||
*
|
||||
* @package Kohana
|
||||
* @category Cache
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2009-2010 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Cache_Xcache extends Cache {
|
||||
|
||||
/**
|
||||
* Check for existence of the APC extension
|
||||
*
|
||||
* @param array configuration
|
||||
* @throws Kohana_Cache_Exception
|
||||
*/
|
||||
protected function __construct(array $config)
|
||||
{
|
||||
if ( ! extension_loaded('xcache'))
|
||||
{
|
||||
throw new Kohana_Cache_Exception('PHP Xcache extension is not available.');
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a value based on an id
|
||||
*
|
||||
* @param string id
|
||||
* @param string default [Optional] Default value to return if id not found
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($id, $default = NULL)
|
||||
{
|
||||
return (($data = xcache_get($this->_sanitize_id($id))) === NULL) ? $default : $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value based on an id. Optionally add tags.
|
||||
*
|
||||
* @param string id
|
||||
* @param string data
|
||||
* @param integer lifetime [Optional]
|
||||
* @return boolean
|
||||
*/
|
||||
public function set($id, $data, $lifetime = NULL)
|
||||
{
|
||||
if (NULL === $lifetime)
|
||||
{
|
||||
$lifetime = Arr::get($this->_config, 'default_expire', Cache::DEFAULT_EXPIRE);
|
||||
}
|
||||
|
||||
return xcache_set($this->_sanitize_id($id), $data, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache entry based on id
|
||||
*
|
||||
* @param string id
|
||||
* @param integer timeout [Optional]
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
return xcache_unset($this->_sanitize_id($id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache entries
|
||||
* To use this method xcache.admin.enable_auth has to be Off in xcache.ini
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
xcache_clear_cache(XC_TYPE_PHP, 0);
|
||||
}
|
||||
}
|
76
includes/kohana/modules/cache/config/cache.php
vendored
Normal file
76
includes/kohana/modules/cache/config/cache.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
return array
|
||||
(
|
||||
'memcache' => array
|
||||
(
|
||||
'driver' => 'memcache',
|
||||
'default_expire' => 3600,
|
||||
'compression' => FALSE, // Use Zlib compression (can cause issues with integers)
|
||||
'servers' => array
|
||||
(
|
||||
array
|
||||
(
|
||||
'host' => 'localhost', // Memcache Server
|
||||
'port' => 11211, // Memcache port number
|
||||
'persistent' => FALSE, // Persistent connection
|
||||
'weight' => 1,
|
||||
'timeout' => 1,
|
||||
'retry_interval' => 15,
|
||||
'status' => TRUE,
|
||||
),
|
||||
),
|
||||
'instant_death' => TRUE, // Take server offline immediately on first fail (no retry)
|
||||
),
|
||||
'memcachetag' => array
|
||||
(
|
||||
'driver' => 'memcachetag',
|
||||
'default_expire' => 3600,
|
||||
'compression' => FALSE, // Use Zlib compression (can cause issues with integers)
|
||||
'servers' => array
|
||||
(
|
||||
array
|
||||
(
|
||||
'host' => 'localhost', // Memcache Server
|
||||
'port' => 11211, // Memcache port number
|
||||
'persistent' => FALSE, // Persistent connection
|
||||
'weight' => 1,
|
||||
'timeout' => 1,
|
||||
'retry_interval' => 15,
|
||||
'status' => TRUE,
|
||||
),
|
||||
),
|
||||
'instant_death' => TRUE,
|
||||
),
|
||||
'apc' => array
|
||||
(
|
||||
'driver' => 'apc',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
'wincache' => array
|
||||
(
|
||||
'driver' => 'wincache',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
'sqlite' => array
|
||||
(
|
||||
'driver' => 'sqlite',
|
||||
'default_expire' => 3600,
|
||||
'database' => APPPATH.'cache/kohana-cache.sql3',
|
||||
'schema' => 'CREATE TABLE caches(id VARCHAR(127) PRIMARY KEY, tags VARCHAR(255), expiration INTEGER, cache TEXT)',
|
||||
),
|
||||
'eaccelerator' => array
|
||||
(
|
||||
'driver' => 'eaccelerator',
|
||||
),
|
||||
'xcache' => array
|
||||
(
|
||||
'driver' => 'xcache',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
'file' => array
|
||||
(
|
||||
'driver' => 'file',
|
||||
'cache_dir' => APPPATH.'cache',
|
||||
'default_expire' => 3600,
|
||||
)
|
||||
);
|
23
includes/kohana/modules/cache/config/userguide.php
vendored
Normal file
23
includes/kohana/modules/cache/config/userguide.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
return array(
|
||||
// Leave this alone
|
||||
'modules' => array(
|
||||
|
||||
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
|
||||
'cache' => array(
|
||||
|
||||
// Whether this modules userguide pages should be shown
|
||||
'enabled' => TRUE,
|
||||
|
||||
// The name that should show up on the userguide index page
|
||||
'name' => 'Cache',
|
||||
|
||||
// A short description of this module, shown on the index page
|
||||
'description' => 'Common interface for caching engines.',
|
||||
|
||||
// Copyright message, shown in the footer for this module
|
||||
'copyright' => '© 2008–2010 Kohana Team',
|
||||
)
|
||||
)
|
||||
);
|
219
includes/kohana/modules/cache/guide/cache.usage.md
vendored
Normal file
219
includes/kohana/modules/cache/guide/cache.usage.md
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
# Kohana Cache usage
|
||||
|
||||
[Kohana_Cache] provides a simple interface allowing getting, setting and deleting of cached values. Two interfaces included in _Kohana Cache_ additionally provide _tagging_ and _garbage collection_ where they are supported by the respective drivers.
|
||||
|
||||
## Getting a new cache instance
|
||||
|
||||
Creating a new _Kohana Cache_ instance is simple, however it must be done using the [Cache::instance] method, rather than the traditional `new` constructor.
|
||||
|
||||
// Create a new instance of cache using the default group
|
||||
$cache = Cache::instance();
|
||||
|
||||
The default group will use whatever is set to [Cache::$default] and must have a corresponding [configuration](cache.config) definition for that group.
|
||||
|
||||
To create a cache instance using a group other than the _default_, simply provide the group name as an argument.
|
||||
|
||||
// Create a new instance of the memcache group
|
||||
$memcache = Cache::instance('memcache');
|
||||
|
||||
If there is a cache instance already instantiated then you can get it directly from the class member.
|
||||
|
||||
[!!] Beware that this can cause issues if you do not test for the instance before trying to access it.
|
||||
|
||||
// Check for the existance of the cache driver
|
||||
if (isset(Cache::$instances['memcache']))
|
||||
{
|
||||
// Get the existing cache instance directly (faster)
|
||||
$memcache = Cache::$instances['memcache'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the cache driver instance (slower)
|
||||
$memcache = Cache::instance('memcache');
|
||||
}
|
||||
|
||||
## Setting and getting variables to and from cache
|
||||
|
||||
The cache library supports scalar and object values, utilising object serialization where required (or not supported by the caching engine). This means that the majority or objects can be cached without any modification.
|
||||
|
||||
[!!] Serialisation does not work with resource handles, such as filesystem, curl or socket resources.
|
||||
|
||||
### Setting a value to cache
|
||||
|
||||
Setting a value to cache using the [Cache::set] method can be done in one of two ways; either using the Cache instance interface, which is good for atomic operations; or getting an instance and using that for multiple operations.
|
||||
|
||||
The first example demonstrates how to quickly load and set a value to the default cache instance.
|
||||
|
||||
// Create a cachable object
|
||||
$object = new stdClass;
|
||||
|
||||
// Set a property
|
||||
$object->foo = 'bar';
|
||||
|
||||
// Cache the object using default group (quick interface) with default time (3600 seconds)
|
||||
Cache::instance()->set('foo', $object);
|
||||
|
||||
If multiple cache operations are required, it is best to assign an instance of Cache to a variable and use that as below.
|
||||
|
||||
// Set the object using a defined group for a defined time period (30 seconds)
|
||||
$memcache = Cache::instance('memcache');
|
||||
$memcache->set('foo', $object, 30);
|
||||
|
||||
#### Setting a value with tags
|
||||
|
||||
Certain cache drivers support setting values with tags. To set a value to cache with tags using the following interface.
|
||||
|
||||
// Get a cache instance that supports tags
|
||||
$memcache = Cache::instance('memcachetag');
|
||||
|
||||
// Test for tagging interface
|
||||
if ($memcache instanceof Kohana_Cache_Tagging)
|
||||
{
|
||||
// Set a value with some tags for 30 seconds
|
||||
$memcache->set('foo', $object, 30, array('snafu', 'stfu', 'fubar'));
|
||||
}
|
||||
// Otherwise set without tags
|
||||
else
|
||||
{
|
||||
// Set a value for 30 seconds
|
||||
$memcache->set('foo', $object, 30);
|
||||
}
|
||||
|
||||
It is possible to implement custom tagging solutions onto existing or new cache drivers by implementing the [Kohana_Cache_Tagging] interface. Kohana_Cache only applies the interface to drivers that support tagging natively as standard.
|
||||
|
||||
### Getting a value from cache
|
||||
|
||||
Getting variables back from cache is achieved using the [Cache::get] method using a single key to identify the cache entry.
|
||||
|
||||
// Retrieve a value from cache (quickly)
|
||||
$object = Cache::instance()->get('foo');
|
||||
|
||||
In cases where the requested key is not available or the entry has expired, a default value will be returned (__NULL__ by default). It is possible to define the default value as the key is requested.
|
||||
|
||||
// If the cache key is available (with default value set to FALSE)
|
||||
if ($object = Cache::instance()->get('foo', FALSE))
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do something else
|
||||
}
|
||||
|
||||
#### Getting values from cache using tags
|
||||
|
||||
It is possible to retrieve values from cache grouped by tag, using the [Cache::find] method with drivers that support tagging.
|
||||
|
||||
[!!] The __Memcachetag__ driver does not support the `Cache::find($tag)` interface and will throw an exception.
|
||||
|
||||
// Get an instance of cache
|
||||
$cache = Cache::instance('memcachetag');
|
||||
|
||||
// Wrap in a try/catch statement to gracefully handle memcachetag
|
||||
try
|
||||
{
|
||||
// Find values based on tag
|
||||
return $cache->find('snafu');
|
||||
}
|
||||
catch (Kohana_Cache_Exception $e)
|
||||
{
|
||||
// Handle gracefully
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
### Deleting values from cache
|
||||
|
||||
Deleting variables is very similar to the getting and setting methods already described. Deleting operations are split into three categories:
|
||||
|
||||
- __Delete value by key__. Deletes a cached value by the associated key.
|
||||
- __Delete all values__. Deletes all caches values stored in the cache instance.
|
||||
- __Delete values by tag__. Deletes all values that have the supplied tag. This is only supported by Memcached-Tag and Sqlite.
|
||||
|
||||
#### Delete value by key
|
||||
|
||||
To delete a specific value by its associated key:
|
||||
|
||||
// If the cache entry for 'foo' is deleted
|
||||
if (Cache::instance()->delete('foo'))
|
||||
{
|
||||
// Cache entry successfully deleted, do something
|
||||
}
|
||||
|
||||
By default a `TRUE` value will be returned. However a `FALSE` value will be returned in instances where the key did not exist in the cache.
|
||||
|
||||
#### Delete all values
|
||||
|
||||
To delete all values in a specific instance:
|
||||
|
||||
// If all cache items where deleted successfully
|
||||
if (Cache::instance()->delete_all())
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
|
||||
It is also possible to delete all cache items in every instance:
|
||||
|
||||
// For each cache instance
|
||||
foreach (Cache::$instances as $group => $instance)
|
||||
{
|
||||
if ($instance->delete_all())
|
||||
{
|
||||
var_dump('instance : '.$group.' has been flushed!');
|
||||
}
|
||||
}
|
||||
|
||||
#### Delete values by tag
|
||||
|
||||
Some of the caching drivers support deleting by tag. This will remove all the cached values that are associated with a specific tag. Below is an example of how to robustly handle deletion by tag.
|
||||
|
||||
// Get cache instance
|
||||
$cache = Cache::instance();
|
||||
|
||||
// Check for tagging interface
|
||||
if ($cache instanceof Kohana_Cache_Tagging)
|
||||
{
|
||||
// Delete all entries by the tag 'snafu'
|
||||
$cache->delete_tag('snafu');
|
||||
}
|
||||
|
||||
#### Garbage Collection
|
||||
|
||||
Garbage Collection (GC) is the cleaning of expired cache entries. For the most part, caching engines will take care of garbage collection internally. However a few of the file based systems do not handle this task and in these circumstances it would be prudent to garbage collect at a predetermined frequency. If no garbage collection is executed, the resource storing the cache entries will eventually fill and become unusable.
|
||||
|
||||
When not automated, garbage collection is the responsibility of the developer. It is prudent to have a GC probability value that dictates how likely the garbage collection routing will be run. An example of such a system is demonstrated below.
|
||||
|
||||
// Get a cache instance
|
||||
$cache_file = Cache::instance('file');
|
||||
|
||||
// Set a GC probability of 10%
|
||||
$gc = 10;
|
||||
|
||||
// If the GC probability is a hit
|
||||
if (rand(0,99) <= $gc and $cache_file instanceof Kohana_Cache_GarbageCollect)
|
||||
{
|
||||
// Garbage Collect
|
||||
$cache_file->garbage_collect();
|
||||
}
|
||||
|
||||
# Interfaces
|
||||
|
||||
Kohana Cache comes with two interfaces that are implemented where the drivers support them:
|
||||
|
||||
- __[Kohana_Cache_Tagging] for tagging support on cache entries__
|
||||
- [Cache_MemcacheTag]
|
||||
- [Cache_Sqlite]
|
||||
- __[Kohana_Cache_GarbageCollect] for garbage collection with drivers without native support__
|
||||
- [Cache_File]
|
||||
- [Cache_Sqlite]
|
||||
|
||||
When using interface specific caching features, ensure that code checks for the required interface before using the methods supplied. The following example checks whether the garbage collection interface is available before calling the `garbage_collect` method.
|
||||
|
||||
// Create a cache instance
|
||||
$cache = Cache::instance();
|
||||
|
||||
// Test for Garbage Collection
|
||||
if ($cache instanceof Kohana_Cache_GarbageCollect)
|
||||
{
|
||||
// Collect garbage
|
||||
$cache->garbage_collect();
|
||||
}
|
168
includes/kohana/modules/cache/guide/cache/config.md
vendored
Normal file
168
includes/kohana/modules/cache/guide/cache/config.md
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
# Kohana Cache configuration
|
||||
|
||||
Kohana Cache uses configuration groups to create cache instances. A configuration group can
|
||||
use any supported driver, with successive groups using multiple instances of the same driver type.
|
||||
|
||||
The default cache group is loaded based on the `Cache::$default` setting. It is set to the `file` driver as standard, however this can be changed within the `/application/boostrap.php` file.
|
||||
|
||||
// Change the default cache driver to memcache
|
||||
Cache::$default = 'memcache';
|
||||
|
||||
// Load the memcache cache driver using default setting
|
||||
$memcache = Cache::instance();
|
||||
|
||||
## Group settings
|
||||
|
||||
Below are the default cache configuration groups for each supported driver. Add to- or override these settings
|
||||
within the `application/config/cache.php` file.
|
||||
|
||||
Name | Required | Description
|
||||
-------------- | -------- | ---------------------------------------------------------------
|
||||
driver | __YES__ | (_string_) The driver type to use
|
||||
default_expire | __NO__ | (_string_) The driver type to use
|
||||
|
||||
|
||||
'file' => array
|
||||
(
|
||||
'driver' => 'file',
|
||||
'cache_dir' => APPPATH.'cache/.kohana_cache',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
|
||||
## Memcache & Memcached-tag settings
|
||||
|
||||
Name | Required | Description
|
||||
-------------- | -------- | ---------------------------------------------------------------
|
||||
driver | __YES__ | (_string_) The driver type to use
|
||||
servers | __YES__ | (_array_) Associative array of server details, must include a __host__ key. (see _Memcache server configuration_ below)
|
||||
compression | __NO__ | (_boolean_) Use data compression when caching
|
||||
|
||||
### Memcache server configuration
|
||||
|
||||
Name | Required | Description
|
||||
---------------- | -------- | ---------------------------------------------------------------
|
||||
host | __YES__ | (_string_) The host of the memcache server, i.e. __localhost__; or __127.0.0.1__; or __memcache.domain.tld__
|
||||
port | __NO__ | (_integer_) Point to the port where memcached is listening for connections. Set this parameter to 0 when using UNIX domain sockets. Default __11211__
|
||||
persistent | __NO__ | (_boolean_) Controls the use of a persistent connection. Default __TRUE__
|
||||
weight | __NO__ | (_integer_) Number of buckets to create for this server which in turn control its probability of it being selected. The probability is relative to the total weight of all servers. Default __1__
|
||||
timeout | __NO__ | (_integer_) Value in seconds which will be used for connecting to the daemon. Think twice before changing the default value of 1 second - you can lose all the advantages of caching if your connection is too slow. Default __1__
|
||||
retry_interval | __NO__ | (_integer_) Controls how often a failed server will be retried, the default value is 15 seconds. Setting this parameter to -1 disables automatic retry. Default __15__
|
||||
status | __NO__ | (_boolean_) Controls if the server should be flagged as online. Default __TRUE__
|
||||
failure_callback | __NO__ | (_[callback](http://www.php.net/manual/en/language.pseudo-types.php#language.types.callback)_) Allows the user to specify a callback function to run upon encountering an error. The callback is run before failover is attempted. The function takes two parameters, the hostname and port of the failed server. Default __NULL__
|
||||
|
||||
'memcache' => array
|
||||
(
|
||||
'driver' => 'memcache',
|
||||
'default_expire' => 3600,
|
||||
'compression' => FALSE, // Use Zlib compression
|
||||
(can cause issues with integers)
|
||||
'servers' => array
|
||||
(
|
||||
array
|
||||
(
|
||||
'host' => 'localhost', // Memcache Server
|
||||
'port' => 11211, // Memcache port number
|
||||
'persistent' => FALSE, // Persistent connection
|
||||
),
|
||||
),
|
||||
),
|
||||
'memcachetag' => array
|
||||
(
|
||||
'driver' => 'memcachetag',
|
||||
'default_expire' => 3600,
|
||||
'compression' => FALSE, // Use Zlib compression
|
||||
(can cause issues with integers)
|
||||
'servers' => array
|
||||
(
|
||||
array
|
||||
(
|
||||
'host' => 'localhost', // Memcache Server
|
||||
'port' => 11211, // Memcache port number
|
||||
'persistent' => FALSE, // Persistent connection
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
## APC settings
|
||||
|
||||
'apc' => array
|
||||
(
|
||||
'driver' => 'apc',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
|
||||
## SQLite settings
|
||||
|
||||
'sqlite' => array
|
||||
(
|
||||
'driver' => 'sqlite',
|
||||
'default_expire' => 3600,
|
||||
'database' => APPPATH.'cache/kohana-cache.sql3',
|
||||
'schema' => 'CREATE TABLE caches(id VARCHAR(127) PRIMARY KEY,
|
||||
tags VARCHAR(255), expiration INTEGER, cache TEXT)',
|
||||
),
|
||||
|
||||
## Eaccelerator settings
|
||||
|
||||
'eaccelerator' array
|
||||
(
|
||||
'driver' => 'eaccelerator',
|
||||
),
|
||||
|
||||
## Xcache settings
|
||||
|
||||
'xcache' => array
|
||||
(
|
||||
'driver' => 'xcache',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
|
||||
## File settings
|
||||
|
||||
'file' => array
|
||||
(
|
||||
'driver' => 'file',
|
||||
'cache_dir' => 'cache/.kohana_cache',
|
||||
'default_expire' => 3600,
|
||||
)
|
||||
|
||||
## Override existing configuration group
|
||||
|
||||
The following example demonstrates how to override an existing configuration setting, using the config file in `/application/config/cache.php`.
|
||||
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
return array
|
||||
(
|
||||
// Override the default configuration
|
||||
'memcache' => array
|
||||
(
|
||||
'driver' => 'memcache', // Use Memcached as the default driver
|
||||
'default_expire' => 8000, // Overide default expiry
|
||||
'servers' => array
|
||||
(
|
||||
// Add a new server
|
||||
array
|
||||
(
|
||||
'host' => 'cache.domain.tld',
|
||||
'port' => 11211,
|
||||
'persistent' => FALSE
|
||||
)
|
||||
),
|
||||
'compression' => FALSE
|
||||
)
|
||||
);
|
||||
|
||||
## Add new configuration group
|
||||
|
||||
The following example demonstrates how to add a new configuration setting, using the config file in `/application/config/cache.php`.
|
||||
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
return array
|
||||
(
|
||||
// Override the default configuration
|
||||
'fastkv' => array
|
||||
(
|
||||
'driver' => 'apc', // Use Memcached as the default driver
|
||||
'default_expire' => 1000, // Overide default expiry
|
||||
)
|
||||
);
|
0
includes/kohana/modules/cache/guide/cache/examples.md
vendored
Normal file
0
includes/kohana/modules/cache/guide/cache/examples.md
vendored
Normal file
59
includes/kohana/modules/cache/guide/cache/index.md
vendored
Normal file
59
includes/kohana/modules/cache/guide/cache/index.md
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
# About Kohana Cache
|
||||
|
||||
[Kohana_Cache] provides a common interface to a variety of caching engines. [Kohana_Cache_Tagging] is
|
||||
supported where available natively to the cache system. Kohana Cache supports multiple
|
||||
instances of cache engines through a grouped singleton pattern.
|
||||
|
||||
## Supported cache engines
|
||||
|
||||
* APC ([Cache_Apc])
|
||||
* eAccelerator ([Cache_Eaccelerator])
|
||||
* File ([Cache_File])
|
||||
* Memcached ([Cache_Memcache])
|
||||
* Memcached-tags ([Cache_Memcachetag])
|
||||
* SQLite ([Cache_Sqlite])
|
||||
* Xcache ([Cache_Xcache])
|
||||
|
||||
## Introduction to caching
|
||||
|
||||
Caching should be implemented with consideration. Generally, caching the result of resources
|
||||
is faster than reprocessing them. Choosing what, how and when to cache is vital. [PHP APC](http://php.net/manual/en/book.apc.php) is one of the fastest caching systems available, closely followed by [Memcached](http://memcached.org/). [SQLite](http://www.sqlite.org/) and File caching are two of the slowest cache methods, however usually faster than reprocessing
|
||||
a complex set of instructions.
|
||||
|
||||
Caching engines that use memory are considerably faster than file based alternatives. But
|
||||
memory is limited whereas disk space is plentiful. If caching large datasets, such as large database result sets, it is best to use file caching.
|
||||
|
||||
[!!] Cache drivers require the relevant PHP extensions to be installed. APC, eAccelerator, Memecached and Xcache all require non-standard PHP extensions.
|
||||
|
||||
## What the Kohana Cache module does (and does not do)
|
||||
|
||||
This module provides a simple abstracted interface to a wide selection of popular PHP cache engines. The caching API provides the basic caching methods implemented across all solutions, memory, network or disk based. Basic key / value storing is supported by all drivers, with additional tagging and garbage collection support where implemented or required.
|
||||
|
||||
_Kohana Cache_ does not provide HTTP style caching for clients (web browsers) and/or proxies (_Varnish_, _Squid_). There are other Kohana modules that provide this functionality.
|
||||
|
||||
## Choosing a cache provider
|
||||
|
||||
Getting and setting values to cache is very simple when using the _Kohana Cache_ interface. The hardest choice is choosing which cache engine to use. When choosing a caching engine, the following criteria must be considered:
|
||||
|
||||
1. __Does the cache need to be distributed?__
|
||||
This is an important consideration as it will severely limit the options available to solutions such as Memcache when a distributed solution is required.
|
||||
2. __Does the cache need to be fast?__
|
||||
In almost all cases retrieving data from a cache is faster than execution. However generally memory based caching is considerably faster than disk based caching (see table below).
|
||||
3. __How much cache is required?__
|
||||
Cache is not endless, and memory based caches are subject to a considerably more limited storage resource.
|
||||
|
||||
Driver | Storage | Speed | Tags | Distributed | Automatic Garbage Collection | Notes
|
||||
---------------- | ------------ | --------- | -------- | ----------- | ---------------------------- | -----------------------
|
||||
APC | __Memory__ | Excellent | No | No | Yes | Widely available PHP opcode caching solution, improves php execution performance
|
||||
eAccelerator | __Memory__ | Excellent | No | No | Yes | Limited support and no longer developed. Included for legacy systems
|
||||
File | __Disk__ | Poor | No | No | No | Marginally faster than execution
|
||||
Memcache (tag) | __Memory__ | Good | No (yes) | Yes | Yes | Generally fast distributed solution, but has a speed hit due to variable network latency
|
||||
Sqlite | __Disk__ | Poor | Yes | No | No | Marginally faster than execution
|
||||
Xcache | __Memory__ | Excellent | Yes | No | Yes | Very fast memory solution and alternative to APC
|
||||
|
||||
It is possible to have hybrid cache solutions that use a combination of the engines above in different contexts. This is supported with _Kohana Cache_ as well.
|
||||
|
||||
## Minimum requirements
|
||||
|
||||
* Kohana 3.0.4
|
||||
* PHP 5.2.4 or greater
|
3
includes/kohana/modules/cache/guide/cache/menu.md
vendored
Normal file
3
includes/kohana/modules/cache/guide/cache/menu.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
## [Cache]()
|
||||
- [Configuration](config)
|
||||
- [Usage](usage)
|
219
includes/kohana/modules/cache/guide/cache/usage.md
vendored
Normal file
219
includes/kohana/modules/cache/guide/cache/usage.md
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
# Kohana Cache usage
|
||||
|
||||
[Kohana_Cache] provides a simple interface allowing getting, setting and deleting of cached values. Two interfaces included in _Kohana Cache_ additionally provide _tagging_ and _garbage collection_ where they are supported by the respective drivers.
|
||||
|
||||
## Getting a new cache instance
|
||||
|
||||
Creating a new _Kohana Cache_ instance is simple, however it must be done using the [Cache::instance] method, rather than the traditional `new` constructor.
|
||||
|
||||
// Create a new instance of cache using the default group
|
||||
$cache = Cache::instance();
|
||||
|
||||
The default group will use whatever is set to [Cache::$default] and must have a corresponding [configuration](cache.config) definition for that group.
|
||||
|
||||
To create a cache instance using a group other than the _default_, simply provide the group name as an argument.
|
||||
|
||||
// Create a new instance of the memcache group
|
||||
$memcache = Cache::instance('memcache');
|
||||
|
||||
If there is a cache instance already instantiated then you can get it directly from the class member.
|
||||
|
||||
[!!] Beware that this can cause issues if you do not test for the instance before trying to access it.
|
||||
|
||||
// Check for the existance of the cache driver
|
||||
if (isset(Cache::$instances['memcache']))
|
||||
{
|
||||
// Get the existing cache instance directly (faster)
|
||||
$memcache = Cache::$instances['memcache'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the cache driver instance (slower)
|
||||
$memcache = Cache::instance('memcache');
|
||||
}
|
||||
|
||||
## Setting and getting variables to and from cache
|
||||
|
||||
The cache library supports scalar and object values, utilising object serialization where required (or not supported by the caching engine). This means that the majority or objects can be cached without any modification.
|
||||
|
||||
[!!] Serialisation does not work with resource handles, such as filesystem, curl or socket resources.
|
||||
|
||||
### Setting a value to cache
|
||||
|
||||
Setting a value to cache using the [Cache::set] method can be done in one of two ways; either using the Cache instance interface, which is good for atomic operations; or getting an instance and using that for multiple operations.
|
||||
|
||||
The first example demonstrates how to quickly load and set a value to the default cache instance.
|
||||
|
||||
// Create a cachable object
|
||||
$object = new stdClass;
|
||||
|
||||
// Set a property
|
||||
$object->foo = 'bar';
|
||||
|
||||
// Cache the object using default group (quick interface) with default time (3600 seconds)
|
||||
Cache::instance()->set('foo', $object);
|
||||
|
||||
If multiple cache operations are required, it is best to assign an instance of Cache to a variable and use that as below.
|
||||
|
||||
// Set the object using a defined group for a defined time period (30 seconds)
|
||||
$memcache = Cache::instance('memcache');
|
||||
$memcache->set('foo', $object, 30);
|
||||
|
||||
#### Setting a value with tags
|
||||
|
||||
Certain cache drivers support setting values with tags. To set a value to cache with tags using the following interface.
|
||||
|
||||
// Get a cache instance that supports tags
|
||||
$memcache = Cache::instance('memcachetag');
|
||||
|
||||
// Test for tagging interface
|
||||
if ($memcache instanceof Kohana_Cache_Tagging)
|
||||
{
|
||||
// Set a value with some tags for 30 seconds
|
||||
$memcache->set('foo', $object, 30, array('snafu', 'stfu', 'fubar'));
|
||||
}
|
||||
// Otherwise set without tags
|
||||
else
|
||||
{
|
||||
// Set a value for 30 seconds
|
||||
$memcache->set('foo', $object, 30);
|
||||
}
|
||||
|
||||
It is possible to implement custom tagging solutions onto existing or new cache drivers by implementing the [Kohana_Cache_Tagging] interface. Kohana_Cache only applies the interface to drivers that support tagging natively as standard.
|
||||
|
||||
### Getting a value from cache
|
||||
|
||||
Getting variables back from cache is achieved using the [Cache::get] method using a single key to identify the cache entry.
|
||||
|
||||
// Retrieve a value from cache (quickly)
|
||||
$object = Cache::instance()->get('foo');
|
||||
|
||||
In cases where the requested key is not available or the entry has expired, a default value will be returned (__NULL__ by default). It is possible to define the default value as the key is requested.
|
||||
|
||||
// If the cache key is available (with default value set to FALSE)
|
||||
if ($object = Cache::instance()->get('foo', FALSE))
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do something else
|
||||
}
|
||||
|
||||
#### Getting values from cache using tags
|
||||
|
||||
It is possible to retrieve values from cache grouped by tag, using the [Cache::find] method with drivers that support tagging.
|
||||
|
||||
[!!] The __Memcachetag__ driver does not support the `Cache::find($tag)` interface and will throw an exception.
|
||||
|
||||
// Get an instance of cache
|
||||
$cache = Cache::instance('memcachetag');
|
||||
|
||||
// Wrap in a try/catch statement to gracefully handle memcachetag
|
||||
try
|
||||
{
|
||||
// Find values based on tag
|
||||
return $cache->find('snafu');
|
||||
}
|
||||
catch (Kohana_Cache_Exception $e)
|
||||
{
|
||||
// Handle gracefully
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
### Deleting values from cache
|
||||
|
||||
Deleting variables is very similar to the getting and setting methods already described. Deleting operations are split into three categories:
|
||||
|
||||
- __Delete value by key__. Deletes a cached value by the associated key.
|
||||
- __Delete all values__. Deletes all caches values stored in the cache instance.
|
||||
- __Delete values by tag__. Deletes all values that have the supplied tag. This is only supported by Memcached-Tag and Sqlite.
|
||||
|
||||
#### Delete value by key
|
||||
|
||||
To delete a specific value by its associated key:
|
||||
|
||||
// If the cache entry for 'foo' is deleted
|
||||
if (Cache::instance()->delete('foo'))
|
||||
{
|
||||
// Cache entry successfully deleted, do something
|
||||
}
|
||||
|
||||
By default a `TRUE` value will be returned. However a `FALSE` value will be returned in instances where the key did not exist in the cache.
|
||||
|
||||
#### Delete all values
|
||||
|
||||
To delete all values in a specific instance:
|
||||
|
||||
// If all cache items where deleted successfully
|
||||
if (Cache::instance()->delete_all())
|
||||
{
|
||||
// Do something
|
||||
}
|
||||
|
||||
It is also possible to delete all cache items in every instance:
|
||||
|
||||
// For each cache instance
|
||||
foreach (Cache::$instances as $group => $instance)
|
||||
{
|
||||
if ($instance->delete_all())
|
||||
{
|
||||
var_dump('instance : '.$group.' has been flushed!');
|
||||
}
|
||||
}
|
||||
|
||||
#### Delete values by tag
|
||||
|
||||
Some of the caching drivers support deleting by tag. This will remove all the cached values that are associated with a specific tag. Below is an example of how to robustly handle deletion by tag.
|
||||
|
||||
// Get cache instance
|
||||
$cache = Cache::instance();
|
||||
|
||||
// Check for tagging interface
|
||||
if ($cache instanceof Kohana_Cache_Tagging)
|
||||
{
|
||||
// Delete all entries by the tag 'snafu'
|
||||
$cache->delete_tag('snafu');
|
||||
}
|
||||
|
||||
#### Garbage Collection
|
||||
|
||||
Garbage Collection (GC) is the cleaning of expired cache entries. For the most part, caching engines will take care of garbage collection internally. However a few of the file based systems do not handle this task and in these circumstances it would be prudent to garbage collect at a predetermined frequency. If no garbage collection is executed, the resource storing the cache entries will eventually fill and become unusable.
|
||||
|
||||
When not automated, garbage collection is the responsibility of the developer. It is prudent to have a GC probability value that dictates how likely the garbage collection routing will be run. An example of such a system is demonstrated below.
|
||||
|
||||
// Get a cache instance
|
||||
$cache_file = Cache::instance('file');
|
||||
|
||||
// Set a GC probability of 10%
|
||||
$gc = 10;
|
||||
|
||||
// If the GC probability is a hit
|
||||
if (rand(0,99) <= $gc and $cache_file instanceof Kohana_Cache_GarbageCollect)
|
||||
{
|
||||
// Garbage Collect
|
||||
$cache_file->garbage_collect();
|
||||
}
|
||||
|
||||
# Interfaces
|
||||
|
||||
Kohana Cache comes with two interfaces that are implemented where the drivers support them:
|
||||
|
||||
- __[Kohana_Cache_Tagging] for tagging support on cache entries__
|
||||
- [Cache_MemcacheTag]
|
||||
- [Cache_Sqlite]
|
||||
- __[Kohana_Cache_GarbageCollect] for garbage collection with drivers without native support__
|
||||
- [Cache_File]
|
||||
- [Cache_Sqlite]
|
||||
|
||||
When using interface specific caching features, ensure that code checks for the required interface before using the methods supplied. The following example checks whether the garbage collection interface is available before calling the `garbage_collect` method.
|
||||
|
||||
// Create a cache instance
|
||||
$cache = Cache::instance();
|
||||
|
||||
// Test for Garbage Collection
|
||||
if ($cache instanceof Kohana_Cache_GarbageCollect)
|
||||
{
|
||||
// Collect garbage
|
||||
$cache->garbage_collect();
|
||||
}
|
91
includes/kohana/modules/cache/tests/cache/KohanaCacheTest.php
vendored
Normal file
91
includes/kohana/modules/cache/tests/cache/KohanaCacheTest.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
class KohanaCacheTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
static protected $test_instance;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
self::$test_instance = Cache::instance('file');
|
||||
self::$test_instance->delete_all();
|
||||
|
||||
self::$test_instance->set('testGet1', 'foo', 3600);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
self::$test_instance->delete_all();
|
||||
self::$test_instance = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the cache static instance method
|
||||
*/
|
||||
public function testInstance()
|
||||
{
|
||||
$file_instance = Cache::instance('file');
|
||||
$file_instance2 = Cache::instance('file');
|
||||
|
||||
// Try and load a Cache instance
|
||||
$this->assertType('Kohana_Cache', Cache::instance());
|
||||
$this->assertType('Kohana_Cache_File', $file_instance);
|
||||
|
||||
// Test instances are only initialised once
|
||||
$this->assertTrue(spl_object_hash($file_instance) == spl_object_hash($file_instance2));
|
||||
|
||||
// Test the publically accessible Cache instance store
|
||||
$this->assertTrue(spl_object_hash(Cache::$instances['file']) == spl_object_hash($file_instance));
|
||||
|
||||
// Get the constructor method
|
||||
$constructorMethod = new ReflectionMethod($file_instance, '__construct');
|
||||
|
||||
// Test the constructor for hidden visibility
|
||||
$this->assertTrue($constructorMethod->isProtected(), '__construct is does not have protected visibility');
|
||||
}
|
||||
|
||||
public function testGet()
|
||||
{
|
||||
// Try and get a non property
|
||||
$this->assertNull(self::$test_instance->get('testGet0'));
|
||||
|
||||
// Try and get a non property with default return value
|
||||
$this->assertEquals('bar', self::$test_instance->get('testGet0', 'bar'));
|
||||
|
||||
// Try and get a real cached property
|
||||
$this->assertEquals('foo', self::$test_instance->get('testGet1'));
|
||||
}
|
||||
|
||||
public function testSet()
|
||||
{
|
||||
$value = 'foobar';
|
||||
$value2 = 'snafu';
|
||||
|
||||
// Set a new property
|
||||
$this->assertTrue(self::$test_instance->set('testSet1', $value));
|
||||
|
||||
// Test the property exists
|
||||
$this->assertEquals(self::$test_instance->get('testSet1'), $value);
|
||||
|
||||
// Test short set
|
||||
$this->assertTrue(self::$test_instance->set('testSet2', $value2, 3));
|
||||
|
||||
// Test the property exists
|
||||
$this->assertEquals(self::$test_instance->get('testSet2'), $value2);
|
||||
|
||||
// Allow test2 to expire
|
||||
sleep(4);
|
||||
|
||||
// Test the property has expired
|
||||
$this->assertNull(self::$test_instance->get('testSet2'));
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function testDeleteAll()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
16
includes/kohana/modules/cache/tests/phpunit.xml
vendored
Normal file
16
includes/kohana/modules/cache/tests/phpunit.xml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<!--
|
||||
This is an example phpunit.xml file to get you started
|
||||
Copy it to a directory, update the relative paths and rename to phpunit.xml
|
||||
Then to run tests cd into it's directory and just run
|
||||
phpunit
|
||||
(it'll automatically use any phpunit.xml file in the current directory)
|
||||
|
||||
Any options you specify when calling phpunit will override the ones in here
|
||||
-->
|
||||
<phpunit colors="true" bootstrap="../../../articles/public/index.php">
|
||||
<testsuites>
|
||||
<testsuite name="Kohana Cache Tests">
|
||||
<directory suffix=".php">cache/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
Reference in New Issue
Block a user