Elgg  Version 2.2
ElggMemcache.php
Go to the documentation of this file.
1 <?php
14  private $CONFIG;
15 
20  private static $MINSERVERVERSION = '1.1.12';
21 
25  private $memcache;
26 
30  private $expires = 86400;
31 
35  private $version = 0;
36 
45  public function __construct($namespace = 'default') {
46  global $CONFIG;
47  $this->CONFIG = $CONFIG;
48 
49  $this->setNamespace($namespace);
50 
51  // Do we have memcache?
52  if (!class_exists('Memcache')) {
53  throw new \ConfigurationException('PHP memcache module not installed, you must install php5-memcache');
54  }
55 
56  // Create memcache object
57  $this->memcache = new Memcache;
58 
59  // Now add servers
60  if (!$this->CONFIG->memcache_servers) {
61  throw new \ConfigurationException('No memcache servers defined, please populate the $this->CONFIG->memcache_servers variable');
62  }
63 
64  if (is_callable(array($this->memcache, 'addServer'))) {
65  foreach ($this->CONFIG->memcache_servers as $server) {
66  if (is_array($server)) {
67  $this->memcache->addServer(
68  $server[0],
69  isset($server[1]) ? $server[1] : 11211,
70  isset($server[2]) ? $server[2] : false,
71  isset($server[3]) ? $server[3] : 1,
72  isset($server[4]) ? $server[4] : 1,
73  isset($server[5]) ? $server[5] : 15,
74  isset($server[6]) ? $server[6] : true
75  );
76 
77  } else {
78  $this->memcache->addServer($server, 11211);
79  }
80  }
81  } else {
82  // don't use _elgg_services()->translator->translate() here because most of the config hasn't been loaded yet
83  // and it caches the language, which is hard coded in $this->CONFIG->language as en.
84  // overriding it with real values later has no effect because it's already cached.
85  _elgg_services()->logger->error("This version of the PHP memcache API doesn't support multiple servers.");
86 
87  $server = $this->CONFIG->memcache_servers[0];
88  if (is_array($server)) {
89  $this->memcache->connect($server[0], $server[1]);
90  } else {
91  $this->memcache->addServer($server, 11211);
92  }
93  }
94 
95  // Get version
96  $this->version = $this->memcache->getVersion();
97  if (version_compare($this->version, \ElggMemcache::$MINSERVERVERSION, '<')) {
98  $msg = vsprintf('Memcache needs at least version %s to run, you are running %s',
99  array(\ElggMemcache::$MINSERVERVERSION,
100  $this->version
101  ));
102 
103  throw new \ConfigurationException($msg);
104  }
105 
106  // Set some defaults
107  if (isset($this->CONFIG->memcache_expires)) {
108  $this->expires = $this->CONFIG->memcache_expires;
109  }
110 
111  // make sure memcache is reset
112  _elgg_services()->events->registerHandler('cache:flush', 'system', array($this, 'clear'));
113  }
114 
122  public function setDefaultExpiry($expires = 0) {
123  $this->expires = $expires;
124  }
125 
134  private function makeMemcacheKey($key) {
135  $prefix = $this->getNamespace() . ":";
136 
137  if (strlen($prefix . $key) > 250) {
138  $key = md5($key);
139  }
140 
141  return $prefix . $key;
142  }
143 
153  public function save($key, $data, $expires = null) {
154  $key = $this->makeMemcacheKey($key);
155 
156  if ($expires === null) {
157  $expires = $this->expires;
158  }
159 
160  $result = $this->memcache->set($key, $data, null, $expires);
161  if ($result === false) {
162  _elgg_services()->logger->error("MEMCACHE: SAVE FAIL $key");
163  } else {
164  _elgg_services()->logger->info("MEMCACHE: SAVE SUCCESS $key");
165  }
166 
167  return $result;
168  }
169 
179  public function load($key, $offset = 0, $limit = null) {
180  $key = $this->makeMemcacheKey($key);
181 
182  $result = $this->memcache->get($key);
183  if ($result === false) {
184  _elgg_services()->logger->info("MEMCACHE: LOAD MISS $key");
185  } else {
186  _elgg_services()->logger->info("MEMCACHE: LOAD HIT $key");
187  }
188 
189  return $result;
190  }
191 
199  public function delete($key) {
200  $key = $this->makeMemcacheKey($key);
201 
202  return $this->memcache->delete($key, 0);
203  }
204 
210  public function clear() {
211  $result = $this->memcache->flush();
212  if ($result === false) {
213  _elgg_services()->logger->info("MEMCACHE: failed to flush {$this->getNamespace()}");
214  } else {
215  sleep(1); // needed because http://php.net/manual/en/memcache.flush.php#81420
216 
217  _elgg_services()->logger->info("MEMCACHE: flushed {$this->getNamespace()}");
218  }
219 
220  return $result;
221 
222  // @todo Namespaces as in #532
223  }
224 
234  public function setNamespace($namespace = "default") {
235 
236  if (isset($this->CONFIG->memcache_namespace_prefix)) {
237  $namespace = $this->CONFIG->memcache_namespace_prefix . $namespace;
238  }
239 
240  parent::setNamespace($namespace);
241  }
242 }
$data
Definition: opendd.php:13
if(!$count) $offset
Definition: pagination.php:26
clear()
Clears the entire cache.
getNamespace()
Get the namespace currently defined.
setDefaultExpiry($expires=0)
Set the default expiry.
$limit
Definition: userpicker.php:38
$key
Definition: summary.php:34
load($key, $offset=0, $limit=null)
Retrieves data.
__construct($namespace= 'default')
Connect to memcache.
var vsprintf
Definition: sprintf.js:180
save($key, $data, $expires=null)
Saves a name and value to the cache.
elgg global
Pointer to the global context.
Definition: elgglib.js:12
it is up to the author donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License If the distribution and or use of the Program is restricted in certain countries either by patents or by copyrighted the original copyright holder who places the Program under this License may add an geographical distribution limitation excluding those so that distribution is permitted only in or among countries not thus excluded In such this License incorporates the limitation as if written in the body of this License The Free Software Foundation may publish revised and or new versions of the General Public License from time to time Such new versions will be similar in spirit to the present version
_elgg_services(\Elgg\Di\ServiceProvider $services=null)
Get the global service provider.
Definition: autoloader.php:17
setNamespace($namespace="default")
Set the namespace of this cache.