Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 400 and 402] [Versions 400 and 403]

   1  <?php
   2  /*
   3   * Copyright 2008 Google Inc.
   4   *
   5   * Licensed under the Apache License, Version 2.0 (the "License");
   6   * you may not use this file except in compliance with the License.
   7   * You may obtain a copy of the License at
   8   *
   9   *     http://www.apache.org/licenses/LICENSE-2.0
  10   *
  11   * Unless required by applicable law or agreed to in writing, software
  12   * distributed under the License is distributed on an "AS IS" BASIS,
  13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14   * See the License for the specific language governing permissions and
  15   * limitations under the License.
  16   */
  17  
  18  if (!class_exists('Google_Client')) {
  19    require_once dirname(__FILE__) . '/../autoload.php';
  20  }
  21  
  22  /**
  23   * A persistent storage class based on the memcache, which is not
  24   * really very persistent, as soon as you restart your memcache daemon
  25   * the storage will be wiped.
  26   *
  27   * Will use either the memcache or memcached extensions, preferring
  28   * memcached.
  29   *
  30   * @author Chris Chabot <chabotc@google.com>
  31   */
  32  class Google_Cache_Memcache extends Google_Cache_Abstract
  33  {
  34    private $connection = false;
  35    private $mc = false;
  36    private $host;
  37    private $port;
  38  
  39    /**
  40     * @var Google_Client the current client
  41     */
  42    private $client;
  43  
  44    public function __construct(Google_Client $client)
  45    {
  46      if (!function_exists('memcache_connect') && !class_exists("Memcached")) {
  47        $error = "Memcache functions not available";
  48  
  49        $client->getLogger()->error($error);
  50        throw new Google_Cache_Exception($error);
  51      }
  52  
  53      $this->client = $client;
  54  
  55      if ($client->isAppEngine()) {
  56        // No credentials needed for GAE.
  57        $this->mc = new Memcached();
  58        $this->connection = true;
  59      } else {
  60        $this->host = $client->getClassConfig($this, 'host');
  61        $this->port = $client->getClassConfig($this, 'port');
  62        if (empty($this->host) || (empty($this->port) && (string) $this->port != "0")) {
  63          $error = "You need to supply a valid memcache host and port";
  64  
  65          $client->getLogger()->error($error);
  66          throw new Google_Cache_Exception($error);
  67        }
  68      }
  69    }
  70  
  71    /**
  72     * @inheritDoc
  73     */
  74    public function get($key, $expiration = false)
  75    {
  76      $this->connect();
  77      $ret = false;
  78      if ($this->mc) {
  79        $ret = $this->mc->get($key);
  80      } else {
  81        $ret = memcache_get($this->connection, $key);
  82      }
  83      if ($ret === false) {
  84        $this->client->getLogger()->debug(
  85            'Memcache cache miss',
  86            array('key' => $key)
  87        );
  88        return false;
  89      }
  90      if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
  91        $this->client->getLogger()->debug(
  92            'Memcache cache miss (expired)',
  93            array('key' => $key, 'var' => $ret)
  94        );
  95        $this->delete($key);
  96        return false;
  97      }
  98  
  99      $this->client->getLogger()->debug(
 100          'Memcache cache hit',
 101          array('key' => $key, 'var' => $ret)
 102      );
 103  
 104      return $ret['data'];
 105    }
 106  
 107    /**
 108     * @inheritDoc
 109     * @param string $key
 110     * @param string $value
 111     * @throws Google_Cache_Exception
 112     */
 113    public function set($key, $value)
 114    {
 115      $this->connect();
 116      // we store it with the cache_time default expiration so objects will at
 117      // least get cleaned eventually.
 118      $data = array('time' => time(), 'data' => $value);
 119      $rc = false;
 120      if ($this->mc) {
 121        $rc = $this->mc->set($key, $data);
 122      } else {
 123        $rc = memcache_set($this->connection, $key, $data, false);
 124      }
 125      if ($rc == false) {
 126        $this->client->getLogger()->error(
 127            'Memcache cache set failed',
 128            array('key' => $key, 'var' => $data)
 129        );
 130  
 131        throw new Google_Cache_Exception("Couldn't store data in cache");
 132      }
 133  
 134      $this->client->getLogger()->debug(
 135          'Memcache cache set',
 136          array('key' => $key, 'var' => $data)
 137      );
 138    }
 139  
 140    /**
 141     * @inheritDoc
 142     * @param String $key
 143     */
 144    public function delete($key)
 145    {
 146      $this->connect();
 147      if ($this->mc) {
 148        $this->mc->delete($key, 0);
 149      } else {
 150        memcache_delete($this->connection, $key, 0);
 151      }
 152  
 153      $this->client->getLogger()->debug(
 154          'Memcache cache delete',
 155          array('key' => $key)
 156      );
 157    }
 158  
 159    /**
 160     * Lazy initialiser for memcache connection. Uses pconnect for to take
 161     * advantage of the persistence pool where possible.
 162     */
 163    private function connect()
 164    {
 165      if ($this->connection) {
 166        return;
 167      }
 168  
 169      if (class_exists("Memcached")) {
 170        $this->mc = new Memcached();
 171        $this->mc->addServer($this->host, $this->port);
 172         $this->connection = true;
 173      } else {
 174        $this->connection = memcache_pconnect($this->host, $this->port);
 175      }
 176  
 177      if (! $this->connection) {
 178        $error = "Couldn't connect to memcache server";
 179  
 180        $this->client->getLogger()->error($error);
 181        throw new Google_Cache_Exception($error);
 182      }
 183    }
 184  }