[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/cache/stores/memcached/ -> lib.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * The library file for the memcached cache store.
  19   *
  20   * This file is part of the memcached cache store, it contains the API for interacting with an instance of the store.
  21   *
  22   * @package    cachestore_memcached
  23   * @copyright  2012 Sam Hemelryk
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * The memcached store.
  31   *
  32   * (Not to be confused with the memcache store)
  33   *
  34   * Configuration options:
  35   *      servers:        string: host:port:weight , ...
  36   *      compression:    true, false
  37   *      serialiser:     SERIALIZER_PHP, SERIALIZER_JSON, SERIALIZER_IGBINARY
  38   *      prefix:         string: defaults to instance name
  39   *      hashmethod:     HASH_DEFAULT, HASH_MD5, HASH_CRC, HASH_FNV1_64, HASH_FNV1A_64, HASH_FNV1_32,
  40   *                      HASH_FNV1A_32, HASH_HSIEH, HASH_MURMUR
  41   *      bufferwrites:   true, false
  42   *
  43   * @copyright  2012 Sam Hemelryk
  44   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  45   */
  46  class cachestore_memcached extends cache_store implements cache_is_configurable {
  47  
  48      /**
  49       * The minimum required version of memcached in order to use this store.
  50       */
  51      const REQUIRED_VERSION = '2.0.0';
  52  
  53      /**
  54       * The name of the store
  55       * @var store
  56       */
  57      protected $name;
  58  
  59      /**
  60       * The memcached connection
  61       * @var Memcached
  62       */
  63      protected $connection;
  64  
  65      /**
  66       * An array of servers to use during connection
  67       * @var array
  68       */
  69      protected $servers = array();
  70  
  71      /**
  72       * The options used when establishing the connection
  73       * @var array
  74       */
  75      protected $options = array();
  76  
  77      /**
  78       * True when this instance is ready to be initialised.
  79       * @var bool
  80       */
  81      protected $isready = false;
  82  
  83      /**
  84       * Set to true when this store instance has been initialised.
  85       * @var bool
  86       */
  87      protected $isinitialised = false;
  88  
  89      /**
  90       * The cache definition this store was initialised with.
  91       * @var cache_definition
  92       */
  93      protected $definition;
  94  
  95      /**
  96       * Set to true when this store is clustered.
  97       * @var bool
  98       */
  99      protected $clustered = false;
 100  
 101      /**
 102       * Array of servers to set when in clustered mode.
 103       * @var array
 104       */
 105      protected $setservers = array();
 106  
 107      /**
 108       * The an array of memcache connections for the set servers, once established.
 109       * @var array
 110       */
 111      protected $setconnections = array();
 112  
 113      /**
 114       * The prefix to use on all keys.
 115       * @var string
 116       */
 117      protected $prefix = '';
 118  
 119      /**
 120       * True if Memcached::deleteMulti can be used, false otherwise.
 121       * This required extension version 2.0.0 or greater.
 122       * @var bool
 123       */
 124      protected $candeletemulti = false;
 125  
 126      /**
 127       * True if the memcached server is shared, false otherwise.
 128       * This required extension version 2.0.0 or greater.
 129       * @var bool
 130       */
 131      protected $isshared = false;
 132  
 133      /**
 134       * Constructs the store instance.
 135       *
 136       * Noting that this function is not an initialisation. It is used to prepare the store for use.
 137       * The store will be initialised when required and will be provided with a cache_definition at that time.
 138       *
 139       * @param string $name
 140       * @param array $configuration
 141       */
 142      public function __construct($name, array $configuration = array()) {
 143          $this->name = $name;
 144          if (!array_key_exists('servers', $configuration) || empty($configuration['servers'])) {
 145              // Nothing configured.
 146              return;
 147          }
 148          if (!is_array($configuration['servers'])) {
 149              $configuration['servers'] = array($configuration['servers']);
 150          }
 151  
 152          $compression = array_key_exists('compression', $configuration) ? (bool)$configuration['compression'] : true;
 153          if (array_key_exists('serialiser', $configuration)) {
 154              $serialiser = (int)$configuration['serialiser'];
 155          } else {
 156              $serialiser = Memcached::SERIALIZER_PHP;
 157          }
 158          $prefix = (!empty($configuration['prefix'])) ? (string)$configuration['prefix'] : crc32($name);
 159          $hashmethod = (array_key_exists('hash', $configuration)) ? (int)$configuration['hash'] : Memcached::HASH_DEFAULT;
 160          $bufferwrites = array_key_exists('bufferwrites', $configuration) ? (bool)$configuration['bufferwrites'] : false;
 161  
 162          foreach ($configuration['servers'] as $server) {
 163              if (!is_array($server)) {
 164                  $server = explode(':', $server, 3);
 165              }
 166              if (!array_key_exists(1, $server)) {
 167                  $server[1] = 11211;
 168                  $server[2] = 100;
 169              } else if (!array_key_exists(2, $server)) {
 170                  $server[2] = 100;
 171              }
 172              $this->servers[] = $server;
 173          }
 174  
 175          $this->clustered = array_key_exists('clustered', $configuration) ? (bool)$configuration['clustered'] : false;
 176  
 177          if ($this->clustered) {
 178              if (!array_key_exists('setservers', $configuration) || (count($configuration['setservers']) < 1)) {
 179                  // Can't setup clustering without set servers.
 180                  return;
 181              }
 182              if (count($this->servers) !== 1) {
 183                  // Can only setup cluster with exactly 1 get server.
 184                  return;
 185              }
 186              foreach ($configuration['setservers'] as $server) {
 187                  // We do not use weights (3rd part) on these servers.
 188                  if (!is_array($server)) {
 189                      $server = explode(':', $server, 3);
 190                  }
 191                  if (!array_key_exists(1, $server)) {
 192                      $server[1] = 11211;
 193                  }
 194                  $this->setservers[] = $server;
 195              }
 196          }
 197  
 198          $this->options[Memcached::OPT_COMPRESSION] = $compression;
 199          $this->options[Memcached::OPT_SERIALIZER] = $serialiser;
 200          $this->options[Memcached::OPT_PREFIX_KEY] = $this->prefix = (string)$prefix;
 201          $this->options[Memcached::OPT_HASH] = $hashmethod;
 202          $this->options[Memcached::OPT_BUFFER_WRITES] = $bufferwrites;
 203  
 204          $this->connection = new Memcached(crc32($this->name));
 205          $servers = $this->connection->getServerList();
 206          if (empty($servers)) {
 207              foreach ($this->options as $key => $value) {
 208                  $this->connection->setOption($key, $value);
 209              }
 210              $this->connection->addServers($this->servers);
 211          }
 212  
 213          if ($this->clustered) {
 214              foreach ($this->setservers as $setserver) {
 215                  // Since we will have a number of them with the same name, append server and port.
 216                  $connection = new Memcached(crc32($this->name.$setserver[0].$setserver[1]));
 217                  foreach ($this->options as $key => $value) {
 218                      $connection->setOption($key, $value);
 219                  }
 220                  $connection->addServer($setserver[0], $setserver[1]);
 221                  $this->setconnections[] = $connection;
 222              }
 223          }
 224  
 225          if (isset($configuration['isshared'])) {
 226              $this->isshared = $configuration['isshared'];
 227          }
 228  
 229          $version = phpversion('memcached');
 230          $this->candeletemulti = ($version && version_compare($version, self::REQUIRED_VERSION, '>='));
 231  
 232          // Test the connection to the main connection.
 233          $this->isready = @$this->connection->set("ping", 'ping', 1);
 234      }
 235  
 236      /**
 237       * Initialises the cache.
 238       *
 239       * Once this has been done the cache is all set to be used.
 240       *
 241       * @throws coding_exception if the instance has already been initialised.
 242       * @param cache_definition $definition
 243       */
 244      public function initialise(cache_definition $definition) {
 245          if ($this->is_initialised()) {
 246              throw new coding_exception('This memcached instance has already been initialised.');
 247          }
 248          $this->definition = $definition;
 249          $this->isinitialised = true;
 250      }
 251  
 252      /**
 253       * Returns true once this instance has been initialised.
 254       *
 255       * @return bool
 256       */
 257      public function is_initialised() {
 258          return ($this->isinitialised);
 259      }
 260  
 261      /**
 262       * Returns true if this store instance is ready to be used.
 263       * @return bool
 264       */
 265      public function is_ready() {
 266          return $this->isready;
 267      }
 268  
 269      /**
 270       * Returns true if the store requirements are met.
 271       *
 272       * @return bool
 273       */
 274      public static function are_requirements_met() {
 275          return extension_loaded('memcached') && class_exists('Memcached');
 276      }
 277  
 278      /**
 279       * Returns true if the given mode is supported by this store.
 280       *
 281       * @param int $mode One of cache_store::MODE_*
 282       * @return bool
 283       */
 284      public static function is_supported_mode($mode) {
 285          return ($mode === self::MODE_APPLICATION || $mode === self::MODE_SESSION);
 286      }
 287  
 288      /**
 289       * Returns the supported features as a combined int.
 290       *
 291       * @param array $configuration
 292       * @return int
 293       */
 294      public static function get_supported_features(array $configuration = array()) {
 295          return self::SUPPORTS_NATIVE_TTL + self::DEREFERENCES_OBJECTS;
 296      }
 297  
 298      /**
 299       * Returns false as this store does not support multiple identifiers.
 300       * (This optional function is a performance optimisation; it must be
 301       * consistent with the value from get_supported_features.)
 302       *
 303       * @return bool False
 304       */
 305      public function supports_multiple_identifiers() {
 306          return false;
 307      }
 308  
 309      /**
 310       * Returns the supported modes as a combined int.
 311       *
 312       * @param array $configuration
 313       * @return int
 314       */
 315      public static function get_supported_modes(array $configuration = array()) {
 316          return self::MODE_APPLICATION;
 317      }
 318  
 319      /**
 320       * Retrieves an item from the cache store given its key.
 321       *
 322       * @param string $key The key to retrieve
 323       * @return mixed The data that was associated with the key, or false if the key did not exist.
 324       */
 325      public function get($key) {
 326          return $this->connection->get($key);
 327      }
 328  
 329      /**
 330       * Retrieves several items from the cache store in a single transaction.
 331       *
 332       * If not all of the items are available in the cache then the data value for those that are missing will be set to false.
 333       *
 334       * @param array $keys The array of keys to retrieve
 335       * @return array An array of items from the cache. There will be an item for each key, those that were not in the store will
 336       *      be set to false.
 337       */
 338      public function get_many($keys) {
 339          $return = array();
 340          $result = $this->connection->getMulti($keys);
 341          if (!is_array($result)) {
 342              $result = array();
 343          }
 344          foreach ($keys as $key) {
 345              if (!array_key_exists($key, $result)) {
 346                  $return[$key] = false;
 347              } else {
 348                  $return[$key] = $result[$key];
 349              }
 350          }
 351          return $return;
 352      }
 353  
 354      /**
 355       * Sets an item in the cache given its key and data value.
 356       *
 357       * @param string $key The key to use.
 358       * @param mixed $data The data to set.
 359       * @return bool True if the operation was a success false otherwise.
 360       */
 361      public function set($key, $data) {
 362          if ($this->clustered) {
 363              $status = true;
 364              foreach ($this->setconnections as $connection) {
 365                  $status = $connection->set($key, $data, $this->definition->get_ttl()) && $status;
 366              }
 367              return $status;
 368          }
 369  
 370          return $this->connection->set($key, $data, $this->definition->get_ttl());
 371      }
 372  
 373      /**
 374       * Sets many items in the cache in a single transaction.
 375       *
 376       * @param array $keyvaluearray An array of key value pairs. Each item in the array will be an associative array with two
 377       *      keys, 'key' and 'value'.
 378       * @return int The number of items successfully set. It is up to the developer to check this matches the number of items
 379       *      sent ... if they care that is.
 380       */
 381      public function set_many(array $keyvaluearray) {
 382          $pairs = array();
 383          foreach ($keyvaluearray as $pair) {
 384              $pairs[$pair['key']] = $pair['value'];
 385          }
 386  
 387          $status = true;
 388          if ($this->clustered) {
 389              foreach ($this->setconnections as $connection) {
 390                  $status = $connection->setMulti($pairs, $this->definition->get_ttl()) && $status;
 391              }
 392          } else {
 393              $status = $this->connection->setMulti($pairs, $this->definition->get_ttl());
 394          }
 395  
 396          if ($status) {
 397              return count($keyvaluearray);
 398          }
 399          return 0;
 400      }
 401  
 402      /**
 403       * Deletes an item from the cache store.
 404       *
 405       * @param string $key The key to delete.
 406       * @return bool Returns true if the operation was a success, false otherwise.
 407       */
 408      public function delete($key) {
 409          if ($this->clustered) {
 410              $status = true;
 411              foreach ($this->setconnections as $connection) {
 412                  $status = $connection->delete($key) && $status;
 413              }
 414              return $status;
 415          }
 416  
 417          return $this->connection->delete($key);
 418      }
 419  
 420      /**
 421       * Deletes several keys from the cache in a single action.
 422       *
 423       * @param array $keys The keys to delete
 424       * @return int The number of items successfully deleted.
 425       */
 426      public function delete_many(array $keys) {
 427          if ($this->clustered) {
 428              // Get the minimum deleted from any of the connections.
 429              $count = count($keys);
 430              foreach ($this->setconnections as $connection) {
 431                  $count = min($this->delete_many_connection($connection, $keys), $count);
 432              }
 433              return $count;
 434          }
 435  
 436          return $this->delete_many_connection($this->connection, $keys);
 437      }
 438  
 439      /**
 440       * Deletes several keys from the cache in a single action for a specific connection.
 441       *
 442       * @param Memcached $connection The connection to work on.
 443       * @param array $keys The keys to delete
 444       * @return int The number of items successfully deleted.
 445       */
 446      protected function delete_many_connection(Memcached $connection, array $keys) {
 447          $count = 0;
 448          if ($this->candeletemulti) {
 449              // We can use deleteMulti, this is a bit faster yay!
 450              $result = $connection->deleteMulti($keys);
 451              foreach ($result as $key => $outcome) {
 452                  if ($outcome === true) {
 453                      $count++;
 454                  }
 455              }
 456              return $count;
 457          }
 458  
 459          // They are running an older version of the php memcached extension.
 460          foreach ($keys as $key) {
 461              if ($connection->delete($key)) {
 462                  $count++;
 463              }
 464          }
 465          return $count;
 466      }
 467  
 468      /**
 469       * Purges the cache deleting all items within it.
 470       *
 471       * @return boolean True on success. False otherwise.
 472       */
 473      public function purge() {
 474          if ($this->isready) {
 475              // Only use delete multi if we have the correct extension installed and if the memcached
 476              // server is shared (flushing the cache is quicker otherwise).
 477              $candeletemulti = ($this->candeletemulti && $this->isshared);
 478  
 479              if ($this->clustered) {
 480                  foreach ($this->setconnections as $connection) {
 481                      if ($candeletemulti) {
 482                          $keys = self::get_prefixed_keys($connection, $this->prefix);
 483                          $connection->deleteMulti($keys);
 484                      } else {
 485                          // Oh damn, this isn't multi-site safe.
 486                          $connection->flush();
 487                      }
 488                  }
 489              } else if ($candeletemulti) {
 490                  $keys = self::get_prefixed_keys($this->connection, $this->prefix);
 491                  $this->connection->deleteMulti($keys);
 492              } else {
 493                  // Oh damn, this isn't multi-site safe.
 494                  $this->connection->flush();
 495              }
 496          }
 497          // It never fails. Ever.
 498          return true;
 499      }
 500  
 501      /**
 502       * Returns all of the keys in the given connection that belong to this cache store instance.
 503       *
 504       * Requires php memcached extension version 2.0.0 or greater.
 505       *
 506       * @param Memcached $connection
 507       * @param string $prefix
 508       * @return array
 509       */
 510      protected static function get_prefixed_keys(Memcached $connection, $prefix) {
 511          $connkeys = $connection->getAllKeys();
 512          if (empty($connkeys)) {
 513              return array();
 514          }
 515  
 516          $keys = array();
 517          $start = strlen($prefix);
 518          foreach ($connkeys as $key) {
 519              if (strpos($key, $prefix) === 0) {
 520                  $keys[] = substr($key, $start);
 521              }
 522          }
 523          return $keys;
 524      }
 525  
 526      /**
 527       * Gets an array of options to use as the serialiser.
 528       * @return array
 529       */
 530      public static function config_get_serialiser_options() {
 531          $options = array(
 532              Memcached::SERIALIZER_PHP => get_string('serialiser_php', 'cachestore_memcached')
 533          );
 534          if (Memcached::HAVE_JSON) {
 535              $options[Memcached::SERIALIZER_JSON] = get_string('serialiser_json', 'cachestore_memcached');
 536          }
 537          if (Memcached::HAVE_IGBINARY) {
 538              $options[Memcached::SERIALIZER_IGBINARY] = get_string('serialiser_igbinary', 'cachestore_memcached');
 539          }
 540          return $options;
 541      }
 542  
 543      /**
 544       * Gets an array of hash options available during configuration.
 545       * @return array
 546       */
 547      public static function config_get_hash_options() {
 548          $options = array(
 549              Memcached::HASH_DEFAULT => get_string('hash_default', 'cachestore_memcached'),
 550              Memcached::HASH_MD5 => get_string('hash_md5', 'cachestore_memcached'),
 551              Memcached::HASH_CRC => get_string('hash_crc', 'cachestore_memcached'),
 552              Memcached::HASH_FNV1_64 => get_string('hash_fnv1_64', 'cachestore_memcached'),
 553              Memcached::HASH_FNV1A_64 => get_string('hash_fnv1a_64', 'cachestore_memcached'),
 554              Memcached::HASH_FNV1_32 => get_string('hash_fnv1_32', 'cachestore_memcached'),
 555              Memcached::HASH_FNV1A_32 => get_string('hash_fnv1a_32', 'cachestore_memcached'),
 556              Memcached::HASH_HSIEH => get_string('hash_hsieh', 'cachestore_memcached'),
 557              Memcached::HASH_MURMUR => get_string('hash_murmur', 'cachestore_memcached'),
 558          );
 559          return $options;
 560      }
 561  
 562      /**
 563       * Given the data from the add instance form this function creates a configuration array.
 564       *
 565       * @param stdClass $data
 566       * @return array
 567       */
 568      public static function config_get_configuration_array($data) {
 569          $lines = explode("\n", $data->servers);
 570          $servers = array();
 571          foreach ($lines as $line) {
 572              // Trim surrounding colons and default whitespace.
 573              $line = trim(trim($line), ":");
 574              // Skip blank lines.
 575              if ($line === '') {
 576                  continue;
 577              }
 578              $servers[] = explode(':', $line, 3);
 579          }
 580  
 581          $clustered = false;
 582          $setservers = array();
 583          if (isset($data->clustered)) {
 584              $clustered = true;
 585  
 586              $lines = explode("\n", $data->setservers);
 587              foreach ($lines as $line) {
 588                  // Trim surrounding colons and default whitespace.
 589                  $line = trim(trim($line), ":");
 590                  if ($line === '') {
 591                      continue;
 592                  }
 593                  $setserver = explode(':', $line, 3);
 594                  // We don't use weights, so display a debug message.
 595                  if (count($setserver) > 2) {
 596                      debugging('Memcached Set Server '.$setserver[0].' has too many parameters.');
 597                  }
 598                  $setservers[] = $setserver;
 599              }
 600          }
 601  
 602          $isshared = false;
 603          if (isset($data->isshared)) {
 604              $isshared = $data->isshared;
 605          }
 606  
 607          return array(
 608              'servers' => $servers,
 609              'compression' => $data->compression,
 610              'serialiser' => $data->serialiser,
 611              'prefix' => $data->prefix,
 612              'hash' => $data->hash,
 613              'bufferwrites' => $data->bufferwrites,
 614              'clustered' => $clustered,
 615              'setservers' => $setservers,
 616              'isshared' => $isshared
 617          );
 618      }
 619  
 620      /**
 621       * Allows the cache store to set its data against the edit form before it is shown to the user.
 622       *
 623       * @param moodleform $editform
 624       * @param array $config
 625       */
 626      public static function config_set_edit_form_data(moodleform $editform, array $config) {
 627          $data = array();
 628          if (!empty($config['servers'])) {
 629              $servers = array();
 630              foreach ($config['servers'] as $server) {
 631                  $servers[] = join(":", $server);
 632              }
 633              $data['servers'] = join("\n", $servers);
 634          }
 635          if (isset($config['compression'])) {
 636              $data['compression'] = (bool)$config['compression'];
 637          }
 638          if (!empty($config['serialiser'])) {
 639              $data['serialiser'] = $config['serialiser'];
 640          }
 641          if (!empty($config['prefix'])) {
 642              $data['prefix'] = $config['prefix'];
 643          }
 644          if (!empty($config['hash'])) {
 645              $data['hash'] = $config['hash'];
 646          }
 647          if (isset($config['bufferwrites'])) {
 648              $data['bufferwrites'] = (bool)$config['bufferwrites'];
 649          }
 650          if (isset($config['clustered'])) {
 651              $data['clustered'] = (bool)$config['clustered'];
 652          }
 653          if (!empty($config['setservers'])) {
 654              $servers = array();
 655              foreach ($config['setservers'] as $server) {
 656                  $servers[] = join(":", $server);
 657              }
 658              $data['setservers'] = join("\n", $servers);
 659          }
 660          if (isset($config['isshared'])) {
 661              $data['isshared'] = $config['isshared'];
 662          }
 663          $editform->set_data($data);
 664      }
 665  
 666      /**
 667       * Performs any necessary clean up when the store instance is being deleted.
 668       */
 669      public function instance_deleted() {
 670          if ($this->connection) {
 671              $connection = $this->connection;
 672          } else {
 673              $connection = new Memcached(crc32($this->name));
 674              $servers = $connection->getServerList();
 675              if (empty($servers)) {
 676                  foreach ($this->options as $key => $value) {
 677                      $connection->setOption($key, $value);
 678                  }
 679                  $connection->addServers($this->servers);
 680              }
 681          }
 682          // We have to flush here to be sure we are completely cleaned up.
 683          // Bad for performance but this is incredibly rare.
 684          @$connection->flush();
 685          unset($connection);
 686          unset($this->connection);
 687      }
 688  
 689      /**
 690       * Generates an instance of the cache store that can be used for testing.
 691       *
 692       * @param cache_definition $definition
 693       * @return cachestore_memcached|false
 694       */
 695      public static function initialise_test_instance(cache_definition $definition) {
 696  
 697          if (!self::are_requirements_met()) {
 698              return false;
 699          }
 700  
 701          $config = get_config('cachestore_memcached');
 702          if (empty($config->testservers)) {
 703              return false;
 704          }
 705  
 706          $configuration = array();
 707          $configuration['servers'] = explode("\n", $config->testservers);
 708          if (!empty($config->testcompression)) {
 709              $configuration['compression'] = $config->testcompression;
 710          }
 711          if (!empty($config->testserialiser)) {
 712              $configuration['serialiser'] = $config->testserialiser;
 713          }
 714          if (!empty($config->testprefix)) {
 715              $configuration['prefix'] = $config->testprefix;
 716          }
 717          if (!empty($config->testhash)) {
 718              $configuration['hash'] = $config->testhash;
 719          }
 720          if (!empty($config->testbufferwrites)) {
 721              $configuration['bufferwrites'] = $config->testbufferwrites;
 722          }
 723          if (!empty($config->testclustered)) {
 724              $configuration['clustered'] = $config->testclustered;
 725          }
 726          if (!empty($config->testsetservers)) {
 727              $configuration['setservers'] = explode("\n", $config->testsetservers);
 728          }
 729          if (!empty($config->testname)) {
 730              $name = $config->testname;
 731          } else {
 732              $name = 'Test memcached';
 733          }
 734  
 735          $store = new cachestore_memcached($name, $configuration);
 736          $store->initialise($definition);
 737  
 738          return $store;
 739      }
 740  
 741      /**
 742       * Creates a test instance for unit tests if possible.
 743       * @param cache_definition $definition
 744       * @return bool|cachestore_memcached
 745       */
 746      public static function initialise_unit_test_instance(cache_definition $definition) {
 747          if (!self::are_requirements_met()) {
 748              return false;
 749          }
 750          if (!defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) {
 751              return false;
 752          }
 753  
 754          $configuration = array();
 755          $configuration['servers'] = explode("\n", TEST_CACHESTORE_MEMCACHED_TESTSERVERS);
 756  
 757          $store = new cachestore_memcached('Test memcached', $configuration);
 758          $store->initialise($definition);
 759  
 760          return $store;
 761      }
 762  
 763      /**
 764       * Returns the name of this instance.
 765       * @return string
 766       */
 767      public function my_name() {
 768          return $this->name;
 769      }
 770  
 771      /**
 772       * Used to notify of configuration conflicts.
 773       *
 774       * The warnings returned here will be displayed on the cache configuration screen.
 775       *
 776       * @return string[] Returns an array of warnings (strings)
 777       */
 778      public function get_warnings() {
 779          global $CFG;
 780          $warnings = array();
 781          if (isset($CFG->session_memcached_save_path) && count($this->servers)) {
 782              $bits = explode(':', $CFG->session_memcached_save_path, 3);
 783              $host = array_shift($bits);
 784              $port = (count($bits)) ? array_shift($bits) : '11211';
 785  
 786              foreach ($this->servers as $server) {
 787                  if ((string)$server[0] === $host && (string)$server[1] === $port) {
 788                      $warnings[] = get_string('sessionhandlerconflict', 'cachestore_memcached', $this->my_name());
 789                      break;
 790                  }
 791              }
 792          }
 793          return $warnings;
 794      }
 795  
 796      /**
 797       * Returns true if this cache store instance is both suitable for testing, and ready for testing.
 798       *
 799       * Cache stores that support being used as the default store for unit and acceptance testing should
 800       * override this function and return true if there requirements have been met.
 801       *
 802       * @return bool
 803       */
 804      public static function ready_to_be_used_for_testing() {
 805          return defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS');
 806      }
 807  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1