Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
<?php
> /** > * Memory caching. // security - hide paths > * if (!defined('ADODB_DIR')) die(); > * This file is part of ADOdb, a Database Abstraction Layer library for PHP. > * global $ADODB_INCLUDED_MEMCACHE; > * @package ADOdb $ADODB_INCLUDED_MEMCACHE = 1; > * @link https://adodb.org Project's web site and documentation > * @link https://github.com/ADOdb/ADOdb Source code and issue tracker global $ADODB_INCLUDED_CSV; > * if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php'); > * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause > * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option, /* > * any later version. This means you can use it in proprietary products. > * See the LICENSE.md file distributed with this source code for details. @version v5.21.0 2021-02-27 > * @license BSD-3-Clause @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved. > * @license LGPL-2.1-or-later @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community > * Released under both BSD license and Lesser GPL library license. > * @copyright 2000-2013 John Lim Whenever there is any discrepancy between the two licenses, > * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community the BSD license will take precedence. See License.txt. > * Set tabs to 4 for best viewing. > * @noinspection PhpUnused > */
< if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php'); < < /*
> if (empty($ADODB_INCLUDED_CSV)) { > include_once(ADODB_DIR . '/adodb-csvlib.inc.php'); > }
< @version v5.21.0 2021-02-27 < @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved. < @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community < Released under both BSD license and Lesser GPL library license. < Whenever there is any discrepancy between the two licenses, < the BSD license will take precedence. See License.txt. < Set tabs to 4 for best viewing.
> class ADODB_Cache_MemCache > { > /** > * @var bool Prevents parent class calling non-existant function > */ > public $createdir = false;
< Latest version is available at https://adodb.org/
> /** > * @var array of hosts > */ > private $hosts;
< Usage:
> /** > * @var int Connection Port, uses default > */ > private $port;
< $db = NewADOConnection($driver); < $db->memCache = true; /// should we use memCache instead of caching in files < $db->memCacheHost = array($ip1, $ip2, $ip3); < $db->memCachePort = 11211; /// this is default memCache port < $db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib) < /// Note; compression is not supported w/the memcached library
> /** > * @var bool memcache compression with zlib > */ > private $compress;
< $db->Connect(...); < $db->CacheExecute($sql);
> /** > * @var array of options for memcached only > */ > private $options;
< Notes; The memcache class is shared by all connections, is created during the first call to Connect/PConnect. < We'll look for both the memcache library (https://pecl.php.net/package/memcache) and the memcached < library (https://pecl.php.net/package/memcached). If both exist, the memcache library will be used.
> /** > * @var bool Internal flag indicating successful connection > */ > private $isConnected = false;
< Class instance is stored in $ADODB_CACHE
> /** > * @var Memcache|Memcached Handle for the Memcache library > * > * Populated with the proper library on connect, used later when > * there are differences in specific calls between memcache and memcached
// $library will be populated with the proper library on connect
> private $memcacheLibrary = false;
< class ADODB_Cache_MemCache { < var $createdir = false; // create caching directory structure?
> /** > * @var array New server feature controller lists available servers > */ > private $serverControllers = array();
< // $library will be populated with the proper library on connect < // and is used later when there are differences in specific calls < // between memcache and memcached < var $library = false;
> /** > * @var array New server feature template uses granular server controller > */ > private $serverControllerTemplate = array( > 'host' => '', > 'port' => 11211, > 'weight' => 0, > ); > > /** > * An integer index into the libraries > * @see $libraries > */ > const MCLIB = 1; > const MCLIBD = 2;
< //----------------------------- < // memcache specific variables
> /** > * @var array Xrefs the library flag to the actual class name > */ > private $libraries = array( > self::MCLIB => 'Memcache', > self::MCLIBD => 'Memcached' > );
< var $hosts; // array of hosts < var $port = 11211; < var $compress = false; // memcache compression with zlib
> /** > * @var int An indicator of which library we are using > */ > private $libraryFlag;
< var $_connected = false; < var $_memcache = false;
> /** > * Class Constructor. > * > * @param ADOConnection $db > */ > public function __construct($db) > { > $this->hosts = $db->memCacheHost; > $this->port = $this->serverControllerTemplate['port'] = $db->memCachePort; > $this->compress = $db->memCacheCompress; > $this->options = $db->memCacheOptions; > }
< function __construct(&$obj)
> /** > * Return true if the current library is Memcached. > * @return bool > */ > public function isLibMemcached(): bool
{
< $this->hosts = $obj->memCacheHost; < $this->port = $obj->memCachePort; < $this->compress = $obj->memCacheCompress;
> return $this->libraryFlag == self::MCLIBD;
}
< // implement as lazy connection. The connection only occurs on CacheExecute call < function connect(&$err)
> /** > * Lazy connection. > * > * The connection only occurs on CacheExecute call. > * > * @param string $err > * > * @return bool success of connecting to a server > */ > public function connect(&$err)
{
< // do we have memcache or memcached?
> // do we have memcache or memcached? see the note at adodb.org on memcache
if (class_exists('Memcache')) {
< $this->library='Memcache'; < $memcache = new MemCache;
> $this->libraryFlag = self::MCLIB;
} elseif (class_exists('Memcached')) {
< $this->library='Memcached'; < $memcache = new MemCached;
> $this->libraryFlag = self::MCLIBD;
} else { $err = 'Neither the Memcache nor Memcached PECL extensions were found!'; return false; }
< if (!is_array($this->hosts)) $this->hosts = array($this->hosts);
> $usedLibrary = $this->libraries[$this->libraryFlag]; > > /** @var Memcache|Memcached $memCache */ > $memCache = new $usedLibrary; > if (!$memCache) { > $err = 'Memcache library failed to initialize'; > return false; > } > > // Convert simple compression flag for memcached > if ($this->isLibMemcached()) { > $this->options[Memcached::OPT_COMPRESSION] = $this->compress; > } > > // Are there any options available for memcached > if ($this->isLibMemcached() && count($this->options) > 0) { > $optionSuccess = $memCache->setOptions($this->options); > if (!$optionSuccess) { > $err = 'Invalid option parameters passed to Memcached'; > return false; > } > } > > // Have we passed a controller array > if (!is_array($this->hosts)) { > $this->hosts = array($this->hosts); > } > > if (!is_array($this->hosts[0])) { > // Old way, convert to controller > foreach ($this->hosts as $ipAddress) { > $connector = $this->serverControllerTemplate; > $connector['host'] = $ipAddress; > $connector['port'] = $this->port; > > $this->serverControllers[] = $connector; > } > } else { > // New way, must validate port, etc > foreach ($this->hosts as $controller) { > $connector = array_merge($this->serverControllerTemplate, $controller); > if ($this->isLibMemcached()) { > $connector['weight'] = (int)$connector['weight']; > } else { > // Cannot use weight in memcache, simply discard > $connector['weight'] = 0; > } > > $this->serverControllers[] = $connector; > } > } > > // Checks for existing connections ( but only for memcached ) > if ($this->isLibMemcached() && !empty($memCache->getServerList())) { > // Use the existing configuration > $this->isConnected = true; > $this->memcacheLibrary = $memCache; > return true; > }
$failcnt = 0;
< foreach($this->hosts as $host) { < if (!@$memcache->addServer($host,$this->port)) { < $failcnt += 1;
> foreach ($this->serverControllers as $controller) { > if ($this->isLibMemcached()) { > if (!@$memCache->addServer($controller['host'], $controller['port'], $controller['weight'])) { > $failcnt++; > } > } else { > if (!@$memCache->addServer($controller['host'], $controller['port'])) { > $failcnt++;
} }
< if ($failcnt == sizeof($this->hosts)) {
> } > if ($failcnt == sizeof($this->serverControllers)) {
$err = 'Can\'t connect to any memcache server'; return false; }
< $this->_connected = true; < $this->_memcache = $memcache;
> > $this->memcacheLibrary = $memCache; > > // A valid memcache connection is available > $this->isConnected = true;
return true; }
< // returns true or false. true if successful save < function writecache($filename, $contents, $debug, $secs2cache)
> /** > * Writes a cached query to the server > * > * @param string $filename The MD5 of the query to cache > * @param string $contents The query results > * @param bool $debug > * @param int $secs2cache > * > * @return bool true or false. true if successful save > */ > public function writeCache($filename, $contents, $debug, $secs2cache)
{
< if (!$this->_connected) {
$err = '';
< if (!$this->connect($err) && $debug) ADOConnection::outp($err);
> if (!$this->isConnected && $debug) { > // Call to writeCache() before connect(), try to connect > if (!$this->connect($err)) { > ADOConnection::outp($err); > } > } else { > if (!$this->isConnected) { > $this->connect($err); > } > } > > if (!$this->memcacheLibrary) { > return false;
}
< if (!$this->_memcache) return false;
$failed=false;
< switch ($this->library) { < case 'Memcache': < if (!$this->_memcache->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) {
> switch ($this->libraryFlag) { > case self::MCLIB: > if (!$this->memcacheLibrary->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, > $secs2cache)) {
$failed=true; } break;
< case 'Memcached': < if (!$this->_memcache->set($filename, $contents, $secs2cache)) {
> case self::MCLIBD: > if (!$this->memcacheLibrary->set($filename, $contents, $secs2cache)) {
$failed=true; } break; default: $failed=true; break; } if($failed) {
< if ($debug) ADOConnection::outp(" Failed to save data at the memcache server!<br>\n");
> if ($debug) { > ADOConnection::outp(" Failed to save data at the memcache server!<br>\n"); > }
return false; } return true; }
< // returns a recordset < function readcache($filename, &$err, $secs2cache, $rsClass)
> /** > * Reads a cached query from the server. > * > * @param string $filename The MD5 of the query to read > * @param string $err The query results > * @param int $secs2cache > * @param object $rsClass **UNUSED** > * > * @return object|bool record or false. > * > * @noinspection PhpUnusedParameterInspection > */ > public function readCache($filename, &$err, $secs2cache, $rsClass)
{
< $false = false; < if (!$this->_connected) $this->connect($err); < if (!$this->_memcache) return $false;
> if (!$this->isConnected) { > $this->connect($err); > } > if (!$this->memcacheLibrary) { > return false; > }
< $rs = $this->_memcache->get($filename);
> $rs = $this->memcacheLibrary->get($filename);
if (!$rs) { $err = 'Item with such key doesn\'t exist on the memcache server.';
< return $false;
> return false;
} // hack, should actually use _csv2rs $rs = explode("\n", $rs); unset($rs[0]); $rs = join("\n", $rs); $rs = unserialize($rs); if (! is_object($rs)) { $err = 'Unable to unserialize $rs';
< return $false;
> return false;
}
< if ($rs->timeCreated == 0) return $rs; // apparently have been reports that timeCreated was set to 0 somewhere
> if ($rs->timeCreated == 0) { > return $rs; > } // apparently have been reports that timeCreated was set to 0 somewhere
$tdiff = intval($rs->timeCreated+$secs2cache - time()); if ($tdiff <= 2) { switch($tdiff) { case 2: if ((rand() & 15) == 0) { $err = "Timeout 2";
< return $false;
> return false;
} break; case 1: if ((rand() & 3) == 0) { $err = "Timeout 1";
< return $false;
> return false;
} break; default: $err = "Timeout 0";
< return $false;
> return false;
} } return $rs; }
< function flushall($debug=false)
> /** > * Flushes all of the stored memcache data > * > * @param bool $debug > * > * @return bool The response from the memcache server > */ > public function flushAll($debug = false)
{
< if (!$this->_connected) {
> if (!$this->isConnected) {
$err = '';
< if (!$this->connect($err) && $debug) ADOConnection::outp($err);
> if (!$this->connect($err) && $debug) { > ADOConnection::outp($err); > } > } > if (!$this->memcacheLibrary) { > return false;
}
< if (!$this->_memcache) return false;
< $del = $this->_memcache->flush();
> $del = $this->memcacheLibrary->flush();
< if ($debug) < if (!$del) ADOConnection::outp("flushall: failed!<br>\n"); < else ADOConnection::outp("flushall: succeeded!<br>\n");
> if ($debug) { > if (!$del) { > ADOConnection::outp("flushall: failed!<br>\n"); > } else { > ADOConnection::outp("flushall: succeeded!<br>\n"); > } > }
return $del; }
< function flushcache($filename, $debug=false)
> /** > * Flushes the contents of a specified query > * > * @param string $filename The MD5 of the query to flush > * @param bool $debug > * > * @return bool The response from the memcache server > */ > public function flushCache($filename, $debug = false)
{
< if (!$this->_connected) {
> if (!$this->isConnected) {
$err = '';
< if (!$this->connect($err) && $debug) ADOConnection::outp($err);
> if (!$this->connect($err) && $debug) { > ADOConnection::outp($err); > } > } > if (!$this->memcacheLibrary) { > return false;
}
< if (!$this->_memcache) return false;
< $del = $this->_memcache->delete($filename);
> $del = $this->memcacheLibrary->delete($filename);
< if ($debug) < if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcache server!<br>\n"); < else ADOConnection::outp("flushcache: $key entry flushed from memcache server!<br>\n");
> if ($debug) { > if (!$del) { > ADOConnection::outp("flushcache: $filename entry doesn't exist on memcache server!<br>\n"); > } else { > ADOConnection::outp("flushcache: $filename entry flushed from memcache server!<br>\n"); > } > }
return $del; }
< // not used for memcache < function createdir($dir, $hash) < { < return true; < }
}