[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 ®ister_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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |