PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/cache/classes/store.php

https://bitbucket.org/moodle/moodle
PHP | 536 lines | 129 code | 52 blank | 355 comment | 7 complexity | e561a6aa20149102f3457aba382e7faf MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0
  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. * Cache store - base class
  18. *
  19. * This file is part of Moodle's cache API, affectionately called MUC.
  20. * It contains the components that are required in order to use caching.
  21. *
  22. * @package core
  23. * @category cache
  24. * @copyright 2012 Sam Hemelryk
  25. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  26. */
  27. defined('MOODLE_INTERNAL') || die();
  28. /**
  29. * Cache store interface.
  30. *
  31. * This interface defines the static methods that must be implemented by every cache store plugin.
  32. * To ensure plugins implement this class the abstract cache_store class implements this interface.
  33. *
  34. * @package core
  35. * @category cache
  36. * @copyright 2012 Sam Hemelryk
  37. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38. */
  39. interface cache_store_interface {
  40. /**
  41. * Static method to check if the store requirements are met.
  42. *
  43. * @return bool True if the stores software/hardware requirements have been met and it can be used. False otherwise.
  44. */
  45. public static function are_requirements_met();
  46. /**
  47. * Static method to check if a store is usable with the given mode.
  48. *
  49. * @param int $mode One of cache_store::MODE_*
  50. */
  51. public static function is_supported_mode($mode);
  52. /**
  53. * Returns the supported features as a binary flag.
  54. *
  55. * @param array $configuration The configuration of a store to consider specifically.
  56. * @return int The supported features.
  57. */
  58. public static function get_supported_features(array $configuration = array());
  59. /**
  60. * Returns the supported modes as a binary flag.
  61. *
  62. * @param array $configuration The configuration of a store to consider specifically.
  63. * @return int The supported modes.
  64. */
  65. public static function get_supported_modes(array $configuration = array());
  66. /**
  67. * Generates an instance of the cache store that can be used for testing.
  68. *
  69. * Returns an instance of the cache store, or false if one cannot be created.
  70. *
  71. * @param cache_definition $definition
  72. * @return cache_store|false
  73. */
  74. public static function initialise_test_instance(cache_definition $definition);
  75. /**
  76. * Generates the appropriate configuration required for unit testing.
  77. *
  78. * @return array Array of unit test configuration data to be used by initialise().
  79. */
  80. public static function unit_test_configuration();
  81. }
  82. /**
  83. * Abstract cache store class.
  84. *
  85. * All cache store plugins must extend this base class.
  86. * It lays down the foundation for what is required of a cache store plugin.
  87. *
  88. * @since Moodle 2.4
  89. * @package core
  90. * @category cache
  91. * @copyright 2012 Sam Hemelryk
  92. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  93. */
  94. abstract class cache_store implements cache_store_interface {
  95. // Constants for features a cache store can support
  96. /**
  97. * Supports multi-part keys
  98. */
  99. const SUPPORTS_MULTIPLE_IDENTIFIERS = 1;
  100. /**
  101. * Ensures data remains in the cache once set.
  102. */
  103. const SUPPORTS_DATA_GUARANTEE = 2;
  104. /**
  105. * Supports a native ttl system.
  106. */
  107. const SUPPORTS_NATIVE_TTL = 4;
  108. /**
  109. * The cache is searchable by key.
  110. */
  111. const IS_SEARCHABLE = 8;
  112. /**
  113. * The cache store dereferences objects.
  114. *
  115. * When set, loaders will assume that all data coming from this store has already had all references
  116. * resolved. So even for complex object structures it will not try to remove references again.
  117. */
  118. const DEREFERENCES_OBJECTS = 16;
  119. // Constants for the modes of a cache store
  120. /**
  121. * Application caches. These are shared caches.
  122. */
  123. const MODE_APPLICATION = 1;
  124. /**
  125. * Session caches. Just access to the PHP session.
  126. */
  127. const MODE_SESSION = 2;
  128. /**
  129. * Request caches. Static caches really.
  130. */
  131. const MODE_REQUEST = 4;
  132. /**
  133. * Static caches.
  134. */
  135. const STATIC_ACCEL = '** static accel. **';
  136. /**
  137. * Returned from get_last_io_bytes if this cache store doesn't support counting bytes read/sent.
  138. */
  139. const IO_BYTES_NOT_SUPPORTED = -1;
  140. /**
  141. * Constructs an instance of the cache store.
  142. *
  143. * The constructor should be responsible for creating anything needed by the store that is not
  144. * specific to a definition.
  145. * Tasks such as opening a connection to check it is available are best done here.
  146. * Tasks that are definition specific such as creating a storage area for the definition data
  147. * or creating key tables and indexs are best done within the initialise method.
  148. *
  149. * Once a store has been constructed the cache API will check it is ready to be intialised with
  150. * a definition by called $this->is_ready().
  151. * If the setup of the store failed (connection could not be established for example) then
  152. * that method should return false so that the store instance is not selected for use.
  153. *
  154. * @param string $name The name of the cache store
  155. * @param array $configuration The configuration for this store instance.
  156. */
  157. abstract public function __construct($name, array $configuration = array());
  158. /**
  159. * Returns the name of this store instance.
  160. * @return string
  161. */
  162. abstract public function my_name();
  163. /**
  164. * Initialises a new instance of the cache store given the definition the instance is to be used for.
  165. *
  166. * This function should be used to run any definition specific setup the store instance requires.
  167. * Tasks such as creating storage areas, or creating indexes are best done here.
  168. *
  169. * Its important to note that the initialise method is expected to always succeed.
  170. * If there are setup tasks that may fail they should be done within the __construct method
  171. * and should they fail is_ready should return false.
  172. *
  173. * @param cache_definition $definition
  174. */
  175. abstract public function initialise(cache_definition $definition);
  176. /**
  177. * Returns true if this cache store instance has been initialised.
  178. * @return bool
  179. */
  180. abstract public function is_initialised();
  181. /**
  182. * Returns true if this cache store instance is ready to use.
  183. * @return bool
  184. */
  185. public function is_ready() {
  186. return forward_static_call(array($this, 'are_requirements_met'));
  187. }
  188. /**
  189. * Retrieves an item from the cache store given its key.
  190. *
  191. * @param string $key The key to retrieve
  192. * @return mixed The data that was associated with the key, or false if the key did not exist.
  193. */
  194. abstract public function get($key);
  195. /**
  196. * Retrieves several items from the cache store in a single transaction.
  197. *
  198. * 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.
  199. *
  200. * @param array $keys The array of keys to retrieve
  201. * @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
  202. * be set to false.
  203. */
  204. abstract public function get_many($keys);
  205. /**
  206. * Sets an item in the cache given its key and data value.
  207. *
  208. * @param string $key The key to use.
  209. * @param mixed $data The data to set.
  210. * @return bool True if the operation was a success false otherwise.
  211. */
  212. abstract public function set($key, $data);
  213. /**
  214. * Sets many items in the cache in a single transaction.
  215. *
  216. * @param array $keyvaluearray An array of key value pairs. Each item in the array will be an associative array with two
  217. * keys, 'key' and 'value'.
  218. * @return int The number of items successfully set. It is up to the developer to check this matches the number of items
  219. * sent ... if they care that is.
  220. */
  221. abstract public function set_many(array $keyvaluearray);
  222. /**
  223. * Deletes an item from the cache store.
  224. *
  225. * @param string $key The key to delete.
  226. * @return bool Returns true if the operation was a success, false otherwise.
  227. */
  228. abstract public function delete($key);
  229. /**
  230. * Deletes several keys from the cache in a single action.
  231. *
  232. * @param array $keys The keys to delete
  233. * @return int The number of items successfully deleted.
  234. */
  235. abstract public function delete_many(array $keys);
  236. /**
  237. * Purges the cache deleting all items within it.
  238. *
  239. * @return boolean True on success. False otherwise.
  240. */
  241. abstract public function purge();
  242. /**
  243. * @deprecated since 2.5
  244. * @see \cache_store::instance_deleted()
  245. */
  246. public function cleanup() {
  247. throw new coding_exception('cache_store::cleanup() can not be used anymore.' .
  248. ' Please use cache_store::instance_deleted() instead.');
  249. }
  250. /**
  251. * Performs any necessary operation when the store instance has been created.
  252. *
  253. * @since Moodle 2.5
  254. */
  255. public function instance_created() {
  256. // By default, do nothing.
  257. }
  258. /**
  259. * Performs any necessary operation when the store instance is being deleted.
  260. *
  261. * This method may be called before the store has been initialised.
  262. *
  263. * @since Moodle 2.5
  264. * @see cleanup()
  265. */
  266. public function instance_deleted() {
  267. if (method_exists($this, 'cleanup')) {
  268. // There used to be a legacy function called cleanup, it was renamed to instance delete.
  269. // To be removed in 2.6.
  270. $this->cleanup();
  271. }
  272. }
  273. /**
  274. * Returns true if the user can add an instance of the store plugin.
  275. *
  276. * @return bool
  277. */
  278. public static function can_add_instance() {
  279. return true;
  280. }
  281. /**
  282. * Returns true if the store instance guarantees data.
  283. *
  284. * @return bool
  285. */
  286. public function supports_data_guarantee() {
  287. return $this::get_supported_features() & self::SUPPORTS_DATA_GUARANTEE;
  288. }
  289. /**
  290. * Returns true if the store instance supports multiple identifiers.
  291. *
  292. * @return bool
  293. */
  294. public function supports_multiple_identifiers() {
  295. return $this::get_supported_features() & self::SUPPORTS_MULTIPLE_IDENTIFIERS;
  296. }
  297. /**
  298. * Returns true if the store instance supports native ttl.
  299. *
  300. * @return bool
  301. */
  302. public function supports_native_ttl() {
  303. return $this::get_supported_features() & self::SUPPORTS_NATIVE_TTL;
  304. }
  305. /**
  306. * Returns true if the store instance is searchable.
  307. *
  308. * @return bool
  309. */
  310. public function is_searchable() {
  311. return in_array('cache_is_searchable', class_implements($this));
  312. }
  313. /**
  314. * Returns true if the store automatically dereferences objects.
  315. *
  316. * @return bool
  317. */
  318. public function supports_dereferencing_objects() {
  319. return $this::get_supported_features() & self::DEREFERENCES_OBJECTS;
  320. }
  321. /**
  322. * Creates a clone of this store instance ready to be initialised.
  323. *
  324. * This method is used so that a cache store needs only be constructed once.
  325. * Future requests for an instance of the store will be given a cloned instance.
  326. *
  327. * If you are writing a cache store that isn't compatible with the clone operation
  328. * you can override this method to handle any situations you want before cloning.
  329. *
  330. * @param array $details An array containing the details of the store from the cache config.
  331. * @return cache_store
  332. */
  333. public function create_clone(array $details = array()) {
  334. // By default we just run clone.
  335. // Any stores that have an issue with this will need to override the create_clone method.
  336. return clone($this);
  337. }
  338. /**
  339. * Can be overridden to return any warnings this store instance should make to the admin.
  340. *
  341. * This should be used to notify things like configuration conflicts etc.
  342. * The warnings returned here will be displayed on the cache configuration screen.
  343. *
  344. * @return string[] An array of warning strings from the store instance.
  345. */
  346. public function get_warnings() {
  347. return array();
  348. }
  349. /**
  350. * Estimates the storage size used within this cache if the given value is stored with the
  351. * given key.
  352. *
  353. * This function is not exactly accurate; it does not necessarily take into account all the
  354. * overheads involved. It is only intended to give a good idea of the relative size of
  355. * different caches.
  356. *
  357. * The default implementation serializes both key and value and sums the lengths (as a rough
  358. * estimate which is probably good enough for everything unless the cache offers compression).
  359. *
  360. * @param mixed $key Key
  361. * @param mixed $value Value
  362. * @return int Size in bytes
  363. */
  364. public function estimate_stored_size($key, $value): int {
  365. return strlen(serialize($key)) + strlen(serialize($value));
  366. }
  367. /**
  368. * Gets the amount of memory/storage currently used by this cache store if known.
  369. *
  370. * This value should be obtained quickly from the store itself, if available.
  371. *
  372. * This is the total memory usage of the entire store, not for ther specific cache in question.
  373. *
  374. * Where not supported (default), will always return null.
  375. *
  376. * @return int|null Amount of memory used in bytes or null
  377. */
  378. public function store_total_size(): ?int {
  379. return null;
  380. }
  381. /**
  382. * Gets the amount of memory used by this specific cache within the store, if known.
  383. *
  384. * This function may be slow and should not be called in normal usage, only for administration
  385. * pages. The value is usually an estimate, and may not be available at all.
  386. *
  387. * When estimating, a number of sample items will be used for the estimate. If set to 50
  388. * (default), then this function will retrieve 50 random items and use that to estimate the
  389. * total size.
  390. *
  391. * The return value has the following fields:
  392. * - supported (true if any other values are completed)
  393. * - items (number of items)
  394. * - mean (mean size of one item in bytes)
  395. * - sd (standard deviation of item size in bytes, based on sample)
  396. * - margin (95% confidence margin for mean - will be 0 if exactly computed)
  397. *
  398. * @param int $samplekeys Number of samples to use
  399. * @return stdClass Object with information about the store size
  400. */
  401. public function cache_size_details(int $samplekeys = 50): stdClass {
  402. $result = (object)[
  403. 'supported' => false,
  404. 'items' => 0,
  405. 'mean' => 0,
  406. 'sd' => 0,
  407. 'margin' => 0
  408. ];
  409. // If this cache isn't searchable, we don't know the answer.
  410. if (!$this->is_searchable()) {
  411. return $result;
  412. }
  413. $result->supported = true;
  414. // Get all the keys for the cache.
  415. $keys = $this->find_all();
  416. $result->items = count($keys);
  417. // Don't do anything else if there are no items.
  418. if ($result->items === 0) {
  419. return $result;
  420. }
  421. // Select N random keys.
  422. $exact = false;
  423. if ($result->items <= $samplekeys) {
  424. $samples = $keys;
  425. $exact = true;
  426. } else {
  427. $indexes = array_rand($keys, $samplekeys);
  428. $samples = [];
  429. foreach ($indexes as $index) {
  430. $samples[] = $keys[$index];
  431. }
  432. }
  433. // Get the random items from cache and estimate the size of each.
  434. $sizes = [];
  435. foreach ($samples as $samplekey) {
  436. $value = $this->get($samplekey);
  437. $sizes[] = $this->estimate_stored_size($samplekey, $value);
  438. }
  439. $number = count($sizes);
  440. // Calculate the mean and standard deviation.
  441. $result->mean = array_sum($sizes) / $number;
  442. $squarediff = 0;
  443. foreach ($sizes as $size) {
  444. $squarediff += ($size - $result->mean) ** 2;
  445. }
  446. $squarediff /= $number;
  447. $result->sd = sqrt($squarediff);
  448. // If it's not exact, also calculate the confidence interval.
  449. if (!$exact) {
  450. // 95% confidence has a Z value of 1.96.
  451. $result->margin = (1.96 * $result->sd) / sqrt($number);
  452. }
  453. return $result;
  454. }
  455. /**
  456. * Returns true if this cache store instance is both suitable for testing, and ready for testing.
  457. *
  458. * Cache stores that support being used as the default store for unit and acceptance testing should
  459. * override this function and return true if there requirements have been met.
  460. *
  461. * @return bool
  462. */
  463. public static function ready_to_be_used_for_testing() {
  464. return false;
  465. }
  466. /**
  467. * Gets the number of bytes read from or written to cache as a result of the last action.
  468. *
  469. * This includes calls to the functions get(), get_many(), set(), and set_many(). The number
  470. * is reset by calling any of these functions.
  471. *
  472. * This should be the actual number of bytes of the value read from or written to cache,
  473. * giving an impression of the network or other load. It will not be exactly the same amount
  474. * as netowrk traffic because of protocol overhead, key text, etc.
  475. *
  476. * If not supported, returns IO_BYTES_NOT_SUPPORTED.
  477. *
  478. * @return int Bytes read (or 0 if none/not supported)
  479. * @since Moodle 4.0
  480. */
  481. public function get_last_io_bytes(): int {
  482. return self::IO_BYTES_NOT_SUPPORTED;
  483. }
  484. }