/[drupal]/drupal/includes/cache.inc
ViewVC logotype

Contents of /drupal/includes/cache.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.40 - (show annotations) (download) (as text)
Sun Sep 13 17:49:51 2009 UTC (2 months, 1 week ago) by dries
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-10, DRUPAL-7-0-UNSTABLE-9
Changes since 1.39: +37 -1 lines
File MIME type: text/x-php
- Patch #575360 by dropcube: added API function to check if a cache bin is empty.
1 <?php
2 // $Id: cache.inc,v 1.39 2009/09/01 20:43:21 webchick Exp $
3
4 /**
5 * Get the cache object for a cache bin.
6 *
7 * By default, this returns an instance of the DrupalDatabaseCache class.
8 * Classes implementing DrupalCacheInterface can register themselves both as a
9 * default implementation and for specific bins.
10 *
11 * @see DrupalCacheInterface
12 *
13 * @param $bin
14 * The cache bin for which the cache object should be returned.
15 */
16 function _cache_get_object($bin) {
17 // We do not use drupal_static() here because we do not want to change the
18 // storage of a cache bin mid-request.
19 static $cache_objects, $default_class;
20 if (!isset($cache_objects[$bin])) {
21 $class = variable_get('cache_class_' . $bin);
22 if (!isset($class)) {
23 $class = variable_get('cache_default_class', 'DrupalDatabaseCache');
24 }
25 $cache_objects[$bin] = new $class($bin);
26 }
27 return $cache_objects[$bin];
28 }
29
30 /**
31 * Return data from the persistent cache. Data may be stored as either plain
32 * text or as serialized data. cache_get will automatically return
33 * unserialized objects and arrays.
34 *
35 * @param $cid
36 * The cache ID of the data to retrieve.
37 * @param $bin
38 * The cache bin to store the data in. Valid core values are 'cache_block',
39 * 'cache_field', 'cache_filter', 'cache_form', 'cache_menu', 'cache_page',
40 * 'cache_path', 'cache_registry', 'cache_update' or 'cache' for the default
41 * cache.
42 * @return The cache or FALSE on failure.
43 */
44 function cache_get($cid, $bin = 'cache') {
45 return _cache_get_object($bin)->get($cid);
46 }
47
48 /**
49 * Return data from the persistent cache when given an array of cache IDs.
50 *
51 * @param $cids
52 * An array of cache IDs for the data to retrieve. This is passed by
53 * reference, and will have the IDs successfully returned from cache removed.
54 * @param $bin
55 * The cache bin where the data is stored.
56 * @return
57 * An array of the items successfully returned from cache indexed by cid.
58 */
59 function cache_get_multiple(array &$cids, $bin = 'cache') {
60 return _cache_get_object($bin)->getMultiple($cids);
61 }
62
63 /**
64 * Store data in the persistent cache.
65 *
66 * The persistent cache is split up into several cache bins. In the default
67 * cache implementation, each cache bin corresponds to a database table by the
68 * same name. Other implementations might want to store several bins in data
69 * structures that get flushed together. While it is not a problem for most
70 * cache bins if the entries in them are flushed before their expire time, some
71 * might break functionality or are extremely expensive to recalculate. These
72 * will be marked with a (*). The other bins expired automatically by core.
73 * Contributed modules can add additional bins and get them expired
74 * automatically by implementing hook_flush_caches().
75 *
76 * - cache: Generic cache storage bin (used for variables, theme registry,
77 * locale date, list of simpletest tests etc).
78 *
79 * - cache_block: Stores the content of various blocks.
80 *
81 * - cache field: Stores the field data belonging to a given object.
82 *
83 * - cache_filter: Stores filtered pieces of content.
84 *
85 * - cache_form(*): Stores multistep forms. Flushing this bin means that some
86 * forms displayed to users lose their state and the data already submitted
87 * to them.
88 *
89 * - cache_menu: Stores the structure of visible navigation menus per page.
90 *
91 * - cache_page: Stores generated pages for anonymous users. It is flushed
92 * very often, whenever a page changes, at least for every ode and comment
93 * submission. This is the only bin affected by the page cache setting on
94 * the administrator panel.
95 *
96 * - cache path: Stores the system paths that have an alias.
97 *
98 * - cache update(*): Stores available releases. The update server (for
99 * example, drupal.org) needs to produce the relevant XML for every project
100 * installed on the current site. As this is different for (almost) every
101 * site, it's very expensive to recalculate for the update server.
102 *
103 * The reasons for having several bins are as follows:
104 *
105 * - smaller bins mean smaller database tables and allow for faster selects and
106 * inserts
107 * - we try to put fast changing cache items and rather static ones into different
108 * bins. The effect is that only the fast changing bins will need a lot of
109 * writes to disk. The more static bins will also be better cacheable with
110 * MySQL's query cache.
111 *
112 * @param $cid
113 * The cache ID of the data to store.
114 * @param $data
115 * The data to store in the cache. Complex data types will be automatically
116 * serialized before insertion.
117 * Strings will be stored as plain text and not serialized.
118 * @param $bin
119 * The cache bin to store the data in. Valid core values are 'cache_block',
120 * 'cache_field', 'cache_filter', 'cache_form', 'cache_menu', 'cache_page',
121 * 'cache_path', 'cache_registry', 'cache_update' or 'cache' for the default
122 * cache.
123 * @param $expire
124 * One of the following values:
125 * - CACHE_PERMANENT: Indicates that the item should never be removed unless
126 * explicitly told to using cache_clear_all() with a cache ID.
127 * - CACHE_TEMPORARY: Indicates that the item should be removed at the next
128 * general cache wipe.
129 * - A Unix timestamp: Indicates that the item should be kept at least until
130 * the given time, after which it behaves like CACHE_TEMPORARY.
131 * @param $headers
132 * A string containing HTTP header information for cached pages.
133 */
134 function cache_set($cid, $data, $bin = 'cache', $expire = CACHE_PERMANENT, array $headers = NULL) {
135 return _cache_get_object($bin)->set($cid, $data, $expire, $headers);
136 }
137
138 /**
139 * Expire data from the cache.
140 *
141 * If called without arguments, expirable entries will be cleared from the
142 * cache_page and cache_block bins.
143 *
144 * @param $cid
145 * If set, the cache ID to delete. Otherwise, all cache entries that can
146 * expire are deleted.
147 *
148 * @param $bin
149 * If set, the bin $bin to delete from. Mandatory
150 * argument if $cid is set.
151 *
152 * @param $wildcard
153 * If $wildcard is TRUE, cache IDs starting with $cid are deleted in
154 * addition to the exact cache ID specified by $cid. If $wildcard is
155 * TRUE and $cid is '*' then the entire table $table is emptied.
156 */
157 function cache_clear_all($cid = NULL, $bin = NULL, $wildcard = FALSE) {
158 if (!isset($cid) && !isset($bin)) {
159 // Clear the block cache first, so stale data will
160 // not end up in the page cache.
161 if (module_exists('block')) {
162 cache_clear_all(NULL, 'cache_block');
163 }
164 cache_clear_all(NULL, 'cache_page');
165 return;
166 }
167 return _cache_get_object($bin)->clear($cid, $wildcard);
168 }
169
170 /**
171 * Check if a cache bin is empty.
172 *
173 * A cache bin is considered empty if it does not contain any valid data for any
174 * cache ID.
175 *
176 * @param $bin
177 * The cache bin to check.
178 * @return
179 * TRUE if the cache bin specified is empty.
180 */
181 function cache_is_empty($bin) {
182 return _cache_get_object($bin)->isEmpty();
183 }
184
185 /**
186 * Interface for cache implementations.
187 *
188 * All cache implementations have to implement this interface. DrupalDatabaseCache
189 * provides the default implementation, which can be consulted as an example.
190 *
191 * To make Drupal use your implementation for a certain cache bin, you have to
192 * set a variable with the name of the cache bin as its key and the name of your
193 * class as its value. For example, if your implementation of DrupalCacheInterface
194 * was called MyCustomCache, the following line would make Drupal use it for the
195 * 'cache_page' bin:
196 * @code
197 * variable_set('cache_page', 'MyCustomCache');
198 * @endcode
199 *
200 * Additionally, you can register your cache implementation to be used by default
201 * for all cache bins by setting the variable 'cache_default_class' to the name
202 * of your implementation of the DrupalCacheInterface, e.g.
203 * @code
204 * variable_set('cache_default_class', 'MyCustomCache');
205 * @endcode
206 *
207 * @see _cache_get_object()
208 * @see DrupalDatabaseCache
209 */
210 interface DrupalCacheInterface {
211 /**
212 * Constructor.
213 *
214 * @param $bin
215 * The cache bin for which the object is created.
216 */
217 function __construct($bin);
218
219 /**
220 * Return data from the persistent cache. Data may be stored as either plain
221 * text or as serialized data. cache_get will automatically return
222 * unserialized objects and arrays.
223 *
224 * @param $cid
225 * The cache ID of the data to retrieve.
226 * @return The cache or FALSE on failure.
227 */
228 function get($cid);
229
230 /**
231 * Return data from the persistent cache when given an array of cache IDs.
232 *
233 * @param $cids
234 * An array of cache IDs for the data to retrieve. This is passed by
235 * reference, and will have the IDs successfully returned from cache
236 * removed.
237 * @return
238 * An array of the items successfully returned from cache indexed by cid.
239 */
240 function getMultiple(&$cids);
241
242 /**
243 * Store data in the persistent cache.
244 *
245 * @param $cid
246 * The cache ID of the data to store.
247 * @param $data
248 * The data to store in the cache. Complex data types will be automatically
249 * serialized before insertion.
250 * Strings will be stored as plain text and not serialized.
251 * @param $expire
252 * One of the following values:
253 * - CACHE_PERMANENT: Indicates that the item should never be removed unless
254 * explicitly told to using cache_clear_all() with a cache ID.
255 * - CACHE_TEMPORARY: Indicates that the item should be removed at the next
256 * general cache wipe.
257 * - A Unix timestamp: Indicates that the item should be kept at least until
258 * the given time, after which it behaves like CACHE_TEMPORARY.
259 * @param $headers
260 * A string containing HTTP header information for cached pages.
261 */
262 function set($cid, $data, $expire = CACHE_PERMANENT, array $headers = NULL);
263
264
265 /**
266 * Expire data from the cache. If called without arguments, expirable
267 * entries will be cleared from the cache_page and cache_block bins.
268 *
269 * @param $cid
270 * If set, the cache ID to delete. Otherwise, all cache entries that can
271 * expire are deleted.
272 * @param $wildcard
273 * If set to TRUE, the $cid is treated as a substring
274 * to match rather than a complete ID. The match is a right hand
275 * match. If '*' is given as $cid, the bin $bin will be emptied.
276 */
277 function clear($cid = NULL, $wildcard = FALSE);
278
279 /**
280 * Check if a cache bin is empty.
281 *
282 * A cache bin is considered empty if it does not contain any valid data for
283 * any cache ID.
284 *
285 * @return
286 * TRUE if the cache bin specified is empty.
287 */
288 function isEmpty();
289 }
290
291 /**
292 * Default cache implementation.
293 *
294 * This is Drupal's default cache implementation. It uses the database to store
295 * cached data. Each cache bin corresponds to a database table by the same name.
296 */
297 class DrupalDatabaseCache implements DrupalCacheInterface {
298 protected $bin;
299
300 function __construct($bin) {
301 $this->bin = $bin;
302 }
303
304 function get($cid) {
305 // Garbage collection necessary when enforcing a minimum cache lifetime.
306 $this->garbageCollection($this->bin);
307 $cache = db_query("SELECT data, created, headers, expire, serialized FROM {" . $this->bin . "} WHERE cid = :cid", array(':cid' => $cid))->fetchObject();
308
309 return $this->prepareItem($cache);
310 }
311
312 function getMultiple(&$cids) {
313 // Garbage collection necessary when enforcing a minimum cache lifetime.
314 $this->garbageCollection($this->bin);
315 $query = db_select($this->bin);
316 $query->fields($this->bin, array('cid', 'data', 'created', 'headers', 'expire', 'serialized'));
317 $query->condition($this->bin . '.cid', $cids, 'IN');
318 $result = $query->execute();
319 $cache = array();
320 foreach ($result as $item) {
321 $item = $this->prepareItem($item);
322 if ($item) {
323 $cache[$item->cid] = $item;
324 }
325 }
326 $cids = array_diff($cids, array_keys($cache));
327 return $cache;
328 }
329
330 /**
331 * Garbage collection for get() and getMultiple().
332 *
333 * @param $bin
334 * The bin being requested.
335 */
336 protected function garbageCollection() {
337 global $user;
338
339 // Garbage collection necessary when enforcing a minimum cache lifetime.
340 $cache_flush = variable_get('cache_flush_' . $this->bin, 0);
341 if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= REQUEST_TIME)) {
342 // Reset the variable immediately to prevent a meltdown in heavy load situations.
343 variable_set('cache_flush_' . $this->bin, 0);
344 // Time to flush old cache data
345 db_delete($this->bin)
346 ->condition('expire', CACHE_PERMANENT, '<>')
347 ->condition('expire', $cache_flush, '<=')
348 ->execute();
349 }
350 }
351
352 /**
353 * Prepare a cached item.
354 *
355 * Checks that items are either permanent or did not expire, and unserializes
356 * data as appropriate.
357 *
358 * @param $cache
359 * An item loaded from cache_get() or cache_get_multiple().
360 * @return
361 * The item with data unserialized as appropriate or FALSE if there is no
362 * valid item to load.
363 */
364 protected function prepareItem($cache) {
365 global $user;
366
367 if (!isset($cache->data)) {
368 return FALSE;
369 }
370 // If the data is permanent or we are not enforcing a minimum cache lifetime
371 // always return the cached data.
372 if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime', 0)) {
373 if ($cache->serialized) {
374 $cache->data = unserialize($cache->data);
375 }
376 }
377 // If enforcing a minimum cache lifetime, validate that the data is
378 // currently valid for this user before we return it by making sure the cache
379 // entry was created before the timestamp in the current session's cache
380 // timer. The cache variable is loaded into the $user object by _drupal_session_read()
381 // in session.inc. If the data is permanent or we're not enforcing a minimum
382 // cache lifetime always return the cached data.
383 if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && $user->cache > $cache->created) {
384 // This cache data is too old and thus not valid for us, ignore it.
385 return FALSE;
386 }
387
388 if (isset($cache->headers)) {
389 $cache->headers = unserialize($cache->headers);
390 }
391
392 return $cache;
393 }
394
395 function set($cid, $data, $expire = CACHE_PERMANENT, array $headers = NULL) {
396 $fields = array(
397 'serialized' => 0,
398 'created' => REQUEST_TIME,
399 'expire' => $expire,
400 'headers' => isset($headers) ? serialize($headers) : NULL,
401 );
402 if (!is_string($data)) {
403 $fields['data'] = serialize($data);
404 $fields['serialized'] = 1;
405 }
406 else {
407 $fields['data'] = $data;
408 $fields['serialized'] = 0;
409 }
410
411 db_merge($this->bin)
412 ->key(array('cid' => $cid))
413 ->fields($fields)
414 ->execute();
415 }
416
417 function clear($cid = NULL, $wildcard = FALSE) {
418 global $user;
419
420 if (empty($cid)) {
421 if (variable_get('cache_lifetime', 0)) {
422 // We store the time in the current user's $user->cache variable which
423 // will be saved into the sessions bin by _drupal_session_write(). We then
424 // simulate that the cache was flushed for this user by not returning
425 // cached data that was cached before the timestamp.
426 $user->cache = REQUEST_TIME;
427
428 $cache_flush = variable_get('cache_flush_' . $this->bin, 0);
429 if ($cache_flush == 0) {
430 // This is the first request to clear the cache, start a timer.
431 variable_set('cache_flush_' . $this->bin, REQUEST_TIME);
432 }
433 elseif (REQUEST_TIME > ($cache_flush + variable_get('cache_lifetime', 0))) {
434 // Clear the cache for everyone, cache_lifetime seconds have
435 // passed since the first request to clear the cache.
436 db_delete($this->bin)
437 ->condition('expire', CACHE_PERMANENT, '<>')
438 ->condition('expire', REQUEST_TIME, '<')
439 ->execute();
440 variable_set('cache_flush_' . $this->bin, 0);
441 }
442 }
443 else {
444 // No minimum cache lifetime, flush all temporary cache entries now.
445 db_delete($this->bin)
446 ->condition('expire', CACHE_PERMANENT, '<>')
447 ->condition('expire', REQUEST_TIME, '<')
448 ->execute();
449 }
450 }
451 else {
452 if ($wildcard) {
453 if ($cid == '*') {
454 db_truncate($this->bin)->execute();
455 }
456 else {
457 db_delete($this->bin)
458 ->condition('cid', $cid . '%', 'LIKE')
459 ->execute();
460 }
461 }
462 elseif (is_array($cid)) {
463 // Delete in chunks when a large array is passed.
464 do {
465 db_delete($this->bin)
466 ->condition('cid', array_splice($cid, 0, 1000), 'IN')
467 ->execute();
468 }
469 while (count($cid));
470 }
471 else {
472 db_delete($this->bin)
473 ->condition('cid', $cid)
474 ->execute();
475 }
476 }
477 }
478
479 function isEmpty() {
480 $this->garbageCollection();
481 $query = db_select($this->bin);
482 $query->addExpression('1');
483 $result = $query->range(0, 1)
484 ->execute()
485 ->fetchField();
486 return empty($result);
487 }
488 }

  ViewVC Help
Powered by ViewVC 1.1.2