[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/ -> eaccelerator.class.php (source)

   1  <?php
   2  /**
   3   ** This class abstracts eaccelerator/turckmmcache
   4   ** API to provide
   5   ** 
   6   ** - get()
   7   ** - set()
   8   ** - delete()
   9   ** - getforfill()
  10   ** - releaseforfill()
  11   **
  12   ** Author: Martin Langhoff <martin@catalyst.net.nz>
  13   **
  14   ** Note: do NOT store booleans here. For compatibility with
  15   ** memcached, a false value is indistinguisable from a 
  16   ** "not found in cache" response.
  17   **/
  18  
  19  
  20  class eaccelerator {
  21  
  22      function eaccelerator() {
  23          global $CFG;
  24          if ( function_exists('eaccelerator_get')) {
  25              $this->mode = 'eaccelerator';
  26          } elseif (function_exists('mmcache_get')) {
  27              $this->mode = 'mmcache';
  28          } else {
  29              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.");
  30          }
  31  
  32          $this->prefix = $CFG->dbname .'|' . $CFG->prefix . '|';
  33      }
  34  
  35      function status() {
  36          if (isset($this->mode)) {
  37              return true;
  38          }
  39          return false;
  40      }
  41  
  42      function set($key, $value, $ttl=0) {
  43          $set    = $this->mode . '_put';
  44          $unlock = $this->mode . '_unlock';
  45  
  46          // we may have acquired a lock via getforfill
  47          // release if it exists
  48          @$unlock($this->prefix . $key . '_forfill');
  49  
  50          return $set($this->prefix . $key, serialize($value), $ttl);
  51      }
  52  
  53      function get($key) {
  54          $fn = $this->mode . '_get';
  55          $rec = $fn($this->prefix . $key);
  56          if (is_null($rec)) {
  57              return false;
  58          }
  59          return unserialize($rec);
  60      } 
  61          
  62      function delete($key) {
  63          $fn = $this->mode . '_rm';
  64          return $fn($this->prefix . $key);
  65      }
  66  
  67      /**
  68       * In the simple case, this function will 
  69       * get the cached value if available. If the entry
  70       * is not cached, it will try to get an exclusive
  71       * lock that announces that this process will
  72       * populate the cache.
  73       *
  74       * If we fail to get the lock -- this means another
  75       * process is doing it. 
  76       * so we wait (block) for a few microseconds while we wait for
  77       * the cache to be filled or the lock to timeout.
  78       * 
  79       * If you get a false from this call, you _must_
  80       * populate the cache ASAP or indicate that
  81       * you won't by calling releaseforfill().
  82       *
  83       * This technique forces serialisation and so helps deal 
  84       * with thundering herd scenarios where a lot of clients 
  85       * ask the for the same idempotent (and costly) operation. 
  86       * The implementation is based on suggestions in this message
  87       * http://marc.theaimsgroup.com/?l=git&m=116562052506776&w=2
  88       *
  89       * @param $key string
  90       * @return mixed on cache hit, false otherwise
  91       */
  92      function getforfill ($key) {
  93          $get    = $this->mode . '_get';
  94          $lock   = $this->mode . '_lock';
  95          
  96          $rec = $get($this->prefix . $key);
  97          if (!is_null($rec)) {
  98              return unserialize($rec);
  99          }
 100          if ($lock($this->prefix . $key . '_forfill')) {
 101              // we obtained the _forfill lock
 102              // our caller will compute and set the value
 103              return false;
 104          }
 105          // someone else has the lock
 106          // "block" till we can get the value
 107          // actually, loop .05s waiting for it
 108          for ($n=0;$n<5;$n++) {
 109              usleep(10000);
 110              $rec = $get($this->prefix . $key);
 111              if (!is_null($rec)) {
 112                  return unserialize($rec);
 113              }
 114          }
 115          return false;
 116      }
 117  
 118      /**
 119       * Release the exclusive lock obtained by 
 120       * getforfill(). See getforfill()
 121       * for more details.
 122       *
 123       * @param $key string
 124       * @return bool
 125       */
 126      function releaseforfill ($key) {
 127          $unlock = $this->mode . '_unlock';
 128          return $unlock($this->prefix . $key . '_forfill');
 129      }
 130  }
 131  
 132  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7