2 namespace TYPO3\CMS\Core\Cache\Backend;
89 if (!extension_loaded(
'memcache')) {
90 throw new \TYPO3\CMS\Core\Cache\Exception(
'The PHP extension "memcache" must be installed and loaded in ' .
'order to use the Memcached backend.', 1213987706);
92 parent::__construct(
$context, $options);
117 if ($useCompression ===
true) {
118 $this->flags ^= MEMCACHE_COMPRESSED;
120 $this->flags &= ~MEMCACHE_COMPRESSED;
132 if (empty($this->servers)) {
133 throw new \TYPO3\CMS\Core\Cache\Exception(
'No servers were given to Memcache', 1213115903);
135 $this->memcache = new \Memcache();
136 $defaultPort = ini_get(
'memcache.default_port');
137 foreach ($this->servers as
$server) {
138 if (substr($server, 0, 7) ==
'unix://') {
142 if (substr($server, 0, 6) ===
'tcp://') {
143 $server = substr($server, 6);
145 if (strpos($server,
':') !==
false) {
146 list($host, $port) = explode(
':', $server, 2);
149 $port = $defaultPort;
152 $this->memcache->addserver($host, $port);
162 public function setCache(\TYPO3\CMS\Core\Cache\Frontend\FrontendInterface
$cache)
164 parent::setCache($cache);
165 $identifierHash = substr(md5(PATH_site . $this->context . $this->cacheIdentifier), 0, 12);
166 $this->identifierPrefix =
'TYPO3_' . $identifierHash .
'_';
182 public function set($entryIdentifier, $data, array $tags = array(), $lifetime = null)
184 if (strlen($this->identifierPrefix . $entryIdentifier) > 250) {
185 throw new \InvalidArgumentException(
'Could not set value. Key more than 250 characters (' . $this->identifierPrefix . $entryIdentifier .
').', 1232969508);
187 if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
188 throw new \TYPO3\CMS\Core\Cache\Exception(
'No cache frontend has been set yet via setCache().', 1207149215);
190 if (!is_string($data)) {
191 throw new \TYPO3\CMS\Core\Cache\Exception\InvalidDataException(
'The specified data is of type "' . gettype($data) .
'" but a string is expected.', 1207149231);
197 if ($expiration > 2592000) {
198 $expiration +=
$GLOBALS[
'EXEC_TIME'];
201 if (strlen($data) > self::MAX_BUCKET_SIZE) {
202 $data = str_split($data, 1024 * 1000);
205 foreach ($data as $chunk) {
206 $success = $success && $this->memcache->set($this->identifierPrefix . $entryIdentifier .
'_chunk_' . $chunkNumber, $chunk, $this->flags, $expiration);
209 $success = $success && $this->memcache->set($this->identifierPrefix . $entryIdentifier,
'TYPO3*chunked:' . $chunkNumber, $this->flags, $expiration);
211 $success = $this->memcache->set($this->identifierPrefix . $entryIdentifier, $data, $this->flags, $expiration);
213 if ($success ===
true) {
217 throw new \TYPO3\CMS\Core\Cache\Exception(
'Could not set data to memcache server.', 1275830266);
220 \TYPO3\CMS\Core\Utility\GeneralUtility::sysLog(
'Memcache: could not set value. Reason: ' . $exception->getMessage(),
'core', \TYPO3\CMS\Core\Utility\GeneralUtility::SYSLOG_SEVERITY_WARNING);
231 public function get($entryIdentifier)
233 $value = $this->memcache->get($this->identifierPrefix . $entryIdentifier);
234 if (substr($value, 0, 14) ===
'TYPO3*chunked:') {
235 list(, $chunkCount) = explode(
':', $value);
237 for ($chunkNumber = 1; $chunkNumber < $chunkCount; $chunkNumber++) {
238 $value .= $this->memcache->get($this->identifierPrefix . $entryIdentifier .
'_chunk_' . $chunkNumber);
251 public function has($entryIdentifier)
253 return $this->memcache->get($this->identifierPrefix . $entryIdentifier) !==
false;
265 public function remove($entryIdentifier)
268 return $this->memcache->delete($this->identifierPrefix . $entryIdentifier, 0);
281 $identifiers = $this->memcache->get($this->identifierPrefix .
'tag_' . $tag);
282 if ($identifiers !==
false) {
283 return (array)$identifiers;
298 if (!$this->cache instanceof \TYPO3\CMS\Core\Cache\Frontend\FrontendInterface) {
299 throw new \TYPO3\CMS\Core\Cache\Exception(
'No cache frontend has been set via setCache() yet.', 1204111376);
301 $this->
flushByTag(
'%MEMCACHEBE%' . $this->cacheIdentifier);
314 foreach ($identifiers as $identifier) {
315 $this->
remove($identifier);
330 $existingTagsUpdated =
false;
332 foreach ($tags as $tag) {
335 if (!in_array($entryIdentifier, $identifiers,
true)) {
336 $identifiers[] = $entryIdentifier;
337 $this->memcache->set($this->identifierPrefix .
'tag_' . $tag, $identifiers);
340 if (!in_array($tag, $existingTags,
true)) {
341 $existingTags[] = $tag;
342 $existingTagsUpdated =
true;
347 if ($existingTagsUpdated) {
348 $this->memcache->set($this->identifierPrefix .
'ident_' . $entryIdentifier, $existingTags);
364 foreach ($tags as $tag) {
371 if (($key = array_search($entryIdentifier, $identifiers)) !==
false) {
372 unset($identifiers[$key]);
373 if (!empty($identifiers)) {
374 $this->memcache->set($this->identifierPrefix .
'tag_' . $tag, $identifiers);
376 $this->memcache->delete($this->identifierPrefix .
'tag_' . $tag, 0);
381 $this->memcache->delete($this->identifierPrefix .
'ident_' . $entryIdentifier, 0);
394 $tags = $this->memcache->get($this->identifierPrefix .
'ident_' . $identifier);
395 return $tags ===
false ? array() : (array)$tags;