You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.9 KiB
197 lines
6.9 KiB
<?php
|
|
/**
|
|
* li₃: the most RAD framework for PHP (http://li3.me)
|
|
*
|
|
* Copyright 2009, Union of RAD. All rights reserved. This source
|
|
* code is distributed under the terms of the BSD 3-Clause License.
|
|
* The full license text can be found in the LICENSE.txt file.
|
|
*/
|
|
|
|
namespace lithium\storage\cache\adapter;
|
|
|
|
if (!class_exists('\lithium\storage\cache\Adapter')) {
|
|
$message = 'The file (`' . __FILE__ . '`) has probably been included directly within ';
|
|
$message .= 'the bootstrap process. Due to its dependencies it should be (auto-)loaded ';
|
|
$message .= 'i.e. through the `Libraries` class exclusively. Please update your app\'s ';
|
|
$message .= 'bootstrap directory to the most recent version or remove the line where ';
|
|
$message .= 'this file was originally included. ';
|
|
$message .= 'See https://git.io/voxgh for the most recent version.';
|
|
trigger_error($message, E_USER_DEPRECATED);
|
|
|
|
require_once LITHIUM_LIBRARY_PATH . '/lithium/storage/cache/Adapter.php';
|
|
}
|
|
|
|
use lithium\storage\Cache;
|
|
|
|
/**
|
|
* An Alternative PHP Cache (APC) cache adapter implementation leveraging the user-
|
|
* space caching features (not the opcode caching features) of the cache.
|
|
*
|
|
* This adapter requires `pecl/apc` or `pecl/apcu` to be installed. The extension
|
|
* and user-space caching must be enabled according to the extension documention.
|
|
*
|
|
* This adapter natively handles multi-key reads/writes/deletes, natively
|
|
* provides serialization features and supports atomic increment/decrement
|
|
* operations as well as clearing the entire user-space cache.
|
|
*
|
|
* Cached item persistence is not guaranteed. Infrequently used items will
|
|
* be evicted from the cache when there is no room to store new ones. Scope
|
|
* is available but not natively.
|
|
*
|
|
* A simple configuration can be accomplished as follows:
|
|
*
|
|
* ```
|
|
* Cache::config([
|
|
* 'default' => ['adapter' => 'Apc']
|
|
* ]);
|
|
* ```
|
|
*
|
|
* @link http://pecl.php.net/package/APCu
|
|
* @link http://pecl.php.net/package/APC
|
|
* @link http://php.net/book.apc.php
|
|
* @see lithium\storage\Cache::key()
|
|
*/
|
|
class Apc extends \lithium\storage\cache\Adapter {
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @see lithium\storage\Cache::config()
|
|
* @param array $config Configuration for this cache adapter. These settings are queryable
|
|
* through `Cache::config('name')`. The available options are as follows:
|
|
* - `'scope'` _string_: Scope which will prefix keys; per default not set.
|
|
* - `'expiry'` _mixed_: The default expiration time for cache values, if no value
|
|
* is otherwise set. Can be either a `strtotime()` compatible tring or TTL in
|
|
* seconds. To indicate items should not expire use `Cache::PERSIST`. Defaults
|
|
* to `+1 hour`.
|
|
* @return void
|
|
*/
|
|
public function __construct(array $config = []) {
|
|
$defaults = [
|
|
'scope' => null,
|
|
'expiry' => '+1 hour'
|
|
];
|
|
parent::__construct($config + $defaults);
|
|
}
|
|
|
|
/**
|
|
* Write values to the cache. All items to be cached will receive an
|
|
* expiration time of `$expiry`.
|
|
*
|
|
* @param array $keys Key/value pairs with keys to uniquely identify the to-be-cached item.
|
|
* @param string|integer $expiry A `strtotime()` compatible cache time or TTL in seconds.
|
|
* To persist an item use `\lithium\storage\Cache::PERSIST`.
|
|
* @return boolean `true` on successful write, `false` otherwise.
|
|
*/
|
|
public function write(array $keys, $expiry = null) {
|
|
$expiry = $expiry || $expiry === Cache::PERSIST ? $expiry : $this->_config['expiry'];
|
|
|
|
if (!$expiry || $expiry === Cache::PERSIST) {
|
|
$ttl = 0;
|
|
} elseif (is_int($expiry)) {
|
|
$ttl = $expiry;
|
|
} else {
|
|
$ttl = strtotime($expiry) - time();
|
|
}
|
|
if ($this->_config['scope']) {
|
|
$keys = $this->_addScopePrefix($this->_config['scope'], $keys);
|
|
}
|
|
return apc_store($keys, null, $ttl) === [];
|
|
}
|
|
|
|
/**
|
|
* Read values from the cache. Will attempt to return an array of data
|
|
* containing key/value pairs of the requested data.
|
|
*
|
|
* @param array $keys Keys to uniquely identify the cached items.
|
|
* @return array Cached values keyed by cache keys on successful read,
|
|
* keys which could not be read will not be included in
|
|
* the results array.
|
|
*/
|
|
public function read(array $keys) {
|
|
if ($this->_config['scope']) {
|
|
$keys = $this->_addScopePrefix($this->_config['scope'], $keys);
|
|
}
|
|
$results = apc_fetch($keys);
|
|
|
|
if ($this->_config['scope']) {
|
|
$results = $this->_removeScopePrefix($this->_config['scope'], $results);
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
/**
|
|
* Will attempt to remove specified keys from the user space cache.
|
|
*
|
|
* @param array $keys Keys to uniquely identify the cached items.
|
|
* @return boolean `true` on successful delete, `false` otherwise.
|
|
*/
|
|
public function delete(array $keys) {
|
|
if ($this->_config['scope']) {
|
|
$keys = $this->_addScopePrefix($this->_config['scope'], $keys);
|
|
}
|
|
return apc_delete($keys) === [];
|
|
}
|
|
|
|
/**
|
|
* Performs an atomic decrement operation on specified numeric cache item.
|
|
*
|
|
* Note that, as per the APC specification:
|
|
* If the item's value is not numeric, the decrement operation has no effect
|
|
* on the key - it retains its original non-integer value.
|
|
*
|
|
* @param string $key Key of numeric cache item to decrement.
|
|
* @param integer $offset Offset to decrement - defaults to `1`.
|
|
* @return integer|boolean The item's new value on successful decrement, else `false`.
|
|
*/
|
|
public function decrement($key, $offset = 1) {
|
|
return apc_dec(
|
|
$this->_config['scope'] ? "{$this->_config['scope']}:{$key}" : $key, $offset
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Performs an atomic increment operation on specified numeric cache item.
|
|
*
|
|
* Note that, as per the APC specification:
|
|
* If the item's value is not numeric, the increment operation has no effect
|
|
* on the key - it retains its original non-integer value.
|
|
*
|
|
* @param string $key Key of numeric cache item to increment.
|
|
* @param integer $offset Offset to increment - defaults to `1`.
|
|
* @return integer|boolean The item's new value on successful increment, else `false`.
|
|
*/
|
|
public function increment($key, $offset = 1) {
|
|
return apc_inc(
|
|
$this->_config['scope'] ? "{$this->_config['scope']}:{$key}" : $key, $offset
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Clears entire user-space cache by flushing it. All cache keys
|
|
* using the configuration but *without* honoring the scope are removed.
|
|
*
|
|
* The behavior and result when removing a single key
|
|
* during this process fails is unknown.
|
|
*
|
|
* @return boolean `true` on successful clearing, `false` otherwise.
|
|
*/
|
|
public function clear() {
|
|
return apc_clear_cache('user');
|
|
}
|
|
|
|
/**
|
|
* Determines if the APC extension has been installed and
|
|
* if the userspace cache is available.
|
|
*
|
|
* @return boolean `true` if enabled, `false` otherwise.
|
|
*/
|
|
public static function enabled() {
|
|
$loaded = extension_loaded('apc');
|
|
$isCli = (php_sapi_name() === 'cli');
|
|
$enabled = (!$isCli && ini_get('apc.enabled')) || ($isCli && ini_get('apc.enable_cli'));
|
|
return ($loaded && $enabled);
|
|
}
|
|
}
|
|
|
|
?>
|