[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/cache/stores/static/ -> 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 static cache store.
  19   *
  20   * This file is part of the static cache store, it contains the API for interacting with an instance of the store.
  21   * This is used as a default cache store within the Cache API. It should never be deleted.
  22   *
  23   * @package    cachestore_static
  24   * @category   cache
  25   * @copyright  2012 Sam Hemelryk
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  /**
  32   * The static data store class
  33   *
  34   * @copyright  2012 Sam Hemelryk
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  abstract class static_data_store extends cache_store {
  38  
  39      /**
  40       * An array for storage.
  41       * @var array
  42       */
  43      private static $staticstore = array();
  44  
  45      /**
  46       * Returns a static store by reference... REFERENCE SUPER IMPORTANT.
  47       *
  48       * @param string $id
  49       * @return array
  50       */
  51      protected static function &register_store_id($id) {
  52          if (!array_key_exists($id, self::$staticstore)) {
  53              self::$staticstore[$id] = array();
  54          }
  55          return self::$staticstore[$id];
  56      }
  57  
  58      /**
  59       * Flushes the store of all values for belonging to the store with the given id.
  60       * @param string $id
  61       */
  62      protected static function flush_store_by_id($id) {
  63          unset(self::$staticstore[$id]);
  64          self::$staticstore[$id] = array();
  65      }
  66  
  67      /**
  68       * Flushes all of the values from all stores.
  69       *
  70       * @copyright  2012 Sam Hemelryk
  71       * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  72       */
  73      protected static function flush_store() {
  74          $ids = array_keys(self::$staticstore);
  75          unset(self::$staticstore);
  76          self::$staticstore = array();
  77          foreach ($ids as $id) {
  78              self::$staticstore[$id] = array();
  79          }
  80      }
  81  }
  82  
  83  /**
  84   * The static store class.
  85   *
  86   * @copyright  2012 Sam Hemelryk
  87   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  88   */
  89  class cachestore_static extends static_data_store implements cache_is_key_aware, cache_is_searchable {
  90  
  91      /**
  92       * The name of the store
  93       * @var store
  94       */
  95      protected $name;
  96  
  97      /**
  98       * The store id (should be unique)
  99       * @var string
 100       */
 101      protected $storeid;
 102  
 103      /**
 104       * The store we use for data.
 105       * @var array
 106       */
 107      protected $store;
 108  
 109      /**
 110       * The ttl if there is one. Hopefully not.
 111       * @var int
 112       */
 113      protected $ttl = 0;
 114  
 115      /**
 116       * The maximum size for the store, or false if there isn't one.
 117       * @var bool
 118       */
 119      protected $maxsize = false;
 120  
 121      /**
 122       * The number of items currently being stored.
 123       * @var int
 124       */
 125      protected $storecount = 0;
 126  
 127      /**
 128       * Constructs the store instance.
 129       *
 130       * Noting that this function is not an initialisation. It is used to prepare the store for use.
 131       * The store will be initialised when required and will be provided with a cache_definition at that time.
 132       *
 133       * @param string $name
 134       * @param array $configuration
 135       */
 136      public function __construct($name, array $configuration = array()) {
 137          $this->name = $name;
 138      }
 139  
 140      /**
 141       * Returns the supported features as a combined int.
 142       *
 143       * @param array $configuration
 144       * @return int
 145       */
 146      public static function get_supported_features(array $configuration = array()) {
 147          return self::SUPPORTS_DATA_GUARANTEE +
 148                 self::SUPPORTS_NATIVE_TTL +
 149                 self::IS_SEARCHABLE;
 150      }
 151  
 152      /**
 153       * Returns false as this store does not support multiple identifiers.
 154       * (This optional function is a performance optimisation; it must be
 155       * consistent with the value from get_supported_features.)
 156       *
 157       * @return bool False
 158       */
 159      public function supports_multiple_identifiers() {
 160          return false;
 161      }
 162  
 163      /**
 164       * Returns the supported modes as a combined int.
 165       *
 166       * @param array $configuration
 167       * @return int
 168       */
 169      public static function get_supported_modes(array $configuration = array()) {
 170          return self::MODE_REQUEST;
 171      }
 172  
 173      /**
 174       * Returns true if the store requirements are met.
 175       *
 176       * @return bool
 177       */
 178      public static function are_requirements_met() {
 179          return true;
 180      }
 181  
 182      /**
 183       * Returns true if the given mode is supported by this store.
 184       *
 185       * @param int $mode One of cache_store::MODE_*
 186       * @return bool
 187       */
 188      public static function is_supported_mode($mode) {
 189          return ($mode === self::MODE_REQUEST);
 190      }
 191  
 192      /**
 193       * Initialises the cache.
 194       *
 195       * Once this has been done the cache is all set to be used.
 196       *
 197       * @param cache_definition $definition
 198       */
 199      public function initialise(cache_definition $definition) {
 200          $this->storeid = $definition->generate_definition_hash();
 201          $this->store = &self::register_store_id($this->storeid);
 202          $this->ttl = $definition->get_ttl();
 203          $maxsize = $definition->get_maxsize();
 204          if ($maxsize !== null) {
 205              // Must be a positive int.
 206              $this->maxsize = abs((int)$maxsize);
 207              $this->storecount = count($this->store);
 208          }
 209      }
 210  
 211      /**
 212       * Returns true once this instance has been initialised.
 213       *
 214       * @return bool
 215       */
 216      public function is_initialised() {
 217          return (is_array($this->store));
 218      }
 219  
 220      /**
 221       * Retrieves an item from the cache store given its key.
 222       *
 223       * @param string $key The key to retrieve
 224       * @return mixed The data that was associated with the key, or false if the key did not exist.
 225       */
 226      public function get($key) {
 227          if (isset($this->store[$key])) {
 228              if ($this->ttl == 0) {
 229                  return $this->store[$key][0];
 230              } else if ($this->store[$key][1] >= (cache::now() - $this->ttl)) {
 231                  return $this->store[$key][0];
 232              }
 233          }
 234          return false;
 235      }
 236  
 237      /**
 238       * Retrieves several items from the cache store in a single transaction.
 239       *
 240       * 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.
 241       *
 242       * @param array $keys The array of keys to retrieve
 243       * @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
 244       *      be set to false.
 245       */
 246      public function get_many($keys) {
 247          $return = array();
 248          if ($this->ttl != 0) {
 249              $maxtime = cache::now() - $this->ttl;
 250          }
 251  
 252          foreach ($keys as $key) {
 253              $return[$key] = false;
 254              if (isset($this->store[$key])) {
 255                  if ($this->ttl == 0) {
 256                      $return[$key] = $this->store[$key][0];
 257                  } else if ($this->store[$key][1] >= $maxtime) {
 258                      $return[$key] = $this->store[$key][0];
 259                  }
 260              }
 261          }
 262          return $return;
 263      }
 264  
 265      /**
 266       * Sets an item in the cache given its key and data value.
 267       *
 268       * @param string $key The key to use.
 269       * @param mixed $data The data to set.
 270       * @param bool $testmaxsize If set to true then we test the maxsize arg and reduce if required.
 271       * @return bool True if the operation was a success false otherwise.
 272       */
 273      public function set($key, $data, $testmaxsize = true) {
 274          $testmaxsize = ($testmaxsize && $this->maxsize !== false);
 275          if ($testmaxsize) {
 276              $increment = (!isset($this->store[$key]));
 277          }
 278          if ($this->ttl == 0) {
 279              $this->store[$key][0] = $data;
 280          } else {
 281              $this->store[$key] = array($data, cache::now());
 282          }
 283          if ($testmaxsize && $increment) {
 284              $this->storecount++;
 285              if ($this->storecount > $this->maxsize) {
 286                  $this->reduce_for_maxsize();
 287              }
 288          }
 289          return true;
 290      }
 291  
 292      /**
 293       * Sets many items in the cache in a single transaction.
 294       *
 295       * @param array $keyvaluearray An array of key value pairs. Each item in the array will be an associative array with two
 296       *      keys, 'key' and 'value'.
 297       * @return int The number of items successfully set. It is up to the developer to check this matches the number of items
 298       *      sent ... if they care that is.
 299       */
 300      public function set_many(array $keyvaluearray) {
 301          $count = 0;
 302          foreach ($keyvaluearray as $pair) {
 303              // Don't test the maxsize here. We'll do it once when we are done.
 304              $this->set($pair['key'], $pair['value'], false);
 305              $count++;
 306          }
 307          if ($this->maxsize !== false) {
 308              $this->storecount += $count;
 309              if ($this->storecount > $this->maxsize) {
 310                  $this->reduce_for_maxsize();
 311              }
 312          }
 313          return $count;
 314      }
 315  
 316      /**
 317       * Checks if the store has a record for the given key and returns true if so.
 318       *
 319       * @param string $key
 320       * @return bool
 321       */
 322      public function has($key) {
 323          if (isset($this->store[$key])) {
 324              if ($this->ttl == 0) {
 325                  return true;
 326              } else if ($this->store[$key][1] >= (cache::now() - $this->ttl)) {
 327                  return true;
 328              }
 329          }
 330          return false;
 331      }
 332  
 333      /**
 334       * Returns true if the store contains records for all of the given keys.
 335       *
 336       * @param array $keys
 337       * @return bool
 338       */
 339      public function has_all(array $keys) {
 340          if ($this->ttl != 0) {
 341              $maxtime = cache::now() - $this->ttl;
 342          }
 343  
 344          foreach ($keys as $key) {
 345              if (!isset($this->store[$key])) {
 346                  return false;
 347              }
 348              if ($this->ttl != 0 && $this->store[$key][1] < $maxtime) {
 349                  return false;
 350              }
 351          }
 352          return true;
 353      }
 354  
 355      /**
 356       * Returns true if the store contains records for any of the given keys.
 357       *
 358       * @param array $keys
 359       * @return bool
 360       */
 361      public function has_any(array $keys) {
 362          if ($this->ttl != 0) {
 363              $maxtime = cache::now() - $this->ttl;
 364          }
 365  
 366          foreach ($keys as $key) {
 367              if (isset($this->store[$key]) && ($this->ttl == 0 || $this->store[$key][1] >= $maxtime)) {
 368                  return true;
 369              }
 370          }
 371          return false;
 372      }
 373  
 374      /**
 375       * Deletes an item from the cache store.
 376       *
 377       * @param string $key The key to delete.
 378       * @return bool Returns true if the operation was a success, false otherwise.
 379       */
 380      public function delete($key) {
 381          $result = isset($this->store[$key]);
 382          unset($this->store[$key]);
 383          if ($this->maxsize !== false) {
 384              $this->storecount--;
 385          }
 386          return $result;
 387      }
 388  
 389      /**
 390       * Deletes several keys from the cache in a single action.
 391       *
 392       * @param array $keys The keys to delete
 393       * @return int The number of items successfully deleted.
 394       */
 395      public function delete_many(array $keys) {
 396          $count = 0;
 397          foreach ($keys as $key) {
 398              if (isset($this->store[$key])) {
 399                  $count++;
 400              }
 401              unset($this->store[$key]);
 402          }
 403          if ($this->maxsize !== false) {
 404              $this->storecount -= $count;
 405          }
 406          return $count;
 407      }
 408  
 409      /**
 410       * Purges the cache deleting all items within it.
 411       *
 412       * @return boolean True on success. False otherwise.
 413       */
 414      public function purge() {
 415          $this->flush_store_by_id($this->storeid);
 416          $this->store = &self::register_store_id($this->storeid);
 417          // Don't worry about checking if we're using max size just set it as thats as fast as the check.
 418          $this->storecount = 0;
 419          return true;
 420      }
 421  
 422      /**
 423       * Reduces the size of the array if maxsize has been hit.
 424       *
 425       * This function reduces the size of the store reducing it by 10% of its maxsize.
 426       * It removes the oldest items in the store when doing this.
 427       * The reason it does this an doesn't use a least recently used system is purely the overhead such a system
 428       * requires. The current approach is focused on speed, MUC already adds enough overhead to static/session caches
 429       * and avoiding more is of benefit.
 430       *
 431       * @return int
 432       */
 433      protected function reduce_for_maxsize() {
 434          $diff = $this->storecount - $this->maxsize;
 435          if ($diff < 1) {
 436              return 0;
 437          }
 438          // Reduce it by an extra 10% to avoid calling this repetitively if we are in a loop.
 439          $diff += floor($this->maxsize / 10);
 440          $this->store = array_slice($this->store, $diff, null, true);
 441          $this->storecount -= $diff;
 442          return $diff;
 443      }
 444  
 445      /**
 446       * Returns true if the user can add an instance of the store plugin.
 447       *
 448       * @return bool
 449       */
 450      public static function can_add_instance() {
 451          return false;
 452      }
 453  
 454      /**
 455       * Performs any necessary clean up when the store instance is being deleted.
 456       */
 457      public function instance_deleted() {
 458          $this->purge();
 459      }
 460  
 461      /**
 462       * Generates an instance of the cache store that can be used for testing.
 463       *
 464       * @param cache_definition $definition
 465       * @return cachestore_static
 466       */
 467      public static function initialise_test_instance(cache_definition $definition) {
 468          // Do something here perhaps.
 469          $cache = new cachestore_static('Static store');
 470          $cache->initialise($definition);
 471          return $cache;
 472      }
 473  
 474      /**
 475       * Returns the name of this instance.
 476       * @return string
 477       */
 478      public function my_name() {
 479          return $this->name;
 480      }
 481  
 482      /**
 483       * Finds all of the keys being stored in the cache store instance.
 484       *
 485       * @return array
 486       */
 487      public function find_all() {
 488          return array_keys($this->store);
 489      }
 490  
 491      /**
 492       * Finds all of the keys whose keys start with the given prefix.
 493       *
 494       * @param string $prefix
 495       */
 496      public function find_by_prefix($prefix) {
 497          $return = array();
 498          foreach ($this->find_all() as $key) {
 499              if (strpos($key, $prefix) === 0) {
 500                  $return[] = $key;
 501              }
 502          }
 503          return $return;
 504      }
 505  }


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