3 // This file is part of Moodle - http://moodle.org/
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
19 * This class abstracts eaccelerator/turckmmcache
28 * Note: do NOT store booleans here. For compatibility with
29 * memcached, a false value is indistinguisable from a
30 * "not found in cache" response.
34 * @copyright Martin Langhoff <martin@catalyst.net.nz>
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 defined('MOODLE_INTERNAL') ||
die();
42 * @copyright Martin Langhoff <martin@catalyst.net.nz>
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
49 * @todo Document this function
53 function eaccelerator() {
55 if ( function_exists('eaccelerator_get')) {
56 $this->mode
= 'eaccelerator';
57 } elseif (function_exists('mmcache_get')) {
58 $this->mode
= 'mmcache';
60 debugging("\$CFG->eaccelerator is set to true but the required functions are not available. You need to have either eaccelerator or turckmmcache extensions installed, compiled with the shmem keys option enabled.");
63 $this->prefix
= $CFG->dbname
.'|' . $CFG->prefix
. '|';
67 * The status of the eaccelerator, if it has been established
68 * this will return true
73 if (isset($this->mode
)) {
80 * @todo Document this function
83 * @param string $value
87 function set($key, $value, $ttl=0) {
88 $set = $this->mode
. '_put';
89 $unlock = $this->mode
. '_unlock';
91 // we may have acquired a lock via getforfill
92 // release if it exists
93 @$unlock($this->prefix
. $key . '_forfill');
95 return $set($this->prefix
. $key, serialize($value), $ttl);
99 * @todo Document this function
102 * @return string|bool String if success else false
105 $fn = $this->mode
. '_get';
106 $rec = $fn($this->prefix
. $key);
110 return unserialize($rec);
114 * @todo Document this function
119 function delete($key) {
120 $fn = $this->mode
. '_rm';
121 return $fn($this->prefix
. $key);
125 * In the simple case, this function will
126 * get the cached value if available. If the entry
127 * is not cached, it will try to get an exclusive
128 * lock that announces that this process will
129 * populate the cache.
131 * If we fail to get the lock -- this means another
132 * process is doing it.
133 * so we wait (block) for a few microseconds while we wait for
134 * the cache to be filled or the lock to timeout.
136 * If you get a false from this call, you _must_
137 * populate the cache ASAP or indicate that
138 * you won't by calling releaseforfill().
140 * This technique forces serialisation and so helps deal
141 * with thundering herd scenarios where a lot of clients
142 * ask the for the same idempotent (and costly) operation.
143 * The implementation is based on suggestions in this message
144 * http://marc.theaimsgroup.com/?l=git&m=116562052506776&w=2
147 * @return mixed on cache hit, false otherwise
149 function getforfill ($key) {
150 $get = $this->mode
. '_get';
151 $lock = $this->mode
. '_lock';
153 $rec = $get($this->prefix
. $key);
154 if (!is_null($rec)) {
155 return unserialize($rec);
157 if ($lock($this->prefix
. $key . '_forfill')) {
158 // we obtained the _forfill lock
159 // our caller will compute and set the value
162 // someone else has the lock
163 // "block" till we can get the value
164 // actually, loop .05s waiting for it
165 for ($n=0;$n<5;$n++
) {
167 $rec = $get($this->prefix
. $key);
168 if (!is_null($rec)) {
169 return unserialize($rec);
176 * Release the exclusive lock obtained by
177 * getforfill(). See getforfill()
183 function releaseforfill ($key) {
184 $unlock = $this->mode
. '_unlock';
185 return $unlock($this->prefix
. $key . '_forfill');