Drupal PHP Cross Reference Content Management Systems

Source: /includes/cache.inc - 558 lines - 18746 bytes - Summary - Text - Print

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

title

Description

title

Description

title

Description

title

title

Body