Permalink
Browse files

$MACHE: add support for eaccelerator/memcached, change the $MCACHE ca…

…lling convention a bit

 - this effectively breaks memcached support for the moment
  • Loading branch information...
martinlanghoff
martinlanghoff committed Dec 27, 2006
1 parent 3530015 commit 2142d4924f6303dca2609d0ff90d4902e038e0eb
Showing with 147 additions and 0 deletions.
  1. +130 −0 lib/eaccelerator.class.php
  2. +3 −0 lib/setup.php
  3. +14 −0 lib/setuplib.php
View
@@ -0,0 +1,130 @@
+<?php
+/**
+ ** This class abstracts eaccelerator/turckmmcache
+ ** API to provide
+ **
+ ** - get()
+ ** - set()
+ ** - delete()
+ ** - getforfill()
+ ** - releaseforfill()
+ **
+ ** Author: Martin Langhoff <martin@catalyst.net.nz>
+ **
+ **/
+
+
+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');
+ }
+}
+
+?>
View
@@ -261,6 +261,9 @@
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)) {
View
@@ -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;
+}
+
+
+
?>

0 comments on commit 2142d49

Please sign in to comment.