Apache Zeta Components Manual :: File Source for memory.php
Source for file memory.php
Documentation is available at memory.php
* File containing the ezcCacheStorageMemory class.
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* @version //autogentag//
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* Base abstract class for all memory storage classes.
* Abstract classes extending this class:
* - {@link ezcCacheStorageMemcache}
* - {@link ezcCacheStorageApc}
* Implementations derived from this class and its descendants:
* - {@link ezcCacheStorageMemcachePlain}
* - {@link ezcCacheStorageApcPlain}
* - {@link ezcCacheStorageFileApcArray}
* @version //autogentag//
* Holds the memory backend object which communicates with the memory handler
* @var ezcCacheMemoryBackend
* Holds the name of the memory backend.
* Holds the name of the registry.
* Holds the search registry.
* Wether this storage holds a lock.
* Creates a new cache storage in the given location.
* Options can contain the 'ttl' (Time-To-Live). Specific implementations
* can have additional options.
* @throws ezcBasePropertyNotFoundException
* If you tried to set a non-existent option value. The accepted
* options depend on the ezcCacheStorage implementation and may
* @param string $location Path to the cache location. Null for
* memory-based storage and an existing
* writeable path for file or memory/file
* @param array(string=>string) $options Options for the cache
public function __construct( $location, array $options =
array() )
* Stores data to the cache storage under the key $id.
* The type of cache data which is expected by an ezcCacheStorageMemory
* implementation depends on the backend. In most cases strings and arrays
* will be accepted, in some rare cases only strings might be accepted.
* Using attributes you can describe your cache data further. This allows
* you to deal with multiple cache data at once later. Some
* ezcCacheStorageMemory implementations also use the attributes for storage
* purposes. Attributes form some kind of "extended ID".
* @return string The ID string of the newly cached data
* @param string $id Unique identifier for the data
* @param mixed $data The data to store
* @param array(string=>string) $attributes Attributes describing the cached data
public function store( $id, $data, $attributes =
array() )
// Generate the Identifier
if ( isset
( $this->registry[$location][$id][$identifier] ) )
unset
( $this->registry[$location][$id][$identifier] );
$dataStr =
$this->prepareData( $data );
$exceptionClass =
"ezcCache{$this->backendName}Exception
";
throw new $exceptionClass( "{
$this->backendName} store failed.
" );
* Restores the data from the cache.
* During access to cached data the caches are automatically
* expired. This means, that the ezcCacheStorageMemory object checks
* before returning the data if it's still actual. If the cache
* has expired, data will be deleted and false is returned.
* You should always provide the attributes you assigned, although
* the cache storages must be able to find a cache ID even without
* them. BEWARE: Finding cache data only by ID can be much
* slower than finding it by ID and attributes.
* @param string $id The item ID to restore
* @param array(string=>string) $attributes Attributes describing the data to restore
* @param bool $search Whether to search for items if not found directly
* @return mixed The cached data on success, otherwise false
public function restore( $id, $attributes = array(), $search = false )
// Generate the Identifier
// Creates a registry object
if ( !isset
( $this->registry[$location][$id][$identifier] ) )
if ( !isset( $this->registry[$location] ) )
if ( !isset( $this->registry[$location][$id] ) )
$this->registry[$location][$id] =
array();
$this->registry[$location][$id][$identifier] =
$this->fetchData( $identifier, true );
// Makes sure a cache exists
if ( $this->registry[$location][$id][$identifier] ===
false )
&& count( $identifiers = $this->search( $id, $attributes ) ) ===
1 )
$identifier = $identifiers[0][2];
$this->registry[$location][$id][$identifier] =
$this->fetchData( $identifier, true );
// There are more elements found during search, so false is returned
// Make sure the data is not supposed to be expired
if ( $this->properties['options']['ttl'] !==
false
$this->delete( $id, $attributes, false );
$data = is_object( $this->registry[$location][$id][$identifier] ) ?
$this->registry[$location][$id][$identifier]->data :
false;
* Deletes the data associated with $id or $attributes from the cache.
* Additional attributes provided will matched additionally. This can give
* you an immense speed improvement against just searching for ID (see
* {@link ezcCacheStorage::restore()}).
* If you only provide attributes for deletion of cache data, all cache
* data matching these attributes will be purged.
* @throws ezcBaseFilePermissionException
* If an already existsing cache file could not be unlinked.
* This exception means most likely that your cache directory
* has been corrupted by external influences (file permission
* @param string $id The item ID to purge
* @param array(string=>string) $attributes Attributes describing the data to restore
* @param bool $search Whether to search for items if not found directly
public function delete( $id = null, $attributes = array(), $search = false )
// Generate the Identifier
// Finds the caches that require deletion
if ( $this->fetchData( $identifier ) !==
false )
$delCaches[] = array( $id, $attributes, $identifier );
else if ( $search === true )
$delCaches = $this->search( $id, $attributes );
// Process the caches to delete
foreach ( $delCaches as $cache )
$deletedIds[] =
$cache[0];
if ( isset
( $this->registry[$location][$cache[0]][$cache[2]] ) )
unset( $this->registry[$location][$cache[0]][$cache[2]] );
* Returns the number of items in the cache matching a certain criteria.
* This method determines if cache data described by the given ID and/or
* attributes exists. It returns the number of cache data items found.
* @param string $id The item ID
* @param array(string=>string) $attributes Attributes describing the data
* @return int Number of data items matching the criteria
public function countDataItems( $id = null, $attributes = array() )
return count( $this->search( $id, $attributes ) );
* Returns the time in seconds which remains for a cache object, before it
* gets outdated. In case the cache object is already outdated or does not
* exists, this method returns 0.
* @param string $id The item ID
* @param array(string=>string) $attributes Attributes describing the data
* @return int The remaining lifetime (0 if it does not exist or outdated)
public function getRemainingLifetime( $id, $attributes = array() )
if ( count( $found = $this->search( $id, $attributes ) ) >
0 )
$identifier = $found[0][2];
* Generates the storage internal identifier from ID and attributes.
* @param string $id The ID
* @param array(string=>string) $attributes Attributes describing the data
* @return string The generated identifier
public function generateIdentifier( $id, $attributes = null )
( $attributes !==
null &&
!empty( $attributes ) )
?
md5( serialize( $attributes ) )
return urlencode( $identifier );
* Purge outdated data from the storage.
* This method purges outdated data from the cache. If $limit is given, a
* maximum of $limit items is purged. Otherwise all outdated items are
* purged. The method returns an array containing the IDs of all cache
* items that have been purged.
public function purge( $limit = null )
foreach( $identifiers as $identifier => $data )
if ( $ttl !== false && $this->calcLifetime( $identifier ) ==
0 )
// Since ID <-> identifier mapping is ambigious, this does
// not ensure that all data for an ID is deleted. However,
// this should work if used properly
// Avoid adding an ID twice to the returned array
if ( $limit !== null && count( $purgedIds ) >= $limit )
* Reset the complete storage.
* This method resets the complete cache storage. All content (including
* content stored with the {@link ezcCacheStackMetaDataStorage} interfacer) must
* be deleted and the cache storage must appear as if it has just newly
* Restores and returns the meta data struct.
* This method fetches the meta data stored in the storage and returns the
* according struct of type {@link ezcCacheStackMetaData}. The meta data
* must be stored inside the storage, but should not be visible as normal
* cache items to the user.
* @return ezcCacheStackMetaData
public function restoreMetaData()
$metaDataKey = urlencode( $this->properties['location'] ) .
'_'
if ( ( $data =
$this->backend->fetch( $metaDataKey ) ) ===
false )
* Stores the given meta data struct.
* This method stores the given $metaData inside the storage. The data must
* be stored with the same mechanism that the storage itself uses. However,
* it should not be stored as a normal cache item, if possible, to avoid
* accedental user manipulation.
* @param ezcCacheStackMetaData $metaData
public function storeMetaData( ezcCacheStackMetaData $metaData )
$metaDataKey = urlencode( $this->properties['location'] ) .
'_'
* Acquire a lock on the storage.
* This method acquires a lock on the storage. If locked, the storage must
* block all other method calls until the lock is freed again using {@link
* ezcCacheStackMetaDataStorage::unlock()}. Methods that are called within
* the request that successfully acquired the lock must succeed as usual.
$lockKey = urlencode( $this->properties['location'] ) .
'_'
* Release a lock on the storage.
* This method releases the lock of the storage, that has been acquired via
* {@link ezcCacheStackMetaDataStorage::lock()}. After this method has been
* called, blocked method calls (including calls to lock()) can suceed
if ( $this->lock !==
false )
$lockKey = urlencode( $this->properties['location'] ) .
'_'
* Calculates the lifetime remaining for a cache object.
* In case the TTL options is set to true, this method always returns 1.
* @param string $identifier The memcache identifier
* @param bool $dataObject The optional data object for which to calculate the lifetime
* @return int The remaining lifetime in seconds (0 if no time remaining)
protected function calcLifetime( $identifier, $dataObject = false )
$ttl = $this->options->ttl;
$dataObject =
is_object( $dataObject ) ?
$dataObject :
$this->fetchData ( $identifier, true );
if ( is_object( $dataObject ) )
( $lifeTime = ( time() - $dataObject->time ) <
$ttl )
* Registers an identifier to facilitate searching.
* @param string $id ID for the cache item
* @param array $attributes Attributes for the cache item
* @param string $identifier Identifier generated for the cache item
protected function registerIdentifier( $id = null, $attributes = array(), $identifier = null )
$identifier = ( $identifier !== null ) ? $identifier : $this->generateIdentifier( $id, $attributes );
// Makes sure the identifier exists
// Makes sure the id exists
$this->searchRegistry[$location][$id][$identifier] =
new ezcCacheStorageMemoryRegisterStruct( $id, $attributes, $identifier, $location );
* Un-registers a previously registered identifier.
* @param string $id ID for the cache item
* @param array $attributes Attributes for the cache item
* @param string $identifier Identifier generated for the cache item
* @param bool $delayStore Delays the storing of the updated search registry
protected function unRegisterIdentifier( $id = null, $attributes = array(), $identifier = null, $delayStore = false )
$identifier = ( $identifier !== null ) ? $identifier : $this->generateIdentifier( $id, $attributes );
if ( $delayStore ===
false )
* Fetches the search registry from the backend or creates it if empty.
* @param bool $requireFresh To create a new search registry or not
protected function fetchSearchRegistry( $requireFresh = false )
// Makes sure the registry exists
||
$requireFresh ===
true )
* Stores the search registry in the backend.
protected function storeSearchRegistry()
* Generates a string from the $attributes array.
* @param array(string=>string) $attributes Attributes describing the data
* @apichange Was only used to generate "pseudo-regex". Attribute arrays
* are compared directly now.
protected function generateAttrStr( $attributes = array() )
foreach ( $attributes as $key => $val )
$attrStr .= '-' . $key . '=' .$val;
* Checks if the location property is valid.
protected function validateLocation()
* Searches the storage for data defined by ID and/or attributes.
* @param string $id The item ID
* @param array(string=>string) $attributes Attributes describing the data
protected function search( $id = null, $attributes = array() )
// Grabs the identifier registry
// Finds all in case of empty $id and $attributes
foreach ( $idArr as $registryObj )
if ( !is_null( $registryObj->id ) )
$itemArr[] = array( $registryObj->id, $registryObj->attributes, $registryObj->identifier );
// Makes sure we've seen this ID before
foreach ( $this->searchRegistry[$location][$id] as $identifier =>
$dataArr )
if ( $this->fetchData( $identifier ) !==
false )
$itemArr[] = array( $id, $attributes, $identifier );
// Finds cache items that fit our description
foreach ( $arr as $identifier => $registryObj )
if ( count( array_diff_assoc( $attributes, $registryObj->attributes ) ) ===
0 )
$registryObj->attributes,