1<?php
2
3// security - hide paths
4if (!defined('ADODB_DIR')) die();
5
6global $ADODB_INCLUDED_MEMCACHE;
7$ADODB_INCLUDED_MEMCACHE = 1;
8
9global $ADODB_INCLUDED_CSV;
10if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
11
12/*
13
14  @version   v5.20.16  12-Jan-2020
15  @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
16  @copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community
17  Released under both BSD license and Lesser GPL library license.
18  Whenever there is any discrepancy between the two licenses,
19  the BSD license will take precedence. See License.txt.
20  Set tabs to 4 for best viewing.
21
22  Latest version is available at http://adodb.org/
23
24Usage:
25
26$db = NewADOConnection($driver);
27$db->memCache = true; /// should we use memCache instead of caching in files
28$db->memCacheHost = array($ip1, $ip2, $ip3);
29$db->memCachePort = 11211; /// this is default memCache port
30$db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib)
31
32$db->Connect(...);
33$db->CacheExecute($sql);
34
35  Note the memcache class is shared by all connections, is created during the first call to Connect/PConnect.
36
37  Class instance is stored in $ADODB_CACHE
38*/
39
40	class ADODB_Cache_MemCache {
41		var $createdir = false; // create caching directory structure?
42
43		//-----------------------------
44		// memcache specific variables
45
46		var $hosts;	// array of hosts
47		var $port = 11211;
48		var $compress = false; // memcache compression with zlib
49
50		var $_connected = false;
51		var $_memcache = false;
52
53		function __construct(&$obj)
54		{
55			$this->hosts = $obj->memCacheHost;
56			$this->port = $obj->memCachePort;
57			$this->compress = $obj->memCacheCompress;
58		}
59
60		// implement as lazy connection. The connection only occurs on CacheExecute call
61		function connect(&$err)
62		{
63			if (!function_exists('memcache_pconnect')) {
64				$err = 'Memcache module PECL extension not found!';
65				return false;
66			}
67
68			$memcache = new MemCache;
69
70			if (!is_array($this->hosts)) $this->hosts = array($this->hosts);
71
72			$failcnt = 0;
73			foreach($this->hosts as $host) {
74				if (!@$memcache->addServer($host,$this->port,true)) {
75					$failcnt += 1;
76				}
77			}
78			if ($failcnt == sizeof($this->hosts)) {
79				$err = 'Can\'t connect to any memcache server';
80				return false;
81			}
82			$this->_connected = true;
83			$this->_memcache = $memcache;
84			return true;
85		}
86
87		// returns true or false. true if successful save
88		function writecache($filename, $contents, $debug, $secs2cache)
89		{
90			if (!$this->_connected) {
91				$err = '';
92				if (!$this->connect($err) && $debug) ADOConnection::outp($err);
93			}
94			if (!$this->_memcache) return false;
95
96			if (!$this->_memcache->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) {
97				if ($debug) ADOConnection::outp(" Failed to save data at the memcached server!<br>\n");
98				return false;
99			}
100
101			return true;
102		}
103
104		// returns a recordset
105		function readcache($filename, &$err, $secs2cache, $rsClass)
106		{
107			$false = false;
108			if (!$this->_connected) $this->connect($err);
109			if (!$this->_memcache) return $false;
110
111			$rs = $this->_memcache->get($filename);
112			if (!$rs) {
113				$err = 'Item with such key doesn\'t exists on the memcached server.';
114				return $false;
115			}
116
117			// hack, should actually use _csv2rs
118			$rs = explode("\n", $rs);
119            unset($rs[0]);
120            $rs = join("\n", $rs);
121 			$rs = unserialize($rs);
122			if (! is_object($rs)) {
123				$err = 'Unable to unserialize $rs';
124				return $false;
125			}
126			if ($rs->timeCreated == 0) return $rs; // apparently have been reports that timeCreated was set to 0 somewhere
127
128			$tdiff = intval($rs->timeCreated+$secs2cache - time());
129			if ($tdiff <= 2) {
130				switch($tdiff) {
131					case 2:
132						if ((rand() & 15) == 0) {
133							$err = "Timeout 2";
134							return $false;
135						}
136						break;
137					case 1:
138						if ((rand() & 3) == 0) {
139							$err = "Timeout 1";
140							return $false;
141						}
142						break;
143					default:
144						$err = "Timeout 0";
145						return $false;
146				}
147			}
148			return $rs;
149		}
150
151		function flushall($debug=false)
152		{
153			if (!$this->_connected) {
154				$err = '';
155				if (!$this->connect($err) && $debug) ADOConnection::outp($err);
156			}
157			if (!$this->_memcache) return false;
158
159			$del = $this->_memcache->flush();
160
161			if ($debug)
162				if (!$del) ADOConnection::outp("flushall: failed!<br>\n");
163				else ADOConnection::outp("flushall: succeeded!<br>\n");
164
165			return $del;
166		}
167
168		function flushcache($filename, $debug=false)
169		{
170			if (!$this->_connected) {
171  				$err = '';
172  				if (!$this->connect($err) && $debug) ADOConnection::outp($err);
173			}
174			if (!$this->_memcache) return false;
175
176			$del = $this->_memcache->delete($filename);
177
178			if ($debug)
179				if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcached server!<br>\n");
180				else ADOConnection::outp("flushcache: $key entry flushed from memcached server!<br>\n");
181
182			return $del;
183		}
184
185		// not used for memcache
186		function createdir($dir, $hash)
187		{
188			return true;
189		}
190	}
191