summaryrefslogtreecommitdiff
path: root/framework/Data/TAPCCache.php
blob: aba4fac84c897f53cf83060484d04eca42dc1760 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
<?php
/**
 * TAPCCache class file
 *
 * @author Alban Hanry <compte_messagerie@hotmail.com>
 * @link http://www.pradosoft.com/
 * @copyright Copyright &copy; 2005 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @version $Revision: $  $Date: $
 * @package System.Data
 */

/**
 * TAPCCache class
 *
 * TAPCCache implements a cache application module based on {@link http://www.php.net/apc APC}.
 *
 * By definition, cache does not ensure the existence of a value
 * even if it never expires. Cache is not meant to be an persistent storage.
 *
 * To use this module, the APC PHP extension must be loaded.
 *
 * Some usage examples of TAPCCache are as follows,
 * <code>
 * $cache=new TAPCCache;  // TAPCCache may also be loaded as a Prado application module
 * $cache->init(null);
 * $cache->add('object',$object);
 * $object2=$cache->get('object');
 * </code>
 *
 * If loaded, TAPCCache will register itself with {@link TApplication} as the
 * cache module. It can be accessed via {@link TApplication::getCache()}.
 *
 * TAPCCache may be configured in application configuration file as follows
 * <module id="cache" type="System.Data.TAPCCache" Prefix="apc_cache_prefix_key_"/>
 *
 * @author Alban Hanry <compte_messagerie@hotmail.com>
 * @version $Revision: $  $Date: $
 * @package System.Data
 * @since 3.0b
 */
class TAPCCache extends TModule implements ICache
{
   
    const SERIALIZED = "_serialized";
   
   /**
    * @var boolean if the module is initialized
    */
   private $_initialized=false;

   /**
    * @var string a unique prefix used to identify this cache instance from the others
    */
   protected $_prefix=null;

   /**
    * Initializes this module.
    * This method is required by the IModule interface.
    * @param TXmlElement configuration for this module, can be null
    * @throws TConfigurationException if apc extension is not installed or not started, check your php.ini
    */
   public function init($config)
   {
      $application=$this->getApplication();
      if(!$application || $application->getMode()!==TApplication::STATE_PERFORMANCE)
      {
         if(!extension_loaded('apc'))
            throw new TConfigurationException('apccache_extension_required');
      }
      if($application) {
      	if(!$this->_prefix)
         $this->_prefix=$application->getUniqueID();
         $application->setCache($this);
      }
      $this->_initialized=true;
   }

   /**
    * @return string prefix used to cache key
    */
   public function getPrefix()
   {
      return $this->_prefix;
   }

   /**
    * @param string prefix to be used for cache key
    * @throws TInvalidOperationException if the module is already initialized
    */
   public function setPrefix($value)
   {
      if($this->_initialized)
         throw new TInvalidOperationException('apccache_prefix_unchangeable');
      else
         $this->_prefix=$value;
   }

   /**
    * Retrieves a value from cache with a specified key.
    * @return mixed the value stored in cache, false if the value is not in the cache or expired.
    */
   public function get($key)
   {
      $ret=apc_fetch($this->_prefix.$key);
      if((boolean)apc_fetch($this->_prefix.$key.self::SERIALIZED))
        $ret=unserialize($ret);
      return $ret;
   }

   /**
    * Stores a value identified by a key into cache.
    * If the cache already contains such a key, the existing value and
    * expiration time will be replaced with the new ones.
    *
    * @param string the key identifying the value to be cached
    * @param mixed the value to be cached
    * @param integer the expiration time of the value,
    *        0 means never expire,
    * @return boolean true if the value is successfully stored into cache, false otherwise
    */
   public function set($key,$value,$expiry=0)
   {
       if(!is_string($value)) {
           $value=serialize($value);
           apc_store($this->_prefix.$key.self::SERIALIZED,1,$expiry);
       }
      return apc_store($this->_prefix.$key,$value,$expiry);
   }

   /**
    * Stores a value identified by a key into cache if the cache does not contain this key.
    * Nothing will be done if the cache already contains the key.
    * @param string the key identifying the value to be cached
    * @param mixed the value to be cached
    * @param integer the expiration time of the value,
    *        0 means never expire,
    * @return boolean true if the value is successfully stored into cache, false otherwise
    */
   public function add($key,$value,$expiry=0)
   {
      if(!apc_fetch($this->_prefix.$key))
         return $this->set($key,$value,$expiry);
      else return false;
   }

   /**
    * Stores a value identified by a key into cache only if the cache contains this key.
    * The existing value and expiration time will be overwritten with the new ones.
    * @param string the key identifying the value to be cached
    * @param mixed the value to be cached
    * @param integer the expiration time of the value,
    *        0 means never expire,
    * @return boolean true if the value is successfully stored into cache, false otherwise
    */
   public function replace($key,$value,$expiry=0)
   {
      if(apc_fetch($this->_prefix.$key))
      	return $this->set($key,$value,$expiry);
      else return false;
   }

   /**
    * Deletes a value with the specified key from cache
    * @param string the key of the value to be deleted
    * @return boolean if no error happens during deletion
    */
   public function delete($key)
   {
      apc_delete($this->_prefix.$key.self::SERIALIZED);
      return apc_delete($this->_prefix.$key);
   }

   /**
    * Deletes all values from cache.
    */
   public function flush()
   {
      return apc_clear_cache('user');
   }

}

?>