<?php
/**
 * File containing the ezcCacheStack 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
 * under the License.
 *
 * @package Cache
 * @version //autogentag//
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 * @filesource
 */

/**
 * Hierarchical caching class using multiple storages.
 *
 * An instance of this class can be used to achieve so called "hierarchical
 * caching". A cache stack consists of an arbitrary number of cache storages,
 * being sorted from top to bottom. Usually this order reflects the speed of
 * access for the caches: The fastest cache is at the top, the slowest at the
 * bottom. Whenever data is stored in the stack, it is stored in all contained
 * storages. When data is to be restored, the stack will restore it from the
 * highest storage it is found in. Data is removed from a storage, whenever the
 * storage reached a configured number of items, using a {@link
 * ezcCacheStackReplacementStrategy}.
 *
 * To create a cache stack, multiple storages are necessary. The following
 * examples assume that $storage1, $storage2 and $storage3 contain objects that
 * implement the {@link ezcCacheStackableStorage} interface.
 *
 * The slowest cache should be at the very bottom of the stack, so that items
 * don't need to be restored from it that frequently.
 * <code>
 * <?php
 *  $stack = new ezcCacheStack( 'stack_id' );
 *  $stack->pushStorage(
 *      new ezcCacheStackStorageConfiguration(
 *          'filesystem_cache',
 *          $storage1,
 *          1000000,
 *          .5
 *      )
 *  );
 * ?>
 * </code>
 * This operations create a new cache stack and add $storage1 to its very
 * bottom. The first parameter for {@linke ezcCacheStackStorageConfiguration}
 * are a unique ID for the storage inside the stack, which should never change.
 * The second parameter is the storage object itself. Parameter 3 is the
 * maximum number of items the storage might contain. As soon as this limit ist
 * reached, 500000 items will be purged from the cache. The latter number is
 * defined through the fourth parameter, indicating the fraction of the stored
 * item number, that is to be freed. For freeing, first already outdated items
 * will be purged. If this does not last, more items will be freed using the
 * {@link ezcCacheStackReplacementStrategy} used by the stack.
 *
 * The following code adds the other 2 storages to the stack, where $storage2
 * is a memory storage {@link ezcCacheStackMemoryStorage} and $storage3 is a
 * custom storage implementation, that stores objects in the current requests
 * memory.
 * <code>
 * <?php
 *  $stack->pushStorage(
 *      new ezcCacheStackStorageConfiguration(
 *          'apc_storage',
 *          $storage2,
 *          10000,
 *          .8
 *      )
 *  );
 *  $stack->pushStorage(
 *      new ezcCacheStackStorageConfiguration(
 *          'custom_storage',
 *          $storage3,
 *          50,
 *          .3
 *      )
 *  );
 * ?>
 * </code>
 * The second level of the cache build by $storage2. This storage will contain
 * 10000 items maximum and when it runs full, 8000 items will be deleted from
 * it. The top level of the cache is the custom cache storage, that will only
 * contain 50 objects in the currently processed request. If this storage ever
 * runs full, which should not happen within a request, 15 items will be
 * removed from it.
 *
 * Since the top most storage in this example does not implement {@link
 * ezcCacheStackMetaDataStorage}, another storage must be defined to be used
 * for storing meta data about the stack:
 * <code>
 * <?php
 *  $stack->options->metaStorage = $storage2;
 *  $stack->options->replacementStrategy = 'ezcCacheStackLfuReplacementStrategy';
 * ?>
 * </code>
 * $storage2 is defined to store the meta information for the stack. In
 * addition, a different replacement strategy than the default {@link
 * ezcCacheStackLruReplacementStrategy} replacement strategy is defined. LFU
 * removes least frequently used items, while LRU deletes least recently used
 * items from a storage, if it runs full.
 *
 * Using the $bubbleUpOnRestore option you can determine, that data which is
 * restored from a lower storage will be automatically stored in all higher
 * storages again. The problem with this is, that only the attributes that are
 * used for restoring will be assigned to the item in higher storages. In
 * addition, the items will be stored with a fresh TTL. Therefore, this
 * behavior is not recommended.
 *
 * If you want to use a cache stack in combination with {@ezcCacheManager}, you
 * will most likely want to use {@link ezcCacheStackConfigurator}. This allows
 * you to let the stack be configured on the fly, when it is used for the first
 * time in a request.
 *
 * Beware, that whenever you change the structure of your stack or the
 * replacement strategy between 2 requests, you should always perform a
 * complete {@link ezcCacheStack::reset()} on it. Otherwise, your cache data
 * might be seriously broken which will result in undefined behaviour of the
 * stack. Changing the replacement strategy will most possibly result in an
 * {@link ezcCacheInvalidMetaDataException}.
 * 
 * @property ezcCacheStackOptions $options
 *           Options for the cache stack.
 * @property string $location
 *           Location of this stack. Unused.
 * @mainclass
 * @package Cache
 * @version //autogentag//
 */
class ezcCacheStack extends ezcCacheStorage
{
    /**
     * Stack of storages. 
     * 
     * @var array(int=>ezcCacheStackableStorage)
     */
    private $storageStack = array();

    /**
     * Mapping if IDs to storages.
     *
     * Mainly used to validate an ID is not taken twice and a storage is not
     * added twice.
     * 
     * @var array(string=>ezcCacheStackableStorage)
     */
    private $storageIdMap = array();

    /**
     * Creates a new cache stack.
     *
     * Usually you will want to use the {@link ezcCacheManager} to take care of
     * your caches. The $options ({@link ezcCacheStackOptions}) stored in the
     * manager and given here can contain a class reference to an
     * implementation of {@link ezcCacheStackConfigurator} that will be used to
     * initially configure the stack instance directly after construction.
     *
     * To perform manual configuration of the stack the {@link
     * ezcCacheStack::pushStorage()} and {@link ezcCacheStack::popStorage()}
     * methods can be used.
     *
     * The location can be a free form string that identifies the stack
     * uniquely in the {@link ezcCacheManager}. It is currently not used
     * internally in the stack.
     * 
     * @param string $location 
     * @param ezcCacheStackOptions $options 
     */
    public function __construct( $location, ezcCacheStackOptions $options = null )
    {
        if ( $options === null )
        {
            $options = new ezcCacheStackOptions();
        }

        $this->properties['location'] = $location;
        $this->properties['options']  = $options;

        if ( $options->configurator !== null )
        {
            // Configure this instance
            call_user_func(
                array( $options->configurator, 'configure' ),
                $this
            );
        }
    }

    /**
     * Stores data in the cache stack.
     *
     * This method will store the given data across the complete stack. It can
     * afterwards be restored using the {@link ezcCacheStack::restore()} method
     * and be deleted through the {@link ezcCacheStack::delete()} method.
     *
     * The data that can be stored in the cache depends on the configured
     * storages. Usually it is save to store arrays and scalars. However, some
     * caches support objects or do not even support arrays. You need to make
     * sure that the inner caches of the stack *all* support the data you want
     * to store!
     *
     * The $attributes array is optional and can be used to describe the stack
     * further.
     *
     * @param string $id 
     * @param mixed $data 
     * @param array $attributes 
     */
    public function store( $id, $data, $attributes = array() )
    {
        $metaStorage = $this->getMetaDataStorage();
        $metaStorage->lock();
        
        $metaData = $this->getMetaData( $metaStorage );

        foreach( $this->storageStack as $storageConf )
        {
            call_user_func(
                array(
                    $this->properties['options']->replacementStrategy,
                    'store'
                ),
                $storageConf,
                $metaData,
                $id,
                $data,
                $attributes
            );
        }

        $metaStorage->storeMetaData( $metaData );
        $metaStorage->unlock();
    }

    /**
     * Returns the meta data to use.
     *
     * Returns the meta data to use with the configured {@link
     * ezcCacheStackStackReplacementStrategy}.
     * 
     * @param ezcCacheStackMetaDataStorage $metaStorage 
     * @return ezcCacheMetaData
     */
    private function getMetaData( ezcCacheStackMetaDataStorage $metaStorage )
    {
        $metaData = $metaStorage->restoreMetaData();
        
        if ( $metaData === null )
        {
            $metaData = call_user_func(
                array(
                    $this->properties['options']->replacementStrategy,
                    'createMetaData'
                )
            );
        }

        return $metaData;
    }

    /**
     * Restores an item from the stack.
     *
     * This method tries to restore an item from the cache stack and returns
     * the found data, if any. If no data is found, boolean false is returned.
     * Given the ID of an object will restore exactly the desired object. If
     * additional $attributes are given, this may speed up the restore process
     * for some caches. If only attributes are given, the $search parameter
     * makes sense, since it will instruct the inner cach storages to search
     * their content for the given attribute combination and will restore the
     * first item found. However, this process is much slower then restoring
     * with an ID and therefore is not recommended.
     * 
     * @param string $id 
     * @param array $attributes 
     * @param bool $search 
     * @return mixed The restored data or false on failure.
     */
    public function restore( $id, $attributes = array(), $search = false )
    {
        $metaStorage = $this->getMetaDataStorage();
        $metaStorage->lock();

        $metaData = $this->getMetaData( $metaStorage );

        $item = false;
        foreach ( $this->storageStack as $storageConf )
        {
            $item = call_user_func(
                array(
                    $this->properties['options']->replacementStrategy,
                    'restore'
                ),
                $storageConf,
                $metaData,
                $id,
                $attributes,
                $search
            );
            if ( $item !== false )
            {
                if ( $this->properties['options']->bubbleUpOnRestore )
                {
                    $this->bubbleUp( $id, $attributes, $item, $storageConf, $metaData );
                }
                // Found, so end.
                break;
            }
        }

        $metaStorage->storeMetaData( $metaData );
        $metaStorage->unlock();

        return $item;
    }

    /**
     * Bubbles a restored $item up to all storages above $foundStorageConf. 
     * 
     * @param string $id 
     * @param array $attributes 
     * @param mixed $item 
     * @param ezcCacheStackStorageConfiguration $foundStorageConf 
     * @param ezcCacheStackMetaData $metaData
     */
    private function bubbleUp( $id, array $attributes, $item, ezcCacheStackStorageConfiguration $foundStorageConf, ezcCacheStackMetaData $metaData )
    {
        foreach( $this->storageStack as $storageConf )
        {
            if ( $storageConf === $foundStorageConf )
            {
                // This was the storage where we restored
                break;
            }
            call_user_func(
                array(
                    $this->properties['options']->replacementStrategy,
                    'store'
                ),
                $storageConf,
                $metaData,
                $id,
                $item,
                $attributes
            );
        }
    }

    /**
     * Deletes an item from the stack.
     *
     * This method deletes an item from the cache stack. The item will
     * afterwards no more be stored in any of the inner cache storages. Giving
     * the ID of the cache item will delete exactly 1 desired item. Giving an
     * attribute array, describing the desired item in more detail, can speed
     * up the deletion in some caches.
     *
     * Giving null as the ID and just an attribibute array, with the $search
     * attribute in addition, will delete *all* items that comply to the
     * attributes from all storages. This might be much slower than just
     * deleting a single item.
     *
     * Deleting items from a cache stack is not recommended at all. Instead,
     * items should expire on their own or be overwritten with more actual
     * data.
     *
     * The method returns an array containing all deleted item IDs.
     * 
     * @param string $id 
     * @param array $attributes 
     * @param bool $search 
     * @return array(string)
     */
    public function delete( $id = null, $attributes = array(), $search = false )
    {
        $metaStorage = $this->getMetaDataStorage();
        $metaStorage->lock();

        $metaData = $metaStorage->restoreMetaData();

        $deletedIds = array();
        foreach ( $this->storageStack as $storageConf )
        {
            $deletedIds = array_merge(
                $deletedIds,
                call_user_func(
                    array(
                        $this->properties['options']->replacementStrategy,
                        'delete'
                    ),
                    $storageConf,
                    $metaData,
                    $id,
                    $attributes,
                    $search
                )
            );
        }

        $metaStorage->storeMetaData( $metaData );
        $metaStorage->unlock();

        return array_unique( $deletedIds );
    }

    /**
     * Returns the meta data storage to be used.
     *
     * Determines the meta data storage to be used by the stack and returns it.
     *
     * @return ezcCacheStackMetaData
     */
    private function getMetaDataStorage()
    {
        $metaStorage = $this->options->metaStorage;
        if ( $metaStorage === null )
        {
            $metaStorage = reset( $this->storageStack )->storage;
            if ( !( $metaStorage instanceof ezcCacheStackMetaDataStorage ) )
            {
                throw new ezcBaseValueException(
                    'metaStorage',
                    $metaStorage,
                    'ezcCacheStackMetaDataStorage',
                    'top of storage stack'
                );
            }
        }
        return $metaStorage;
    }

    /**
     * Counts how many items are stored, fulfilling certain criteria.
     *
     * This method counts how many data items fulfilling the given criteria are
     * stored overall. Note: The items of all contained storages are counted
     * independantly and summarized.
     * 
     * @param string $id 
     * @param array $attributes 
     * @return int
     */
    public function countDataItems( $id = null, $attributes = array() )
    {
        $sum = 0;
        foreach( $this->storageStack as $storageConf )
        {
            $sum += $storageConf->storage->countDataItems( $id, $attributes );
        }
        return $sum;
    }

    /**
     * Returns the remaining lifetime for the given item ID.
     *
     * This method returns the lifetime in seconds for the item identified by $item
     * and optionally described by $attributes. Definining the $attributes
     * might lead to faster results with some caches.
     *
     * The first internal storage that is found for the data item is chosen to
     * detemine the lifetime. If no storage contains the item or the item is
     * outdated in all found caches, 0 is returned.
     * 
     * @param string $id 
     * @param array $attributes 
     * @return int
     */
    public function getRemainingLifetime( $id, $attributes = array() )
    {
        foreach ( $this->storageStack as $storageConf )
        {
            $lifetime = $storageConf->storage->getRemainingLifetime(
                $id,
                $attributes
            );
            if ( $lifetime > 0 )
            {
                return $lifetime;
            }
        }
        return 0;
    }

    /**
     * Add a storage to the top of the stack.
     *
     * This method is used to add a new storage to the top of the cache. The
     * $storageConf of type {@link ezcCacheStackStorageConfiguration} consists
     * of the actual {@link ezcCacheStackableStorage} and other information.
     *
     * Most importantly, the configuration object contains an ID, which must be
     * unique within the whole storage. The itemLimit setting determines how
     * many items might be stored in the storage at all. freeRate determines
     * which fraction of itemLimit will be freed by the {@link
     * ezcCacheStackStackReplacementStrategy} of the stack, when the storage
     * runs full.
     *
     * @param ezcCacheStackStorageConfiguration $storageConf 
     */
    public function pushStorage( ezcCacheStackStorageConfiguration $storageConf )
    {
        if ( isset( $this->storageIdMap[$storageConf->id] ) )
        {
            throw new ezcCacheStackIdAlreadyUsedException(
                $storageConf->id
            );
        }
        if ( in_array( $storageConf->storage, $this->storageIdMap, true ) )
        {
            throw new ezcCacheStackStorageUsedTwiceException(
                $storageConf->storage
            );
        }
        array_unshift( $this->storageStack, $storageConf );
        $this->storageIdMap[$storageConf->id] = $storageConf->storage;
    }

    /**
     * Removes a storage from the top of the stack.
     *
     * This method can be used to remove the top most {@link
     * ezcCacheStackableStorage} from the stack. This is commonly done to
     * remove caches or to insert new ones into lower positions. In both cases,
     * it is recommended to {@link ezcCacheStack::reset()} the whole cache
     * afterwards to avoid any kind of inconsistency.
     *
     * @return ezcCacheStackStorageConfiguration
     *
     * @throws ezcCacheStackUnderflowException
     *         if called on an empty stack.
     */
    public function popStorage()
    {
        if ( count( $this->storageStack ) === 0 )
        {
            throw new ezcCacheStackUnderflowException();
        }
        $storageConf = array_shift( $this->storageStack );
        unset( $this->storageIdMap[$storageConf->id] );
        return $storageConf;
    }

    /**
     * Returns the number of storages on the stack.
     *
     * Returns the number of storages currently on the stack.
     * 
     * @return int
     */
    public function countStorages()
    {
        return count( $this->storageStack );
    }

    /**
     * Returns all stacked storages.
     *
     * This method returns the whole stack of {@link ezcCacheStackableStorage}
     * as an array. This maybe useful to adjust options of the storages after
     * they have been added to the stack. However, it is not recommended to
     * perform any drastical changes to the configurations. Performing manual
     * stores, restores and deletes on the storages is *highly discouraged*,
     * since it may lead to irrepairable inconsistencies of the stack.
     * 
     * @return array(ezcCacheStackableStorage)
     */
    public function getStorages()
    {
        return $this->storageStack;
    }

    /**
     * Resets the complete stack.
     *
     * This method is used to reset the complete stack of storages. It will
     * reset all storages, using {@link ezcCacheStackableStorage::reset()}, and
     * therefore purge the complete content of the stack. In addition, it will
     * kill the complete meta data.
     *
     * The stack is in a consistent, but empty, state afterwards.
     * 
     * @return void
     */
    public function reset()
    {
        foreach ( $this->storageStack as $storageConf )
        {
            $storageConf->storage->reset();
        }
    }

    /**
     * Validates the $location parameter of the constructor.
     *
     * Returns true, since $location is not necessary for this storage.
     * 
     * @return bool
     */
    protected function validateLocation()
    {
        // Does not utilize $location
        return true;
    }

    /**
     * Sets the options for this stack instance.
     *
     * Overwrites the parent implementation to only allow instances of {@link
     * ezcCacheStackOptions}.
     * 
     * @param ezcCacheStackOptions $options 
     *
     * @apichange Use $stack->options instead.
     */
    public function setOptions( $options )
    {
        // Overloading
        $this->options = $options;
    }
    
    /**
     * Property write access.
     * 
     * @param string $propertyName Name of the property.
     * @param mixed $propertyValue  The value for the property.
     *
     * @throws ezcBaseValueException 
     *         If the value for the property options is not an instance of 
     *         ezcCacheStackOptions. 
     * @ignore
     */
    public function __set( $propertyName, $propertyValue )
    {
        switch ( $propertyName ) 
        {
            case 'options':
                if ( !( $propertyValue instanceof ezcCacheStackOptions ) )
                {
                    throw new ezcBaseValueException( $propertyName, $propertyValue, 'ezcCacheStackOptions' );
                }
                break;
            default:
                parent::__set( $propertyName, $propertyValue );
                return;
        }
        $this->properties[$propertyName] = $propertyValue;
    }
}

?>
