/google_api/Cache/Memcache.php

  1. <?php 
  2. /** 
  3. * Copyright 2008 Google Inc. 
  4. * 
  5. * Licensed under the Apache License, Version 2.0 (the "License"); 
  6. * you may not use this file except in compliance with the License. 
  7. * You may obtain a copy of the License at 
  8. * 
  9. * http://www.apache.org/licenses/LICENSE-2.0 
  10. * 
  11. * Unless required by applicable law or agreed to in writing, software 
  12. * distributed under the License is distributed on an "AS IS" BASIS,  
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14. * See the License for the specific language governing permissions and 
  15. * limitations under the License. 
  16. */ 
  17.  
  18. if (!class_exists('Google_Client')) { 
  19. require_once dirname(__FILE__) . '/../autoload.php'; 
  20.  
  21. /** 
  22. * A persistent storage class based on the memcache, which is not 
  23. * really very persistent, as soon as you restart your memcache daemon 
  24. * the storage will be wiped. 
  25. * 
  26. * Will use either the memcache or memcached extensions, preferring 
  27. * memcached. 
  28. * 
  29. * @author Chris Chabot <chabotc@google.com> 
  30. */ 
  31. class Google_Cache_Memcache extends Google_Cache_Abstract 
  32. private $connection = false; 
  33. private $mc = false; 
  34. private $host; 
  35. private $port; 
  36.  
  37. /** 
  38. * @var Google_Client the current client 
  39. */ 
  40. private $client; 
  41.  
  42. public function __construct(Google_Client $client) 
  43. if (!function_exists('memcache_connect') && !class_exists("Memcached")) { 
  44. $error = "Memcache functions not available"; 
  45.  
  46. $client->getLogger()->error($error); 
  47. throw new Google_Cache_Exception($error); 
  48.  
  49. $this->client = $client; 
  50.  
  51. if ($client->isAppEngine()) { 
  52. // No credentials needed for GAE. 
  53. $this->mc = new Memcached(); 
  54. $this->connection = true; 
  55. } else { 
  56. $this->host = $client->getClassConfig($this, 'host'); 
  57. $this->port = $client->getClassConfig($this, 'port'); 
  58. if (empty($this->host) || (empty($this->port) && (string) $this->port != "0")) { 
  59. $error = "You need to supply a valid memcache host and port"; 
  60.  
  61. $client->getLogger()->error($error); 
  62. throw new Google_Cache_Exception($error); 
  63.  
  64. /** 
  65. * @inheritDoc 
  66. */ 
  67. public function get($key, $expiration = false) 
  68. $this->connect(); 
  69. $ret = false; 
  70. if ($this->mc) { 
  71. $ret = $this->mc->get($key); 
  72. } else { 
  73. $ret = memcache_get($this->connection, $key); 
  74. if ($ret === false) { 
  75. $this->client->getLogger()->debug( 
  76. 'Memcache cache miss',  
  77. array('key' => $key) 
  78. ); 
  79. return false; 
  80. if (is_numeric($expiration) && (time() - $ret['time'] > $expiration)) { 
  81. $this->client->getLogger()->debug( 
  82. 'Memcache cache miss (expired)',  
  83. array('key' => $key, 'var' => $ret) 
  84. ); 
  85. $this->delete($key); 
  86. return false; 
  87.  
  88. $this->client->getLogger()->debug( 
  89. 'Memcache cache hit',  
  90. array('key' => $key, 'var' => $ret) 
  91. ); 
  92.  
  93. return $ret['data']; 
  94.  
  95. /** 
  96. * @inheritDoc 
  97. * @param string $key 
  98. * @param string $value 
  99. * @throws Google_Cache_Exception 
  100. */ 
  101. public function set($key, $value) 
  102. $this->connect(); 
  103. // we store it with the cache_time default expiration so objects will at 
  104. // least get cleaned eventually. 
  105. $data = array('time' => time(), 'data' => $value); 
  106. $rc = false; 
  107. if ($this->mc) { 
  108. $rc = $this->mc->set($key, $data); 
  109. } else { 
  110. $rc = memcache_set($this->connection, $key, $data, false); 
  111. if ($rc == false) { 
  112. $this->client->getLogger()->error( 
  113. 'Memcache cache set failed',  
  114. array('key' => $key, 'var' => $data) 
  115. ); 
  116.  
  117. throw new Google_Cache_Exception("Couldn't store data in cache"); 
  118.  
  119. $this->client->getLogger()->debug( 
  120. 'Memcache cache set',  
  121. array('key' => $key, 'var' => $data) 
  122. ); 
  123.  
  124. /** 
  125. * @inheritDoc 
  126. * @param String $key 
  127. */ 
  128. public function delete($key) 
  129. $this->connect(); 
  130. if ($this->mc) { 
  131. $this->mc->delete($key, 0); 
  132. } else { 
  133. memcache_delete($this->connection, $key, 0); 
  134.  
  135. $this->client->getLogger()->debug( 
  136. 'Memcache cache delete',  
  137. array('key' => $key) 
  138. ); 
  139.  
  140. /** 
  141. * Lazy initialiser for memcache connection. Uses pconnect for to take 
  142. * advantage of the persistence pool where possible. 
  143. */ 
  144. private function connect() 
  145. if ($this->connection) { 
  146. return; 
  147.  
  148. if (class_exists("Memcached")) { 
  149. $this->mc = new Memcached(); 
  150. $this->mc->addServer($this->host, $this->port); 
  151. $this->connection = true; 
  152. } else { 
  153. $this->connection = memcache_pconnect($this->host, $this->port); 
  154.  
  155. if (! $this->connection) { 
  156. $error = "Couldn't connect to memcache server"; 
  157.  
  158. $this->client->getLogger()->error($error); 
  159. throw new Google_Cache_Exception($error); 
.