MDL-41997 cache: dummy store now uses static acceleration for session + request
[moodle.git] / cache / classes / definition.php
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/>.
17 /**
18  * Cache definition class
19  *
20  * This file is part of Moodle's cache API, affectionately called MUC.
21  * It contains the components that are requried in order to use caching.
22  *
23  * @package    core
24  * @category   cache
25  * @copyright  2012 Sam Hemelryk
26  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27  */
29 defined('MOODLE_INTERNAL') || die();
31 /**
32  * The cache definition class.
33  *
34  * Cache definitions need to be defined in db/caches.php files.
35  * They can be constructed with the following options.
36  *
37  * Required settings:
38  *     + mode
39  *          [int] Sets the mode for the definition. Must be one of cache_store::MODE_*
40  *
41  * Optional settings:
42  *     + simplekeys
43  *          [bool] Set to true if your cache will only use simple keys for its items.
44  *          Simple keys consist of digits, underscores and the 26 chars of the english language. a-zA-Z0-9_
45  *          If true the keys won't be hashed before being passed to the cache store for gets/sets/deletes. It will be
46  *          better for performance and possible only becase we know the keys are safe.
47  *     + simpledata
48  *          [bool] If set to true we know that the data is scalar or array of scalar.
49  *     + requireidentifiers
50  *          [array] An array of identifiers that must be provided to the cache when it is created.
51  *     + requiredataguarantee
52  *          [bool] If set to true then only stores that can guarantee data will remain available once set will be used.
53  *     + requiremultipleidentifiers
54  *          [bool] If set to true then only stores that support multiple identifiers will be used.
55  *     + requirelockingread
56  *          [bool] If set to true then a lock will be gained before reading from the cache store. It is recommended not to use
57  *          this setting unless 100% absolutely positively required. Remember 99.9% of caches will NOT need this setting.
58  *          This setting will only be used for application caches presently.
59  *     + requirelockingwrite
60  *          [bool] If set to true then a lock will be gained before writing to the cache store. As above this is not recommended
61  *          unless truly needed. Please think about the order of your code and deal with race conditions there first.
62  *          This setting will only be used for application caches presently.
63  *     + maxsize
64  *          [int] If set this will be used as the maximum number of entries within the cache store for this definition.
65  *          Its important to note that cache stores don't actually have to acknowledge this setting or maintain it as a hard limit.
66  *     + overrideclass
67  *          [string] A class to use as the loader for this cache. This is an advanced setting and will allow the developer of the
68  *          definition to take 100% control of the caching solution.
69  *          Any class used here must inherit the cache_loader interface and must extend default cache loader for the mode they are
70  *          using.
71  *     + overrideclassfile
72  *          [string] Suplements the above setting indicated the file containing the class to be used. This file is included when
73  *          required.
74  *     + datasource
75  *          [string] A class to use as the data loader for this definition.
76  *          Any class used here must inherit the cache_data_loader interface.
77  *     + datasourcefile
78  *          [string] Supplements the above setting indicating the file containing the class to be used. This file is included when
79  *          required.
80  *     + staticacceleration
81  *          The cache loader will keep an array of the items set and retrieved to the cache during the request.
82  *          Consider using this setting when you know that there are going to be many calls to the cache for the same information.
83  *          Requests for data in this array will be ultra fast, but it will cost memory.
84  *     + staticaccelerationsize
85  *          [int] This supplements the above setting by limiting the number of items in the static acceleration array.
86  *          Tweaking this setting lower will allow you to minimise the memory implications above while hopefully still managing to
87  *          offset calls to the cache store.
88  *     + ttl
89  *          [int] A time to live for the data (in seconds). It is strongly recommended that you don't make use of this and
90  *          instead try to create an event driven invalidation system.
91  *          Not all cache stores will support this natively and there are undesired performance impacts if the cache store does not.
92  *     + mappingsonly
93  *          [bool] If set to true only the mapped cache store(s) will be used and the default mode store will not. This is a super
94  *          advanced setting and should not be used unless absolutely required. It allows you to avoid the default stores for one
95  *          reason or another.
96  *     + invalidationevents
97  *          [array] An array of events that should cause this cache to invalidate some or all of the items within it.
98  *     + sharingoptions
99  *          [int] The sharing options that are appropriate for this definition. Should be the sum of the possible options.
100  *     + defaultsharing
101  *          [int] The default sharing option to use. It's highly recommended that you don't set this unless there is a very
102  *          specific reason not to use the system default.
103  *
104  * For examples take a look at lib/db/caches.php
105  *
106  * @package    core
107  * @category   cache
108  * @copyright  2012 Sam Hemelryk
109  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
110  */
111 class cache_definition {
113     /** The cache can be shared with everyone */
114     const SHARING_ALL = 1;
115     /** The cache can be shared with other sites using the same siteid. */
116     const SHARING_SITEID = 2;
117     /** The cache can be shared with other sites of the same version. */
118     const SHARING_VERSION = 4;
119     /** The cache can be shared with other sites using the same key */
120     const SHARING_INPUT = 8;
122     /**
123      * The default sharing options available.
124      * All + SiteID + Version + Input.
125      */
126     const SHARING_DEFAULTOPTIONS = 15;
127     /**
128      * The default sharing option that gets used if none have been selected.
129      * SiteID. It is the most restrictive.
130      */
131     const SHARING_DEFAULT = 2;
133     /**
134      * The identifier for the definition
135      * @var string
136      */
137     protected $id;
139     /**
140      * The mode for the defintion. One of cache_store::MODE_*
141      * @var int
142      */
143     protected $mode;
145     /**
146      * The component this definition is associated with.
147      * @var string
148      */
149     protected $component;
151     /**
152      * The area this definition is associated with.
153      * @var string
154      */
155     protected $area;
157     /**
158      * If set to true we know the keys are simple. a-zA-Z0-9_
159      * @var bool
160      */
161     protected $simplekeys = false;
163     /**
164      * Set to true if we know the data is scalar or array of scalar.
165      * @var bool
166      */
167     protected $simpledata = false;
169     /**
170      * An array of identifiers that must be provided when the definition is used to create a cache.
171      * @var array
172      */
173     protected $requireidentifiers = array();
175     /**
176      * If set to true then only stores that guarantee data may be used with this definition.
177      * @var bool
178      */
179     protected $requiredataguarantee = false;
181     /**
182      * If set to true then only stores that support multple identifiers may be used with this definition.
183      * @var bool
184      */
185     protected $requiremultipleidentifiers = false;
187     /**
188      * If set to true then we know that this definition requires the locking functionality.
189      * This gets set during construction based upon the settings requirelockingread and requirelockingwrite.
190      * @var bool
191      */
192     protected $requirelocking = false;
194     /**
195      * Set to true if this definition requires read locking.
196      * @var bool
197      */
198     protected $requirelockingread = false;
200     /**
201      * Gets set to true if this definition requires write locking.
202      * @var bool
203      */
204     protected $requirelockingwrite = false;
206     /**
207      * Gets set to true if this definition requires searchable stores.
208      * @since 2.4.4
209      * @var bool
210      */
211     protected $requiresearchable = false;
213     /**
214      * Sets the maximum number of items that can exist in the cache.
215      * Please note this isn't a hard limit, and doesn't need to be enforced by the caches. They can choose to do so optionally.
216      * @var int
217      */
218     protected $maxsize = null;
220     /**
221      * The class to use as the cache loader for this definition.
222      * @var string
223      */
224     protected $overrideclass = null;
226     /**
227      * The file in which the override class exists. This will be included if required.
228      * @var string Absolute path
229      */
230     protected $overrideclassfile = null;
232     /**
233      * The data source class to use with this definition.
234      * @var string
235      */
236     protected $datasource = null;
238     /**
239      * The file in which the data source class exists. This will be included if required.
240      * @var string
241      */
242     protected $datasourcefile = null;
244     /**
245      * The data source class aggregate to use. This is a super advanced setting.
246      * @var string
247      */
248     protected $datasourceaggregate = null;
250     /**
251      * Set to true if the cache should hold onto items passing through it to speed up subsequent requests.
252      * @var bool
253      */
254     protected $staticacceleration = false;
256     /**
257      * The maximum number of items that static acceleration cache should hold onto.
258      * @var int
259      */
260     protected $staticaccelerationsize = false;
262     /**
263      * The TTL for data in this cache. Please don't use this, instead use event driven invalidation.
264      * @var int
265      */
266     protected $ttl = 0;
268     /**
269      * Set to true if this cache should only use mapped cache stores and not the default mode cache store.
270      * @var bool
271      */
272     protected $mappingsonly = false;
274     /**
275      * An array of events that should cause this cache to invalidate.
276      * @var array
277      */
278     protected $invalidationevents = array();
280     /**
281      * An array of identifiers provided to this cache when it was initialised.
282      * @var array
283      */
284     protected $identifiers = array();
286     /**
287      * Key prefix for use with single key cache stores
288      * @var string
289      */
290     protected $keyprefixsingle = null;
292     /**
293      * Key prefix to use with cache stores that support multi keys.
294      * @var array
295      */
296     protected $keyprefixmulti = null;
298     /**
299      * A hash identifier of this definition.
300      * @var string
301      */
302     protected $definitionhash = null;
304     /**
305      * The selected sharing mode for this definition.
306      * @var int
307      */
308     protected $sharingoptions;
310     /**
311      * The selected sharing option.
312      * @var int One of self::SHARING_*
313      */
314     protected $selectedsharingoption = self::SHARING_DEFAULT;
316     /**
317      * The user input key to use if the SHARING_INPUT option has been selected.
318      * @var string Must be ALPHANUMEXT
319      */
320     protected $userinputsharingkey = '';
322     /**
323      * Creates a cache definition given a definition from the cache configuration or from a caches.php file.
324      *
325      * @param string $id
326      * @param array $definition
327      * @param string $datasourceaggregate
328      * @return cache_definition
329      * @throws coding_exception
330      */
331     public static function load($id, array $definition, $datasourceaggregate = null) {
332         global $CFG;
334         if (!array_key_exists('mode', $definition)) {
335             throw new coding_exception('You must provide a mode when creating a cache definition');
336         }
337         if (!array_key_exists('component', $definition)) {
338             throw new coding_exception('You must provide a component when creating a cache definition');
339         }
340         if (!array_key_exists('area', $definition)) {
341             throw new coding_exception('You must provide an area when creating a cache definition');
342         }
343         $mode = (int)$definition['mode'];
344         $component = (string)$definition['component'];
345         $area = (string)$definition['area'];
347         // Set the defaults.
348         $simplekeys = false;
349         $simpledata = false;
350         $requireidentifiers = array();
351         $requiredataguarantee = false;
352         $requiremultipleidentifiers = false;
353         $requirelockingread = false;
354         $requirelockingwrite = false;
355         $requiresearchable = ($mode === cache_store::MODE_SESSION) ? true : false;
356         $maxsize = null;
357         $overrideclass = null;
358         $overrideclassfile = null;
359         $datasource = null;
360         $datasourcefile = null;
361         $staticacceleration = false;
362         $staticaccelerationsize = false;
363         $ttl = 0;
364         $mappingsonly = false;
365         $invalidationevents = array();
366         $sharingoptions = self::SHARING_DEFAULT;
367         $selectedsharingoption = self::SHARING_DEFAULT;
368         $userinputsharingkey = '';
370         if (array_key_exists('simplekeys', $definition)) {
371             $simplekeys = (bool)$definition['simplekeys'];
372         }
373         if (array_key_exists('simpledata', $definition)) {
374             $simpledata = (bool)$definition['simpledata'];
375         }
376         if (array_key_exists('requireidentifiers', $definition)) {
377             $requireidentifiers = (array)$definition['requireidentifiers'];
378         }
379         if (array_key_exists('requiredataguarantee', $definition)) {
380             $requiredataguarantee = (bool)$definition['requiredataguarantee'];
381         }
382         if (array_key_exists('requiremultipleidentifiers', $definition)) {
383             $requiremultipleidentifiers = (bool)$definition['requiremultipleidentifiers'];
384         }
386         if (array_key_exists('requirelockingread', $definition)) {
387             $requirelockingread = (bool)$definition['requirelockingread'];
388         }
389         if (array_key_exists('requirelockingwrite', $definition)) {
390             $requirelockingwrite = (bool)$definition['requirelockingwrite'];
391         }
392         $requirelocking = $requirelockingwrite || $requirelockingread;
394         if (array_key_exists('requiresearchable', $definition)) {
395             $requiresearchable = (bool)$definition['requiresearchable'];
396         }
398         if (array_key_exists('maxsize', $definition)) {
399             $maxsize = (int)$definition['maxsize'];
400         }
402         if (array_key_exists('overrideclass', $definition)) {
403             $overrideclass = $definition['overrideclass'];
404         }
405         if (array_key_exists('overrideclassfile', $definition)) {
406             $overrideclassfile = $definition['overrideclassfile'];
407         }
409         if (array_key_exists('datasource', $definition)) {
410             $datasource = $definition['datasource'];
411         }
412         if (array_key_exists('datasourcefile', $definition)) {
413             $datasourcefile = $definition['datasourcefile'];
414         }
416         if (array_key_exists('persistent', $definition)) {
417             // Ahhh this is the legacy persistent option.
418             $staticacceleration = (bool)$definition['persistent'];
419         }
420         if (array_key_exists('staticacceleration', $definition)) {
421             $staticacceleration = (bool)$definition['staticacceleration'];
422         }
423         if (array_key_exists('persistentmaxsize', $definition)) {
424             // Ahhh this is the legacy persistentmaxsize option.
425             $staticaccelerationsize = (int)$definition['persistentmaxsize'];
426         }
427         if (array_key_exists('staticaccelerationsize', $definition)) {
428             $staticaccelerationsize = (int)$definition['staticaccelerationsize'];
429         }
430         if (array_key_exists('ttl', $definition)) {
431             $ttl = (int)$definition['ttl'];
432         }
433         if (array_key_exists('mappingsonly', $definition)) {
434             $mappingsonly = (bool)$definition['mappingsonly'];
435         }
436         if (array_key_exists('invalidationevents', $definition)) {
437             $invalidationevents = (array)$definition['invalidationevents'];
438         }
439         if (array_key_exists('sharingoptions', $definition)) {
440             $sharingoptions = (int)$definition['sharingoptions'];
441         }
442         if (array_key_exists('selectedsharingoption', $definition)) {
443             $selectedsharingoption = (int)$definition['selectedsharingoption'];
444         } else if (array_key_exists('defaultsharing', $definition)) {
445             $selectedsharingoption = (int)$definition['defaultsharing'];
446         } else if ($sharingoptions ^ $selectedsharingoption) {
447             if ($sharingoptions & self::SHARING_SITEID) {
448                 $selectedsharingoption = self::SHARING_SITEID;
449             } else if ($sharingoptions & self::SHARING_VERSION) {
450                 $selectedsharingoption = self::SHARING_VERSION;
451             } else {
452                 $selectedsharingoption = self::SHARING_ALL;
453             }
454         }
456         if (array_key_exists('userinputsharingkey', $definition) && !empty($definition['userinputsharingkey'])) {
457             $userinputsharingkey = (string)$definition['userinputsharingkey'];
458         }
460         if (!is_null($overrideclass)) {
461             if (!is_null($overrideclassfile)) {
462                 if (strpos($overrideclassfile, $CFG->dirroot) !== 0) {
463                     $overrideclassfile = $CFG->dirroot.'/'.$overrideclassfile;
464                 }
465                 if (strpos($overrideclassfile, '../') !== false) {
466                     throw new coding_exception('No path craziness allowed within override class file path.');
467                 }
468                 if (!file_exists($overrideclassfile)) {
469                     throw new coding_exception('The override class file does not exist.');
470                 }
471                 require_once($overrideclassfile);
472             }
473             if (!class_exists($overrideclass)) {
474                 throw new coding_exception('The override class does not exist.');
475             }
477             // Make sure that the provided class extends the default class for the mode.
478             if (get_parent_class($overrideclass) !== cache_helper::get_class_for_mode($mode)) {
479                 throw new coding_exception('The override class does not immediately extend the relevant cache class.');
480             }
481         }
483         if (!is_null($datasource)) {
484             if (!is_null($datasourcefile)) {
485                 if (strpos($datasourcefile, $CFG->dirroot) !== 0) {
486                     $datasourcefile = $CFG->dirroot.'/'.$datasourcefile;
487                 }
488                 if (strpos($datasourcefile, '../') !== false) {
489                     throw new coding_exception('No path craziness allowed within data source file path.');
490                 }
491                 if (!file_exists($datasourcefile)) {
492                     throw new coding_exception('The data source class file does not exist.');
493                 }
494                 require_once($datasourcefile);
495             }
496             if (!class_exists($datasource)) {
497                 throw new coding_exception('The data source class does not exist.');
498             }
499             if (!array_key_exists('cache_data_source', class_implements($datasource))) {
500                 throw new coding_exception('Cache data source classes must implement the cache_data_source interface');
501             }
502         }
504         $cachedefinition = new cache_definition();
505         $cachedefinition->id = $id;
506         $cachedefinition->mode = $mode;
507         $cachedefinition->component = $component;
508         $cachedefinition->area = $area;
509         $cachedefinition->simplekeys = $simplekeys;
510         $cachedefinition->simpledata = $simpledata;
511         $cachedefinition->requireidentifiers = $requireidentifiers;
512         $cachedefinition->requiredataguarantee = $requiredataguarantee;
513         $cachedefinition->requiremultipleidentifiers = $requiremultipleidentifiers;
514         $cachedefinition->requirelocking = $requirelocking;
515         $cachedefinition->requirelockingread = $requirelockingread;
516         $cachedefinition->requirelockingwrite = $requirelockingwrite;
517         $cachedefinition->requiresearchable = $requiresearchable;
518         $cachedefinition->maxsize = $maxsize;
519         $cachedefinition->overrideclass = $overrideclass;
520         $cachedefinition->overrideclassfile = $overrideclassfile;
521         $cachedefinition->datasource = $datasource;
522         $cachedefinition->datasourcefile = $datasourcefile;
523         $cachedefinition->datasourceaggregate = $datasourceaggregate;
524         $cachedefinition->staticacceleration = $staticacceleration;
525         $cachedefinition->staticaccelerationsize = $staticaccelerationsize;
526         $cachedefinition->ttl = $ttl;
527         $cachedefinition->mappingsonly = $mappingsonly;
528         $cachedefinition->invalidationevents = $invalidationevents;
529         $cachedefinition->sharingoptions = $sharingoptions;
530         $cachedefinition->selectedsharingoption = $selectedsharingoption;
531         $cachedefinition->userinputsharingkey = $userinputsharingkey;
533         return $cachedefinition;
534     }
536     /**
537      * Creates an ah-hoc cache definition given the required params.
538      *
539      * Please note that when using an adhoc definition you cannot set any of the optional params.
540      * This is because we cannot guarantee consistent access and we don't want to mislead people into thinking that.
541      *
542      * @param int $mode One of cache_store::MODE_*
543      * @param string $component The component this definition relates to.
544      * @param string $area The area this definition relates to.
545      * @param array $options An array of options, available options are:
546      *   - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
547      *   - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
548      *   - overrideclass : The class to use as the loader.
549      *   - staticacceleration : If set to true the cache will hold onto data passing through it.
550      *   - staticaccelerationsize : Set it to an int to limit the size of the staticacceleration cache.
551      * @return cache_application|cache_session|cache_request
552      */
553     public static function load_adhoc($mode, $component, $area, array $options = array()) {
554         $id = 'adhoc/'.$component.'_'.$area;
555         $definition = array(
556             'mode' => $mode,
557             'component' => $component,
558             'area' => $area,
559         );
560         if (!empty($options['simplekeys'])) {
561             $definition['simplekeys'] = $options['simplekeys'];
562         }
563         if (!empty($options['simpledata'])) {
564             $definition['simpledata'] = $options['simpledata'];
565         }
566         if (!empty($options['persistent'])) {
567             // Ahhh this is the legacy persistent option.
568             $definition['staticacceleration'] = (bool)$options['persistent'];
569         }
570         if (!empty($options['staticacceleration'])) {
571             $definition['staticacceleration'] = (bool)$options['staticacceleration'];
572         }
573         if (!empty($options['staticaccelerationsize'])) {
574             $definition['staticaccelerationsize'] = (int)$options['staticaccelerationsize'];
575         }
576         if (!empty($options['overrideclass'])) {
577             $definition['overrideclass'] = $options['overrideclass'];
578         }
579         if (!empty($options['sharingoptions'])) {
580             $definition['sharingoptions'] = $options['sharingoptions'];
581         }
582         return self::load($id, $definition, null);
583     }
585     /**
586      * Returns the cache loader class that should be used for this definition.
587      * @return string
588      */
589     public function get_cache_class() {
590         if (!is_null($this->overrideclass)) {
591             return $this->overrideclass;
592         }
593         return cache_helper::get_class_for_mode($this->mode);
594     }
596     /**
597      * Returns the id of this definition.
598      * @return string
599      */
600     public function get_id() {
601         return $this->id;
602     }
604     /**
605      * Returns the name for this definition
606      * @return string
607      */
608     public function get_name() {
609         $identifier = 'cachedef_'.clean_param($this->area, PARAM_STRINGID);
610         $component = $this->component;
611         if ($component === 'core') {
612             $component = 'cache';
613         }
614         return new lang_string($identifier, $component);
615     }
617     /**
618      * Returns the mode of this definition
619      * @return int One more cache_store::MODE_
620      */
621     public function get_mode() {
622         return $this->mode;
623     }
625     /**
626      * Returns the area this definition is associated with.
627      * @return string
628      */
629     public function get_area() {
630         return $this->area;
631     }
633     /**
634      * Returns the component this definition is associated with.
635      * @return string
636      */
637     public function get_component() {
638         return $this->component;
639     }
641     /**
642      * Returns true if this definition is using simple keys.
643      *
644      * Simple keys contain only a-zA-Z0-9_
645      *
646      * @return bool
647      */
648     public function uses_simple_keys() {
649         return $this->simplekeys;
650     }
652     /**
653      * Returns the identifiers that are being used for this definition.
654      * @return array
655      */
656     public function get_identifiers() {
657         return $this->identifiers;
658     }
660     /**
661      * Returns the ttl in seconds for this definition if there is one, or null if not.
662      * @return int|null
663      */
664     public function get_ttl() {
665         return $this->ttl;
666     }
668     /**
669      * Returns the maximum number of items allowed in this cache.
670      * @return int
671      */
672     public function get_maxsize() {
673         return $this->maxsize;
674     }
676     /**
677      * Returns true if this definition should only be used with mappings.
678      * @return bool
679      */
680     public function is_for_mappings_only() {
681         return $this->mappingsonly;
682     }
684     /**
685      * Returns true if the data is known to be scalar or array of scalar.
686      * @return bool
687      */
688     public function uses_simple_data() {
689         return $this->simpledata;
690     }
692     /**
693      * Returns true if this definition requires a data guarantee from the cache stores being used.
694      * @return bool
695      */
696     public function require_data_guarantee() {
697         return $this->requiredataguarantee;
698     }
700     /**
701      * Returns true if this definition requires that the cache stores support multiple identifiers
702      * @return bool
703      */
704     public function require_multiple_identifiers() {
705         return $this->requiremultipleidentifiers;
706     }
708     /**
709      * Returns true if this definition requires locking functionality. Either read or write locking.
710      * @return bool
711      */
712     public function require_locking() {
713         return $this->requirelocking;
714     }
716     /**
717      * Returns true if this definition requires read locking.
718      * @return bool
719      */
720     public function require_locking_read() {
721         return $this->requirelockingread;
722     }
724     /**
725      * Returns true if this definition requires write locking.
726      * @return bool
727      */
728     public function require_locking_write() {
729         return $this->requirelockingwrite;
730     }
732     /**
733      * Returns true if this definition requires a searchable cache.
734      * @since 2.4.4
735      * @return bool
736      */
737     public function require_searchable() {
738         return $this->requiresearchable;
739     }
741     /**
742      * Returns true if this definition has an associated data source.
743      * @return bool
744      */
745     public function has_data_source() {
746         return !is_null($this->datasource);
747     }
749     /**
750      * Returns an instance of the data source class used for this definition.
751      *
752      * @return cache_data_source
753      * @throws coding_exception
754      */
755     public function get_data_source() {
756         if (!$this->has_data_source()) {
757             throw new coding_exception('This cache does not use a data source.');
758         }
759         return forward_static_call(array($this->datasource, 'get_instance_for_cache'), $this);
760     }
762     /**
763      * Sets the identifiers for this definition, or updates them if they have already been set.
764      *
765      * @param array $identifiers
766      * @throws coding_exception
767      */
768     public function set_identifiers(array $identifiers = array()) {
769         foreach ($this->requireidentifiers as $identifier) {
770             if (!isset($identifiers[$identifier])) {
771                 throw new coding_exception('Identifier required for cache has not been provided: '.$identifier);
772             }
773         }
774         foreach ($identifiers as $name => $value) {
775             $this->identifiers[$name] = (string)$value;
776         }
777         // Reset the key prefix's they need updating now.
778         $this->keyprefixsingle = null;
779         $this->keyprefixmulti = null;
780     }
782     /**
783      * Returns the requirements of this definition as a binary flag.
784      * @return int
785      */
786     public function get_requirements_bin() {
787         $requires = 0;
788         if ($this->require_data_guarantee()) {
789             $requires += cache_store::SUPPORTS_DATA_GUARANTEE;
790         }
791         if ($this->require_multiple_identifiers()) {
792             $requires += cache_store::SUPPORTS_MULTIPLE_IDENTIFIERS;
793         }
794         if ($this->require_searchable()) {
795             $requires += cache_store::IS_SEARCHABLE;
796         }
797         return $requires;
798     }
800     /**
801      * Returns true if this definitions cache should be made persistent.
802      *
803      * Please call {@link cache_definition::use_static_acceleration()} instead.
804      *
805      * @see cache_definition::use_static_acceleration()
806      * @deprecated since 2.6
807      * @return bool
808      */
809     public function should_be_persistent() {
810         debugging('Please upgrade your code to use cache_definition::use_static_acceleration', DEBUG_DEVELOPER);
811         return $this->use_static_acceleration();
812     }
814     /**
815      * Returns true if we should hold onto the data flowing through the cache.
816      *
817      * If set to true data flowing through the cache will be stored in a static variable
818      * to make subsequent requests for the data much faster.
819      *
820      * @return bool
821      */
822     public function use_static_acceleration() {
823         if ($this->mode === cache_store::MODE_REQUEST) {
824             // Request caches should never use static acceleration - it just doesn't make sense.
825             return false;
826         }
827         return $this->staticacceleration;
828     }
830     /**
831      * Returns the max size for the static acceleration array.
832      *
833      * Please call {@link cache_definition::get_static_acceleration_size()} instead.
834      *
835      * @see cache_definition::get_static_acceleration_size()
836      * @deprecated since 2.6
837      * @return int
838      */
839     public function get_persistent_max_size() {
840         debugging('Please upgrade your code to call cache_definition::get_static_acceleration_size', DEBUG_DEVELOPER);
841         return $this->get_static_acceleration_size();
842     }
844     /**
845      * Returns the max size for the static acceleration array.
846      * @return int
847      */
848     public function get_static_acceleration_size() {
849         return $this->staticaccelerationsize;
850     }
852     /**
853      * Generates a hash of this definition and returns it.
854      * @return string
855      */
856     public function generate_definition_hash() {
857         if ($this->definitionhash === null) {
858             $this->definitionhash = md5("{$this->mode} {$this->component} {$this->area}");
859         }
860         return $this->definitionhash;
861     }
863     /**
864      * Generates a single key prefix for this definition
865      *
866      * @return string
867      */
868     public function generate_single_key_prefix() {
869         if ($this->keyprefixsingle === null) {
870             $this->keyprefixsingle = $this->mode.'/'.$this->component.'/'.$this->area;
871             $this->keyprefixsingle .= '/'.$this->get_cache_identifier();
872             $identifiers = $this->get_identifiers();
873             if ($identifiers) {
874                 foreach ($identifiers as $key => $value) {
875                     $this->keyprefixsingle .= '/'.$key.'='.$value;
876                 }
877             }
878             $this->keyprefixsingle = md5($this->keyprefixsingle);
879         }
880         return $this->keyprefixsingle;
881     }
883     /**
884      * Generates a multi key prefix for this definition
885      *
886      * @return array
887      */
888     public function generate_multi_key_parts() {
889         if ($this->keyprefixmulti === null) {
890             $this->keyprefixmulti = array(
891                 'mode' => $this->mode,
892                 'component' => $this->component,
893                 'area' => $this->area,
894                 'siteidentifier' => $this->get_cache_identifier()
895             );
896             if (!empty($this->identifiers)) {
897                 $identifiers = array();
898                 foreach ($this->identifiers as $key => $value) {
899                     $identifiers[] = htmlentities($key, ENT_QUOTES, 'UTF-8').'='.htmlentities($value, ENT_QUOTES, 'UTF-8');
900                 }
901                 $this->keyprefixmulti['identifiers'] = join('&', $identifiers);
902             }
903         }
904         return $this->keyprefixmulti;
905     }
907     /**
908      * Check if this definition should invalidate on the given event.
909      *
910      * @param string $event
911      * @return bool True if the definition should invalidate on the event. False otherwise.
912      */
913     public function invalidates_on_event($event) {
914         return (in_array($event, $this->invalidationevents));
915     }
917     /**
918      * Check if the definition has any invalidation events.
919      *
920      * @return bool True if it does, false otherwise
921      */
922     public function has_invalidation_events() {
923         return !empty($this->invalidationevents);
924     }
926     /**
927      * Returns all of the invalidation events for this definition.
928      *
929      * @return array
930      */
931     public function get_invalidation_events() {
932         return $this->invalidationevents;
933     }
935     /**
936      * Returns a cache identification string.
937      *
938      * @return string A string to be used as part of keys.
939      */
940     protected function get_cache_identifier() {
941         $identifiers = array();
942         if ($this->selectedsharingoption & self::SHARING_ALL) {
943             // Nothing to do here.
944         } else {
945             if ($this->selectedsharingoption & self::SHARING_SITEID) {
946                 $identifiers[] = cache_helper::get_site_identifier();
947             }
948             if ($this->selectedsharingoption & self::SHARING_VERSION) {
949                 $identifiers[] = cache_helper::get_site_version();
950             }
951             if ($this->selectedsharingoption & self::SHARING_INPUT && !empty($this->userinputsharingkey)) {
952                 $identifiers[] = $this->userinputsharingkey;
953             }
954         }
955         return join('/', $identifiers);
956     }
958     /**
959      * Returns true if this definition requires identifiers.
960      *
961      * @param bool
962      */
963     public function has_required_identifiers() {
964         return (count($this->requireidentifiers) > 0);
965     }