Elgg  Version 2.2
 All Classes Namespaces Files Functions Variables Pages
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.
string version
Definition: conf.py:54
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.
save($key, $data, $expires=null)
Saves a name and value to the cache.
_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.