'', 'port'=>11211, 'weight'=>0, 'key'=>'' ); /* * An integer index into the libraries */ const MCLIB = 1; const MCLIBD = 2; /* * Xrefs the library flag to the actual class name */ private $libraries = array( 1=>'Memcache', 2=>'Memcached' ); /* * An indicator of which library we are using */ private $libraryFlag; /** * constructor passes in a ADONewConnection Object * * @param $db ADONewConnection object * * @return obj */ public function __construct(&$db) { $this->hosts = $db->memCacheHost; $this->port = $db->memCachePort; $this->compress = $db->memCacheCompress; $this->options = $db->memCacheOptions; } /** * implement as 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? see the note * at adodb.org on memcache */ if (class_exists('Memcache')) $this->libraryFlag = self::MCLIB; elseif (class_exists('Memcached')) $this->libraryFlag = self::MCLIBD; else { $err = 'Neither the Memcache nor Memcached PECL extensions were found!'; return false; } $usedLibrary = $this->libraries[$this->libraryFlag]; $memCache = new $usedLibrary; if (!$memCache) { $err = 'Memcache library failed to initialize'; return false; } /* * Convert simple compression flag for memcached */ if ($this->libraryFlag == self::MCLIBD && $this->compress) { /* * Value of Memcached::OPT_COMPRESSION = 2; */ $this->options[2] == 1; } /* * Are there any options available for memcached */ if ($this->libraryFlag == self::MCLIBD && count($this->options) > 0) { $optionSuccess = $memCache->setOptions($this->options); if (!$optionSuccess) { $err = 'Invalid option parameters passed to Memecached'; return false; } } /* * Have we passed a controller array */ if (!is_array($this->hosts)) $this->hosts = array($this->hosts); if (array_values($this->hosts) == $this->hosts) { /* * 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->libraryFlag == self::MCLIB) { /* * Cannot use a key or weight in memcache, simply discard */ $connector['key'] = ''; $connector['weight'] = 0; } else $connector['weight'] = $connector['weight'] ? (int)$connector['weight']:0; $this->serverControllers[] = $connector; } } /* * Checks for existing connections ( but only for memcached ) */ if ($this->libraryFlag == self::MCLIBD) { $existingServers = $memCache->getServerList(); if (is_array($existingServers)) { /* * Use the existing configuration */ $this->isConnected = true; $this->memcacheLibrary = $memCache; return true; } } $failcnt = 0; foreach($this->serverControllers as $controller) { switch($this->libraryFlag) { case self::MCLIB: if (!@$memCache->addServer($controller['host'],$controller['port'])) $failcnt++; break; default: if (!@$memCache->addServer($controller['host'],$controller['port'],$controller['weight'])) $failcnt++; } } if ($failcnt == sizeof($this->serverControllers)) { $err = 'Can\'t connect to any memcache server'; return false; } $this->memcacheLibrary = $memCache; /* * A valid memcache connection is available */ $this->isConnected = true; return true; } /** * 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) { $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; $failed=false; switch ($this->libraryFlag) { case self::MCLIB: if (!$this->memcacheLibrary->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) { $failed=true; } break; 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!
\n"); return false; } return true; } /** * Reads a cached query to the server * * @param string $filename The MD5 of the query to read * @param string $err The query results * @param int $secs2cache * @param obj $rsClass **UNUSED** * @return the record or false. */ public function readCache($filename, &$err, $secs2cache, $rsClass) { if (!$this->isConnected) $this->connect($err); if (!$this->memcacheLibrary) return false; $rs = $this->memcacheLibrary->get($filename); if (!$rs) { $err = 'Item with such key doesn\'t exist on the memcache server.'; 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; } 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; } break; case 1: if ((rand() & 3) == 0) { $err = "Timeout 1"; return false; } break; default: $err = "Timeout 0"; return false; } } return $rs; } /** * Flushes all of the stored memcache data * * @param bool $debug * * @return int The response from the memcache server */ public function flushAll($debug=false) { if (!$this->isConnected) { $err = ''; if (!$this->connect($err) && $debug) ADOConnection::outp($err); } if (!$this->memcacheLibrary) return false; $del = $this->memcacheLibrary->flush(); if ($debug) if (!$del) ADOConnection::outp("flushall: failed!
\n"); else ADOConnection::outp("flushall: succeeded!
\n"); return $del; } /** * Flushes the contents of a specified query * * @param str $filname The MD5 of the query to flush * @param bool $debug * * @return int The response from the memcache server */ public function flushCache($filename, $debug=false) { if (!$this->isConnected) { $err = ''; if (!$this->connect($err) && $debug) ADOConnection::outp($err); } if (!$this->memcacheLibrary) return false; $del = $this->memcacheLibrary->delete($filename); if ($debug) if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcache server!
\n"); else ADOConnection::outp("flushcache: $key entry flushed from memcache server!
\n"); return $del; } }