Commit 32998560 authored by David's avatar David
Browse files

??

parent cafae14f
Loading
Loading
Loading
Loading

ChainedFastBackend.inc

deleted100644 → 0
+0 −239
Original line number Diff line number Diff line
<?php

/**
 * Defines a backend with a fast and a consistent backend chain.
 *
 * In order to mitigate a network roundtrip for each cache get operation, this
 * cache allows a fast backend to be put in front of a slow(er) backend.
 * Typically the fast backend will be something like APCu, and be bound to a
 * single web node, and will not require a network round trip to fetch a cache
 * item. The fast backend will also typically be inconsistent (will only see
 * changes from one web node). The slower backend will be something like Mysql,
 * Memcached or Redis, and will be used by all web nodes, thus making it
 * consistent, but also require a network round trip for each cache get.
 *
 * In addition to being useful for sites running on multiple web nodes, this
 * backend can also be useful for sites running on a single web node where the
 * fast backend (e.g., APCu) isn't shareable between the web and CLI processes.
 * Single-node configurations that don't have that limitation can just use the
 * fast cache backend directly.
 *
 * We always use the fast backend when reading (get()) entries from cache, but
 * check whether they were created before the last write (set()) to this
 * (chained) cache backend. Those cache entries that were created before the
 * last write are discarded, but we use their cache IDs to then read them from
 * the consistent (slower) cache backend instead; at the same time we update
 * the fast cache backend so that the next read will hit the faster backend
 * again. Hence we can guarantee that the cache entries we return are all
 * up-to-date, and maximally exploit the faster cache backend. This cache
 * backend uses and maintains a "last write timestamp" to determine which cache
 * entries should be discarded.
 *
 * Because this backend will mark all the cache entries in a bin as out-dated
 * for each write to a bin, it is best suited to bins with fewer changes.
 *
 * @ingroup cache
 */
class ChainedFastBackend implements DrupalCacheInterface {

  /**
   * Cache key prefix for the bin-specific entry to track the last write.
   */
  const LAST_WRITE_TIMESTAMP_PREFIX = 'last_write_timestamp_';

  /**
   * @var string
   */
  protected $bin;

  /**
   * The consistent cache backend.
   *
   * @var DrupalCacheInterface
   */
  protected $consistentBackend;

  /**
   * The fast cache backend.
   *
   * @var DrupalCacheInterface
   */
  protected $fastBackend;

  /**
   * The time at which the last write to this cache bin happened.
   *
   * @var float
   */
  protected $lastWriteTimestamp;

  /**
   * Constructs a ChainedFastBackend object.
   *
   * @param DrupalCacheInterface $consistent_backend
   *   The consistent cache backend.
   * @param DrupalCacheInterface $fast_backend
   *   The fast cache backend.
   * @param string $bin
   *   The cache bin for which the object is created.
   */
  public function __construct($bin) {
    global $conf;
    $this->consistentBackend = new $conf['consistentBackend']($bin);
    $this->fastBackend = new $conf['fastBackend']($bin);
    $this->bin = 'cache_' . $bin;
    $this->lastWriteTimestamp = NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function get($cid) {
    $cids = array($cid);
    $cache = $this->getMultiple($cids);
    return reset($cache);
  }

  /**
   * {@inheritdoc}
   */
  public function getMultiple(&$cids) {
    $cids_copy = $cids;
    $cache = array();

    // If we can determine the time at which the last write to the consistent
    // backend occurred (we might not be able to if it has been recently
    // flushed/restarted), then we can use that to validate items from the fast
    // backend, so try to get those first. Otherwise, we can't assume that
    // anything in the fast backend is valid, so don't even bother fetching
    // from there.
    $last_write_timestamp = $this->getLastWriteTimestamp();
    if ($last_write_timestamp) {
      // Items in the fast backend might be invalid based on their timestamp,
      // but we can't check the timestamp prior to getting the item, which
      // includes unserializing it. However, unserializing an invalid item can
      // throw an exception. For example, a __wakeup() implementation that
      // receives object properties containing references to code or data that
      // no longer exists in the application's current state.
      //
      // Unserializing invalid data, whether it throws an exception or not, is
      // a waste of time, but we only incur it while a cache invalidation has
      // not yet finished propagating to all the fast backend instances.
      //
      // Most cache backend implementations should not wrap their internal
      // get() implementations with a try/catch, because they have no reason to
      // assume that their data is invalid, and doing so would mask
      // unserialization errors of valid data. We do so here, only because the
      // fast backend is non-authoritative, and after discarding its
      // exceptions, we proceed to check the consistent (authoritative) backend
      // and allow exceptions from that to bubble up.
      try {
        $items = $this->fastBackend->getMultiple($cids);
      }
      catch (\Exception $e) {
        $cids = $cids_copy;
        $items = array();
      }

      // Even if items were successfully fetched from the fast backend, they
      // are potentially invalid if older than the last time the bin was
      // written to in the consistent backend, so only keep ones that aren't.
      foreach ($items as $item) {
        if ($item->created < $last_write_timestamp) {
          $cids[array_search($item->cid, $cids_copy)] = $item->cid;
        }
        else {
          $cache[$item->cid] = $item;
        }
      }
    }

    // If there were any cache entries that were not available in the fast
    // backend, retrieve them from the consistent backend and store them in the
    // fast one.
    if ($cids) {
      foreach ($this->consistentBackend->getMultiple($cids) as $item) {
        $cache[$item->cid] = $item;
        $this->fastBackend->set($item->cid, $item->data, $item->expire);
      }
    }

    return $cache;
  }

  /**
   * {@inheritdoc}
   */
  public function set($cid, $data, $expire = Cache::PERMANENT) {
    // Only mark as outdated if the item alrady exists in the consisten
    // backend cache.
    if ($this->fastBackend->get($cid) || $this->consistentBackend->get($cid)) {
      $this->markAsOutdated();
    }
    $this->consistentBackend->set($cid, $data, $expire);
    $this->fastBackend->set($cid, $data, $expire);
  }

  /**
   * {@inheritdoc}
   */
  public function setMultiple(array $items) {
    $this->consistentBackend->setMultiple($items);
    $this->markAsOutdated();
    $this->fastBackend->setMultiple($items);
  }

  /**
   * {@inheritdoc}
   */
  public function clear($cid = NULL, $wildcard = FALSE) {
    $this->consistentBackend->clear($cid, $wildcard);
    $this->markAsOutdated();
    $this->fastBackend->clear($cid, $wildcard);
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    return $this->consistentBackend->isEmpty();
  }

  /**
   * {@inheritdoc}
   */
  public function garbageCollection() {
    $this->consistentBackend->garbageCollection();
    $this->fastBackend->garbageCollection();
  }

  /**
   * Gets the last write timestamp.
   */
  protected function getLastWriteTimestamp() {
    if ($this->lastWriteTimestamp === NULL) {
      $cache = $this->consistentBackend->get(self::LAST_WRITE_TIMESTAMP_PREFIX . $this->bin);
      $this->lastWriteTimestamp = $cache ? $cache->data : 0;
    }
    return $this->lastWriteTimestamp;
  }

  /**
   * Marks the fast cache bin as outdated because of a write.
   */
  protected function markAsOutdated() {
    // Clocks on a single server can drift. Multiple servers may have slightly
    // differing opinions about the current time. Given that, do not assume
    // 'now' on this server is always later than our stored timestamp.
    // Also add 1 millisecond, to ensure that caches written earlier in the same
    // millisecond are invalidated. It is possible that caches will be later in
    // the same millisecond and are then incorrectly invalidated, but that only
    // costs one additional roundtrip to the persistent cache.
    $now = round(microtime(TRUE) + .001, 3);
    if ($now > $this->getLastWriteTimestamp()) {
      $this->lastWriteTimestamp = $now;
      $this->consistentBackend->set(self::LAST_WRITE_TIMESTAMP_PREFIX . $this->bin, $this->lastWriteTimestamp);
    }
  }

}

README.txt

deleted100644 → 0
+0 −311
Original line number Diff line number Diff line
/*****************
 * Using Wincache Extension to speed up your site
 ****************/
 This module provides a cache backend for Drupal 7, and a module that
 shows some statistics about wincache backend usage. There is NO need
 to enable the module in order to use the cache backend, this is manually
 setup in settings.php. Correctly setting up Wincache takes some time, but
 it is worth the effort.

 This README file also contains additional instructions on how to get the
 most of wincache, that can be used as (each one of these requires individual
 configuration).

 - 1. Cache Backend (AKA "User Cache")
 - 2. File system operation storage accelerator (file system function rerouting)
 - 3. File System Cache + Resolve Path Cache
 - 4. Opcode Cache (not needed anymore with PHP >= 5)
 - 5. Session Storage Handler

 Recommended readings:

 http://php.net/manual/es/book.wincache.php
 http://www.iis.net/learn/application-frameworks/install-and-configure-php-on-iis/use-the-windows-cache-extension-for-php
 http://forums.iis.net/t/1201106.aspx?WinCache+1+3+5+release+on+SourceForge

/*****************
 * 0. Installing and configuring the Wincache PHP Extension
 ****************/
 For all this to work you need to install the Wincache PHP Extension.
 I recommend downloading this extension from:
 
 http://windows.php.net/downloads/pecl/releases/
 
 These are officially compiled by the PHP.net team.
 
 Like with all other extensions, copy the one you need to the extensions folder
 of you PHP installation and enable it in PHP.ini
 
 [PHP_WINCACHE]
 extension=php_wincache.dll
 
 Restart IIS (or the application pool) to make these changes effective. You can
 check if the extension is enabled running phpinfo() or inside Drupal:
 
 http://yoursite/admin/reports/status/php
 
 Further in this document you will find details for the wincache ini settings,
 but for now this is a recommended configuration:
 
 ; Wincache ini configuration
 ; Disable Opcode cache (only for PHP >= 5, otherwise use 1)
 wincache.ocenabled=0
 ; Enable file cache
 wincache.fcenabled=1
 ; Enable user cache 
 wincache.ucenabled=1

 wincache.fcachesize = 255
 wincache.maxfilesize = 2048
 wincache.ocachesize = 255
 wincache.filecount = 8000
 wincache.ttlmax = 2000
 wincache.ucachesize = 85
 wincache.scachesize = 128

 ; NOTE: Documentation for wincache extension is unproperly pointing to max
 ; values for cache sizes. For ucachesize you can go all the way up to 2048Mb.
 
 ; Configure the file system funcion acces reroutes
 ; Make sure file exists and the IIS application has permissions to read.
 wincache.rerouteini = "C:\Program Files (x86)\PHP\php_5_5\reroute.ini"
 
 [Session]
 ; Handler used to store/retrieve data.
 ; http://php.net/session.save-handler
 session.save_handler = wincache
 ; Where to store sessions if wincache is the session handler.
 ; Make sure the folder exists and that the identity of you PHP process
 ; has read/write permissions.
 session.save_path = "C:\Program Files (x86)\PHP\php5_5_sessions\"

 ; Session data is not persisted by Wincache session handler if your appPool
 ; name has periods.
 ; If your app-pool name has periods (.) in it, change them to underscores (_).
 ; So an app-pool named www.somesite.com should be renamed to www_somesite_com.
 
 ; To make sure these settings are working, check you extension settings
 ; in phpinfo() and access the Wincache statistics page, on you first
 ; run you will need to customize the username and password of the
 ; wincache.php access by directly editing the file.

 http://yoursite/sites/all/modules/wincachedrupal/misc/wincache.php

 or if you have enabled the wincache module:

 http://yoursite/admin/reports/status/wincache

/*****************
 * 1. Cache Backend (AKA "User Cache")
 ****************/
 Wincache uses in memory storage which makes it way faster than memcache
 and other backend storage systems. It is a replacement for APC cache in
 windows systems. The drawback is that wincache has severe memory limitations
 so unless you have a small site, you should not be using it as your main
 cache backend, or be very careful as to what cache tables you are redirecting
 to wincache. On small sites you can use Wincache as your default backend,
 on medium to large sites just use the most frequently accesed caches
 such as bootstrap, menu and/or variable. Maximum documented size for this
 cache is 85Mb but you can go all the way up to 2048Mb without problems.
 
 IMPORTANT: There is a bug in Wincache 1.3.6 when used with PHP 5.6.X where
 you will have a fatal failure if user cache size is set above 450Mb.
 
 http://forums.iis.net/t/1214439.aspx?Wincache+1+3+6

 Adjust the cache size to fit your site, recommended to start with 128Mb.

 CAREFUL: Exhaustion of usercache memory will slow down your site, keep an eye
 every once in a while on the statistics page to make sure you have memory
 overhead, and if don't, just increase ucache size.
 
 Copy the drupalwincache module into you site's module folder:
 
 sites/all/modules/wincachedrupal/
 
 In your site's settings.php (sites/default/settings.php): 
 
 // Register the new cache backend
 $conf['cache_backends'][] = 'sites/all/modules/wincachedrupal/drupal_win_cache.inc';

 // If you have more than one cache Backend at the same time, use this:
 $conf['cache_backends'][] = 'sites/all/modules/memcache/memcache.inc';
 $conf['cache_backends'][] = 'sites/all/modules/wincachedrupal/drupal_win_cache.inc';

 // Tell Drupal what cache types this cache backend
 // should be used with. Wincache should used for non
 // persistent cache storage with low size requirements.
 // This is a proposal for caches to run in Wincache.
 $conf['cache_class_cache'] = 'DrupalWinCache';
 $conf['cache_class_cache_bootstrap'] = 'DrupalWinCache';
 $conf['cache_class_cache_menu'] = 'DrupalWinCache';
 $conf['cache_class_cache_variable'] = 'DrupalWinCache';
 $conf['cache_class_cache_locale'] = 'DrupalWinCache';
 $conf['cache_class_cache_i18n'] = 'DrupalWinCache';
 $conf['cache_class_cache_metatag'] = 'DrupalWinCache';
 $conf['cache_class_cache_field'] = 'DrupalWinCache';
 $conf['cache_class_cache_libraries'] = 'DrupalWinCache';
 $conf['cache_class_cache_rules'] = 'DrupalWinCache';
 $conf['cache_class_cache_advagg_aggregates'] = 'DrupalWinCache';
 $conf['cache_class_cache_advagg_info'] = 'DrupalWinCache';
 $conf['cache_class_cache_views'] = 'DrupalWinCache';

 // If you have a small site then just set wincache as the default backend
 // and forget about memcache.
 $conf['cache_default_class'] = 'DrupalWinCache';
 
 Once this settings are up and running, navigate you website for the cache
 contents to be warmed up and then visit the Wincache Statistics Page and make
 sure the User Cache is being used by visiting the User Cache tab.
 
 // There are a few caches that must always go
 // to persistent storage.
 
 # Keep forms in persistent storage.
 $conf['cache_class_cache_form'] = 'DrupalDatabaseCache';

 # I don't see any point in keeping the module update information in Memcached.
 $conf['cache_class_cache_update'] = 'DrupalDatabaseCache';

/*****************
 * 2. File system operation storage accelerator 
 * http://php.net//manual/es/wincache.reroutes.php
 ****************/
 
 WinCache extension includes Windows-optimized implementation of PHP file 
 functions that may improve performance of PHP applications in 
 cases when PHP has to access files on network shares.
 
 Prior to Wincache 1.3.7.0 rerouting was broken.
 http://forums.iis.net/t/1213205.aspx?Function+reroute+not+working]
 
 After that version, file rerouting functions are enabled by default, to disable
 them use:
 
 wincache.reroute_enabled=0
 
 If WinCache functions reroutes are enabled it is recommended
 to increase the WinCache file cache size in php.ini:
 
 wincache.fcachesize = 255
 
/*****************
 * 3. File System Cache + Resolve Path Cache
 ****************/
 
 You can use Wincache to cache file system files and path resolutions.
 To do this simply enable it in php.ini:
 
 ; Enable file cache
 wincache.fcenabled=1
 
/*****************
 * 4. Opcode Cache (not needed anymore with PHP >= 5)
 ****************/
 One of the most important uses of Wincache prior to PHP 5 whas as an opcode cache.
 
 ## If you are using PHP < 5:
 
 To enable use this in php.ini:
 
 wincache.ocenabled=1
 
 Make sure to increase the size of the cache to catter your site's needs:
 
 wincache.ocachesize = 255
 
 Now acces your site for the cache to heat up and verify that the Opcode cache
 is up and running in the Wincache Statistics page.
 
 ## If you are using PHP > 5:
 
 Disable wincache opcode cache:
 
 wincache.ocenabled=0
 
 Make sure you enable Zend OPCACHE:
 
 [opcache]
 ; Determines if Zend OPCache is enabled 
 opcache.enable=1
 zend_extension=php_opcache.dll

/*****************
 * 5. Session Storage Handler
 ****************/
 
 Wincache has a session handling implementation that is faster the php's native one.
 
 To enable in php.ini:
 
 session.save_handler = wincache
 
 Tell wincache where to store session data (persistent):
 
 ; Where to store sessions if wincache is the session handler.
 ; Make sure the folder exists and that the identity of you PHP process
 ; has read/write permissions.
 session.save_path = "C:\Program Files (x86)\PHP\php5_5_sessions\"
 
 Make sure you set an appropriate size depending on you site's usage:
 
 ; 85 Mb
 wincache.ucachesize = 85

 NOTE: Using this configuration will not tell Drupal to use wincache session
 handler because Drupal implements it's own session handling system that must
 be overriden within Drupal itself. Check this link for additional information:

 http://drupal.stackexchange.com/questions/39065/understanding-drupals-session-management-and-user-authentication

 EXPERIMENTAL: There is an experimental implementation of the wincache session
 handler for Drupal. Besides all the previous configuration, in your settings.php:

 $conf['session_inc'] = 'sites/all/modules/wincachedrupal/wincache-session.inc';

 This version has not been tested under HTTPS (secure) sites.
 
/*****************
 * 6. Optional - Speed up anonymous page cache
 ****************/
 
 When using wincachedrupal as default or manually caching the 'cache_page' bin
 in your settings file you do not need to start the database because Drupal can
 use the WinCache for pages. Add the following code to your settings.php file
 to do so:

 $conf['page_cache_without_database'] = TRUE;
 $conf['page_cache_invoke_hooks'] = FALSE;

 https://www.drupal.org/node/1176856
 
/*****************
 * 7. Optional - Enabling the module
 ****************/
 
 Along with the Wincache backend this package contains a Drupal module.
 This module has some tests to make sure that Wincache is properly running
 and also provides some UI statistics.

 The module does 3 things:

 - Adds information message to the status page.
 - Shows Wincache usage statistics when user has appropriate permissions
 and wincache_show_debug is set to true (in settings.php):
 $conf['wincache_show_debug'] = TRUE;
 - Provide a set of tests.

 /*****************
 * 7. Wincache Lock Mechanism
 ****************/

  To enable the Wincache based Lock mechanism in settings.php:

  $conf['lock_inc'] = 'sites/all/modules/wincachedrupal/wincache-lock.inc';

  This works over a custom cache binary under the name of 'semaphore'.

  Enabling this locking system will save you a few database hits per request.

  Beware that this locking should only be used on single-server setup because
  wincache cannot be shared accross servers.

array_column.inc

deleted100644 → 0
+0 −115
Original line number Diff line number Diff line
<?php
/**
 * This file is part of the array_column library
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * @copyright Copyright (c) Ben Ramsey (http://benramsey.com)
 * @license http://opensource.org/licenses/MIT MIT
 */

if (!function_exists('array_column')) {
  /**
   * Returns the values from a single column of the input array, identified by
   * the $columnKey.
   *
   * Optionally, you may provide an $indexKey to index the values in the returned
   * array by the values from the $indexKey column in the input array.
   *
   * @param array $input A multi-dimensional array (record set) from which to pull
   *                     a column of values.
   * @param mixed $columnKey The column of values to return. This value may be the
   *                         integer key of the column you wish to retrieve, or it
   *                         may be the string key name for an associative array.
   * @param mixed $indexKey (Optional.) The column to use as the index/keys for
   *                        the returned array. This value may be the integer key
   *                        of the column, or it may be the string key name.
   * @return array
   */
  function array_column($input = null, $columnKey = null, $indexKey = null)
  {
    // Using func_get_args() in order to check for proper number of
    // parameters and trigger errors exactly as the built-in array_column()
    // does in PHP 5.5.
    $argc = func_num_args();
    $params = func_get_args();

    if ($argc < 2) {
      trigger_error("array_column() expects at least 2 parameters, {$argc} given", E_USER_WARNING);
      return null;
    }

    if (!is_array($params[0])) {
      trigger_error(
          'array_column() expects parameter 1 to be array, ' . gettype($params[0]) . ' given',
          E_USER_WARNING
      );
      return null;
    }

    if (!is_int($params[1])
        && !is_float($params[1])
        && !is_string($params[1])
        && $params[1] !== null
        && !(is_object($params[1]) && method_exists($params[1], '__toString'))
    ) {
      trigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING);
      return false;
    }

    if (isset($params[2])
        && !is_int($params[2])
        && !is_float($params[2])
        && !is_string($params[2])
        && !(is_object($params[2]) && method_exists($params[2], '__toString'))
    ) {
      trigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING);
      return false;
    }

    $paramsInput = $params[0];
    $paramsColumnKey = ($params[1] !== null) ? (string) $params[1] : null;

    $paramsIndexKey = null;
    if (isset($params[2])) {
      if (is_float($params[2]) || is_int($params[2])) {
        $paramsIndexKey = (int) $params[2];
      } else {
        $paramsIndexKey = (string) $params[2];
      }
    }

    $resultArray = array();

    foreach ($paramsInput as $row) {
      $key = $value = null;
      $keySet = $valueSet = false;

      if ($paramsIndexKey !== null && array_key_exists($paramsIndexKey, $row)) {
        $keySet = true;
        $key = (string) $row[$paramsIndexKey];
      }

      if ($paramsColumnKey === null) {
        $valueSet = true;
        $value = $row;
      } elseif (is_array($row) && array_key_exists($paramsColumnKey, $row)) {
        $valueSet = true;
        $value = $row[$paramsColumnKey];
      }

      if ($valueSet) {
        if ($keySet) {
          $resultArray[$key] = $value;
        } else {
          $resultArray[] = $value;
        }
      }

    }

    return $resultArray;
  }

}
 No newline at end of file

drupal_win_cache.inc

deleted100644 → 0
+0 −592

File deleted.

Preview size limit exceeded, changes collapsed.

misc/reroute.ini

deleted100644 → 0
+0 −11
Original line number Diff line number Diff line
[FunctionRerouteList]
file_exists=wincache_file_exists
file_get_contents:2=wincache_file_get_contents
readfile:2=wincache_readfile
is_readable=wincache_is_readable
is_writable=wincache_is_writable
is_writeable=wincache_is_writable
is_file=wincache_is_file
is_dir=wincache_is_dir
realpath=wincache_realpath
filesize=wincache_filesize
 No newline at end of file
Loading