]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/SugarCache/SugarCacheAbstract.php
Release 6.2.0
[Github/sugarcrm.git] / include / SugarCache / SugarCacheAbstract.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37
38 abstract class SugarCacheAbstract
39 {
40     /**
41      * @var set to false if you don't want to use the local store, true by default.
42      */
43     public $useLocalStore = true;
44     
45     /**
46      * @var timeout in seconds used for cache item expiration
47      */
48     protected $_expireTimeout = 300;
49     
50     /**
51      * @var prefix to use for all cache key entries
52      */
53     protected $_keyPrefix = 'sugarcrm_';
54     
55     /**
56      * @var stores locally any cached items so we don't have to hit the external cache as much
57      */
58     protected $_localStore = array();
59     
60     /**
61      * @var records the number of get requests made against the cache
62      */
63     protected $_cacheRequests = 0;
64     
65     /**
66      * @var records the number of hits made against the cache that have been resolved without hitting the
67      * external cache
68      */
69     protected $_cacheLocalHits = 0;
70     
71     /**
72      * @var records the number of hits made against the cache that are resolved using the external cache
73      */
74     protected $_cacheExternalHits = 0;
75     
76     /**
77      * @var records the number of get requests that aren't in the cache
78      */
79     protected $_cacheMisses = 0;
80     
81     /**
82      * @var indicates the priority level for using this cache; the lower number indicates the highest
83      * priority ( 1 would be the highest priority, but we should never ship a backend with this number
84      * so we don't bump out custom backends. ) Shipping backends use priorities in the range of 900-999.
85      */
86     protected $_priority = 899;
87     
88     /**
89      * Constructor
90      */
91     public function __construct()
92     {
93         if ( isset($GLOBALS['sugar_config']['cache_expire_timeout']) )
94             $this->_expireTimeout = $GLOBALS['sugar_config']['cache_expire_timeout'];
95         if ( isset($GLOBALS['sugar_config']['unique_key']) )
96             $this->_keyPrefix = $GLOBALS['sugar_config']['unique_key'];
97     }
98     
99     /**
100      * Destructor
101      */
102     public function __destruct()
103     {
104     }
105     
106     /**
107      * PHP's magic __get() method, used here for getting the current value from the cache.
108      *
109      * @param  string $key
110      * @return mixed
111      */
112     public function __get(
113         $key
114         )
115     {
116         if ( SugarCache::$isCacheReset )
117             return;
118         
119         $this->_cacheRequests++;
120         if ( !$this->useLocalStore || !isset($this->_localStore[$key]) ) {
121             $this->_localStore[$key] = $this->_getExternal($this->_keyPrefix.$key);
122             if ( isset($this->_localStore[$key]) ) {
123                 $this->_cacheExternalHits++;
124             }
125             else {
126                 $this->_cacheMisses++;
127             }
128         }
129         elseif ( isset($this->_localStore[$key]) ) {
130             $this->_cacheLocalHits++;
131         }
132         
133         if ( isset($this->_localStore[$key]) ) {
134             return $this->_localStore[$key];
135         }
136         
137         return null;
138     }
139     
140     /**
141      * PHP's magic __set() method, used here for setting a value for a key in the cache.
142      *
143      * @param  string $key
144      * @return mixed
145      */
146     public function __set(
147         $key,
148         $value
149         )
150     {
151         if ( is_null($value) ) {
152             $value = SugarCache::EXTERNAL_CACHE_NULL_VALUE;
153         }
154         
155         if ( $this->useLocalStore ) {
156             $this->_localStore[$key] = $value;
157         }
158         $this->_setExternal($this->_keyPrefix.$key,$value);
159     }
160     
161     /**
162      * PHP's magic __isset() method, used here for checking for a key in the cache.
163      *
164      * @param  string $key
165      * @return mixed
166      */
167     public function __isset(
168         $key
169         )
170     {
171         return !is_null($this->__get($key));
172     }
173     
174     /**
175      * PHP's magic __unset() method, used here for clearing a key in the cache.
176      *
177      * @param  string $key
178      * @return mixed
179      */
180     public function __unset(
181         $key
182         )
183     {
184         unset($this->_localStore[$key]);
185         $this->_clearExternal($this->_keyPrefix.$key);
186     }
187     
188     /**
189      * Reset the cache for this request
190      */
191     public function reset()
192     {
193         $this->_localStore = array();
194         SugarCache::$isCacheReset = true;
195     }
196     
197     /**
198      * Reset the cache fully
199      */
200     public function resetFull()
201     {
202         $this->reset();
203         $this->_resetExternal();
204     }
205     
206     /**
207      * Flush the contents of the cache
208      */
209     public function flush()
210     {
211         $this->_localStore = array();
212         $this->_resetExternal();
213     }
214     
215     /**
216      * Returns the number of cache hits made
217      *
218      * @return array assocative array with each key have the value
219      */
220     public function getCacheStats()
221     {
222         return array(
223             'requests'     => $this->_cacheRequests,
224             'externalHits' => $this->_cacheExternalHits,
225             'localHits'    => $this->_cacheLocalHits,
226             'misses'       => $this->_cacheMisses,
227             );
228     }
229     
230     /**
231      * Returns what backend is used for caching, uses normalized class name for lookup
232      *
233      * @return string
234      */
235     public function __toString()
236     {
237         return strtolower(str_replace('SugarCache','',get_class($this)));
238     }
239     
240     /**
241      * Hook for the child implementations of the individual backends to provide thier own logic for
242      * setting a value from cache
243      *
244      * @param string $key
245      * @param mixed  $value
246      */
247     abstract protected function _setExternal(
248         $key,
249         $value
250         );
251     
252     /**
253      * Hook for the child implementations of the individual backends to provide thier own logic for
254      * getting a value from cache
255      *
256      * @param  string $key
257      * @return mixed  $value, returns null if the key is not in the cache
258      */
259     abstract protected function _getExternal(
260         $key
261         );
262     
263     /**
264      * Hook for the child implementations of the individual backends to provide thier own logic for
265      * clearing a value out of thier cache
266      *
267      * @param string $key
268      */
269     abstract protected function _clearExternal(
270         $key
271         );
272     
273     /**
274      * Hook for the child implementations of the individual backends to provide thier own logic for
275      * clearing thier cache out fully
276      */
277     abstract protected function _resetExternal();
278     
279     /**
280      * Hook for testing if the backend should be used or not. Typically we'll extend this for backend specific
281      * checks as well.
282      *
283      * @return boolean true if we can use the backend, false if not
284      */
285     public function useBackend()
286     {
287         if ( !empty($GLOBALS['sugar_config']['external_cache_disabled']) 
288                 && $GLOBALS['sugar_config']['external_cache_disabled'] == true ) {
289             return false;
290         }
291         
292         if (defined('SUGARCRM_IS_INSTALLING')) {
293             return false;
294         }
295         
296         if ( isset($GLOBALS['sugar_config']['external_cache_force_backend'])
297                 && ( $GLOBALS['sugar_config']['external_cache_force_backend'] != (string) $this ) ) {
298             return false;
299         }
300         
301         return true;
302     }
303     
304     /**
305      * Returns the priority level for this backend
306      *
307      * @see self::$_priority
308      *
309      * @return int
310      */
311     public function getPriority()
312     {
313         return $this->_priority;
314     }
315 }