Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]

   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  #[AllowDynamicProperties]
  33  class Google_Cache_Memcache extends Google_Cache_Abstract
  34  {
  35    private $connection = false;
  36    private $mc = false;
  37    private $host;
  38    private $port;
  39  
  40    /**
  41     * @var Google_Client the current client
  42     */
  43    private $client;
  44  
  45    public function __construct(Google_Client $client)
  46    {
  47      if (!function_exists('memcache_connect') && !class_exists("Memcached")) {
  48        $error = "Memcache functions not available";
  49  
  50        $client->getLogger()->error($error);
  51        throw new Google_Cache_Exception($error);
  52      }
  53  
  54      $this->client = $client;
  55  
  56      if ($client->isAppEngine()) {
  57        // No credentials needed for GAE.
  58        $this->mc = new Memcached();
  59        $this->connection = true;
  60      } else {
  61        $this->host = $client->getClassConfig($this, 'host');
  62        $this->port = $client->getClassConfig($this, 'port');
  63        if (empty($this->host) || (empty($this->port) && (string) $this->port != "0")) {
  64          $error = "You need to supply a valid memcache host and port";
  65  
  66          $client->getLogger()->error($error);
  67          throw new Google_Cache_Exception($error);
  68        }
  69      }
  70    }
  71  
  72    /**
  73     * @inheritDoc
  74     */
  75    public function get($key, $expiration = false)
  76    {
  77      $this->connect();
  78      $ret = false;
  79      if ($this->mc) {
  80        $ret = $this->mc->get($key);
  81      } else {
  82        $ret = memcache_get($this->connection, $key);
  83      }
  84      if ($ret === false) {
  85        $this->client->getLogger()->debug(
  86            'Memcache cache miss',
  87            array('key' => $key)
  88        );
  89        return false;
  90      }
  91      if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) {
  92        $this->client->getLogger()->debug(
  93            'Memcache cache miss (expired)',
  94            array('key' => $key, 'var' => $ret)
  95        );
  96        $this->delete($key);
  97        return false;
  98      }
  99  
 100      $this->client->getLogger()->debug(
 101          'Memcache cache hit',
 102          array('key' => $key, 'var' => $ret)
 103      );
 104  
 105      return $ret['data'];
 106    }
 107  
 108    /**
 109     * @inheritDoc
 110     * @param string $key
 111     * @param string $value
 112     * @throws Google_Cache_Exception
 113     */
 114    public function set($key, $value)
 115    {
 116      $this->connect();
 117      // we store it with the cache_time default expiration so objects will at
 118      // least get cleaned eventually.
 119      $data = array('time' => time(), 'data' => $value);
 120      $rc = false;
 121      if ($this->mc) {
 122        $rc = $this->mc->set($key, $data);
 123      } else {
 124        $rc = memcache_set($this->connection, $key, $data, false);
 125      }
 126      if ($rc == false) {
 127        $this->client->getLogger()->error(
 128            'Memcache cache set failed',
 129            array('key' => $key, 'var' => $data)
 130        );
 131  
 132        throw new Google_Cache_Exception("Couldn't store data in cache");
 133      }
 134  
 135      $this->client->getLogger()->debug(
 136          'Memcache cache set',
 137          array('key' => $key, 'var' => $data)
 138      );
 139    }
 140  
 141    /**
 142     * @inheritDoc
 143     * @param String $key
 144     */
 145    public function delete($key)
 146    {
 147      $this->connect();
 148      if ($this->mc) {
 149        $this->mc->delete($key, 0);
 150      } else {
 151        memcache_delete($this->connection, $key, 0);
 152      }
 153  
 154      $this->client->getLogger()->debug(
 155          'Memcache cache delete',
 156          array('key' => $key)
 157      );
 158    }
 159  
 160    /**
 161     * Lazy initialiser for memcache connection. Uses pconnect for to take
 162     * advantage of the persistence pool where possible.
 163     */
 164    private function connect()
 165    {
 166      if ($this->connection) {
 167        return;
 168      }
 169  
 170      if (class_exists("Memcached")) {
 171        $this->mc = new Memcached();
 172        $this->mc->addServer($this->host, $this->port);
 173         $this->connection = true;
 174      } else {
 175        $this->connection = memcache_pconnect($this->host, $this->port);
 176      }
 177  
 178      if (! $this->connection) {
 179        $error = "Couldn't connect to memcache server";
 180  
 181        $this->client->getLogger()->error($error);
 182        throw new Google_Cache_Exception($error);
 183      }
 184    }
 185  }