From 2142d4924f6303dca2609d0ff90d4902e038e0eb Mon Sep 17 00:00:00 2001 From: martinlanghoff Date: Wed, 27 Dec 2006 22:47:14 +0000 Subject: [PATCH] $MACHE: add support for eaccelerator/memcached, change the $MCACHE calling convention a bit - this effectively breaks memcached support for the moment --- lib/eaccelerator.class.php | 130 +++++++++++++++++++++++++++++++++++++ lib/setup.php | 3 + lib/setuplib.php | 14 ++++ 3 files changed, 147 insertions(+) create mode 100644 lib/eaccelerator.class.php diff --git a/lib/eaccelerator.class.php b/lib/eaccelerator.class.php new file mode 100644 index 00000000000..d07f0ee67b6 --- /dev/null +++ b/lib/eaccelerator.class.php @@ -0,0 +1,130 @@ + + ** + **/ + + +class eaccelerator { + + function eaccelerator() { + global $CFG; + if ( function_exists('eaccelerator_get')) { + $mode = 'eaccelerator'; + } elseif (function_exists('mmcache_get')) { + $mode = 'mmcache'; + } else { + 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."); + } + + $this->mode = $mode; + $this->prefix = $CFG->dbname .'|' . $CFG->prefix . '|'; + } + + function status() { + if (isset($this->mode)) { + return true; + } + return false; + } + + function set($key, $value, $ttl=0) { + $set = $this->mode . '_put'; + $unlock = $this->mode . '_unlock'; + + // we may have acquired a lock via getforfill + // release if it exists + @$unlock($this->prefix . $key . '_forfill'); + + return $set($this->prefix . $key, serialize($value), $ttl); + } + + function get($key) { + $fn = $this->mode . '_get'; + $rec = $fn($this->prefix . $key); + if (is_null($rec)) { + return null; + } + return unserialize($rec); + } + + function delete($key) { + $fn = $this->mode . '_rm'; + return $fn($this->prefix . $key); + } + + /** + * In the simple case, this function will + * get the cached value if available. If the entry + * is not cached, it will try to get an exclusive + * lock that announces that this process will + * populate the cache. + * + * If we fail to get the lock -- this means another + * process is doing it. + * so we wait (block) for a few microseconds while we wait for + * the cache to be filled or the lock to timeout. + * + * If you get a false from this call, you _must_ + * populate the cache ASAP or indicate that + * you won't by calling releaseforfill(). + * + * This technique forces serialisation and so helps deal + * with thundering herd scenarios where a lot of clients + * ask the for the same idempotent (and costly) operation. + * The implementation is based on suggestions in this message + * http://marc.theaimsgroup.com/?l=git&m=116562052506776&w=2 + * + * @param $key string + * @return mixed on cache hit, NULL otherwise + */ + function getforfill ($key) { + $get = $this->mode . '_get'; + $lock = $this->mode . '_lock'; + + $rec = $get($this->prefix . $key); + if (!is_null($rec)) { + return unserialize($rec); + } + if ($lock($this->prefix . $key . '_forfill')) { + // we obtained the _forfill lock + // our caller will compute and set the value + return null; + } + // someone else has the lock + // "block" till we can get the value + // actually, loop .05s waiting for it + for ($n=0;$n<5;$n++) { + usleep(10000); + $rec = $get($this->prefix . $key); + if (!is_null($rec)) { + return unserialize($rec); + } + } + return null; + } + + /** + * Release the exclusive lock obtained by + * getforfill(). See getforfill() + * for more details. + * + * @param $key string + * @return bool + */ + function releaseforfill ($key) { + $unlock = $this->mode . '_unlock'; + return $unlock($this->prefix . $key . '_forfill'); + } +} + +?> \ No newline at end of file diff --git a/lib/setup.php b/lib/setup.php index fff6683b00d..eae03dd8a6a 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -261,6 +261,9 @@ global $HTTPSPAGEREQUIRED; if (!empty($CFG->memcached) && !empty($CFG->memcachedhosts)) { init_memcached(); } + if (!empty($CFG->eaccelerator)) { + init_eaccelerator(); + } /// Set a default enrolment configuration (see bug 1598) if (!isset($CFG->enrol)) { diff --git a/lib/setuplib.php b/lib/setuplib.php index 2fe294a30a6..dd7a43fa472 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -236,4 +236,18 @@ function init_memcached() { return true; } +function init_eaccelerator() { + global $CFG, $MCACHE; + + include_once($CFG->libdir . '/eaccelerator.class.php'); + $MCACHE = new eaccelerator; + if ($MCACHE->status) { + return true; + } + unset($MCACHE); + return false; +} + + + ?>