Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Cache / Storage / Adapter / Apc.php
blob2196ff5f43e3f1ddd5118022e3df2978343c52ba
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Cache\Storage\Adapter;
12 use APCIterator as BaseApcIterator;
13 use stdClass;
14 use Traversable;
15 use Zend\Cache\Exception;
16 use Zend\Cache\Storage\AvailableSpaceCapableInterface;
17 use Zend\Cache\Storage\Capabilities;
18 use Zend\Cache\Storage\ClearByNamespaceInterface;
19 use Zend\Cache\Storage\ClearByPrefixInterface;
20 use Zend\Cache\Storage\FlushableInterface;
21 use Zend\Cache\Storage\IterableInterface;
22 use Zend\Cache\Storage\TotalSpaceCapableInterface;
24 class Apc extends AbstractAdapter implements
25 AvailableSpaceCapableInterface,
26 ClearByNamespaceInterface,
27 ClearByPrefixInterface,
28 FlushableInterface,
29 IterableInterface,
30 TotalSpaceCapableInterface
32 /**
33 * Buffered total space in bytes
35 * @var null|int|float
37 protected $totalSpace;
39 /**
40 * Constructor
42 * @param null|array|Traversable|ApcOptions $options
43 * @throws Exception\ExceptionInterface
45 public function __construct($options = null)
47 if (version_compare('3.1.6', phpversion('apc')) > 0) {
48 throw new Exception\ExtensionNotLoadedException("Missing ext/apc >= 3.1.6");
51 $enabled = ini_get('apc.enabled');
52 if (PHP_SAPI == 'cli') {
53 $enabled = $enabled && (bool) ini_get('apc.enable_cli');
56 if (!$enabled) {
57 throw new Exception\ExtensionNotLoadedException(
58 "ext/apc is disabled - see 'apc.enabled' and 'apc.enable_cli'"
62 parent::__construct($options);
65 /* options */
67 /**
68 * Set options.
70 * @param array|Traversable|ApcOptions $options
71 * @return Apc
72 * @see getOptions()
74 public function setOptions($options)
76 if (!$options instanceof ApcOptions) {
77 $options = new ApcOptions($options);
80 return parent::setOptions($options);
83 /**
84 * Get options.
86 * @return ApcOptions
87 * @see setOptions()
89 public function getOptions()
91 if (!$this->options) {
92 $this->setOptions(new ApcOptions());
94 return $this->options;
97 /* TotalSpaceCapableInterface */
99 /**
100 * Get total space in bytes
102 * @return int|float
104 public function getTotalSpace()
106 if ($this->totalSpace === null) {
107 $smaInfo = apc_sma_info(true);
108 $this->totalSpace = $smaInfo['num_seg'] * $smaInfo['seg_size'];
111 return $this->totalSpace;
114 /* AvailableSpaceCapableInterface */
117 * Get available space in bytes
119 * @return int|float
121 public function getAvailableSpace()
123 $smaInfo = apc_sma_info(true);
124 return $smaInfo['avail_mem'];
127 /* IterableInterface */
130 * Get the storage iterator
132 * @return ApcIterator
134 public function getIterator()
136 $options = $this->getOptions();
137 $namespace = $options->getNamespace();
138 $prefix = '';
139 $pattern = null;
140 if ($namespace !== '') {
141 $prefix = $namespace . $options->getNamespaceSeparator();
142 $pattern = '/^' . preg_quote($prefix, '/') . '/';
145 $baseIt = new BaseApcIterator('user', $pattern, 0, 1, APC_LIST_ACTIVE);
146 return new ApcIterator($this, $baseIt, $prefix);
149 /* FlushableInterface */
152 * Flush the whole storage
154 * @return bool
156 public function flush()
158 return apc_clear_cache('user');
161 /* ClearByNamespaceInterface */
164 * Remove items by given namespace
166 * @param string $namespace
167 * @return bool
169 public function clearByNamespace($namespace)
171 $namespace = (string) $namespace;
172 if ($namespace === '') {
173 throw new Exception\InvalidArgumentException('No namespace given');
176 $options = $this->getOptions();
177 $prefix = $namespace . $options->getNamespaceSeparator();
178 $pattern = '/^' . preg_quote($prefix, '/') . '/';
179 return apc_delete(new BaseApcIterator('user', $pattern, 0, 1, APC_LIST_ACTIVE));
182 /* ClearByPrefixInterface */
185 * Remove items matching given prefix
187 * @param string $prefix
188 * @return bool
190 public function clearByPrefix($prefix)
192 $prefix = (string) $prefix;
193 if ($prefix === '') {
194 throw new Exception\InvalidArgumentException('No prefix given');
197 $options = $this->getOptions();
198 $namespace = $options->getNamespace();
199 $nsPrefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
200 $pattern = '/^' . preg_quote($nsPrefix . $prefix, '/') . '/';
201 return apc_delete(new BaseApcIterator('user', $pattern, 0, 1, APC_LIST_ACTIVE));
204 /* reading */
207 * Internal method to get an item.
209 * @param string $normalizedKey
210 * @param bool $success
211 * @param mixed $casToken
212 * @return mixed Data on success, null on failure
213 * @throws Exception\ExceptionInterface
215 protected function internalGetItem(& $normalizedKey, & $success = null, & $casToken = null)
217 $options = $this->getOptions();
218 $namespace = $options->getNamespace();
219 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
220 $internalKey = $prefix . $normalizedKey;
221 $result = apc_fetch($internalKey, $success);
223 if (!$success) {
224 return null;
227 $casToken = $result;
228 return $result;
232 * Internal method to get multiple items.
234 * @param array $normalizedKeys
235 * @return array Associative array of keys and values
236 * @throws Exception\ExceptionInterface
238 protected function internalGetItems(array & $normalizedKeys)
240 $options = $this->getOptions();
241 $namespace = $options->getNamespace();
242 if ($namespace === '') {
243 return apc_fetch($normalizedKeys);
246 $prefix = $namespace . $options->getNamespaceSeparator();
247 $internalKeys = array();
248 foreach ($normalizedKeys as $normalizedKey) {
249 $internalKeys[] = $prefix . $normalizedKey;
252 $fetch = apc_fetch($internalKeys);
254 // remove namespace prefix
255 $prefixL = strlen($prefix);
256 $result = array();
257 foreach ($fetch as $internalKey => & $value) {
258 $result[substr($internalKey, $prefixL)] = $value;
261 return $result;
265 * Internal method to test if an item exists.
267 * @param string $normalizedKey
268 * @return bool
269 * @throws Exception\ExceptionInterface
271 protected function internalHasItem(& $normalizedKey)
273 $options = $this->getOptions();
274 $namespace = $options->getNamespace();
275 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
276 return apc_exists($prefix . $normalizedKey);
280 * Internal method to test multiple items.
282 * @param array $normalizedKeys
283 * @return array Array of found keys
284 * @throws Exception\ExceptionInterface
286 protected function internalHasItems(array & $normalizedKeys)
288 $options = $this->getOptions();
289 $namespace = $options->getNamespace();
290 if ($namespace === '') {
291 // array_filter with no callback will remove entries equal to FALSE
292 return array_keys(array_filter(apc_exists($normalizedKeys)));
295 $prefix = $namespace . $options->getNamespaceSeparator();
296 $internalKeys = array();
297 foreach ($normalizedKeys as $normalizedKey) {
298 $internalKeys[] = $prefix . $normalizedKey;
301 $exists = apc_exists($internalKeys);
302 $result = array();
303 $prefixL = strlen($prefix);
304 foreach ($exists as $internalKey => $bool) {
305 if ($bool === true) {
306 $result[] = substr($internalKey, $prefixL);
310 return $result;
314 * Get metadata of an item.
316 * @param string $normalizedKey
317 * @return array|bool Metadata on success, false on failure
318 * @throws Exception\ExceptionInterface
320 protected function internalGetMetadata(& $normalizedKey)
322 $options = $this->getOptions();
323 $namespace = $options->getNamespace();
324 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
325 $internalKey = $prefix . $normalizedKey;
327 // @see http://pecl.php.net/bugs/bug.php?id=22564
328 if (!apc_exists($internalKey)) {
329 $metadata = false;
330 } else {
331 $format = APC_ITER_ALL ^ APC_ITER_VALUE ^ APC_ITER_TYPE ^ APC_ITER_REFCOUNT;
332 $regexp = '/^' . preg_quote($internalKey, '/') . '$/';
333 $it = new BaseApcIterator('user', $regexp, $format, 100, APC_LIST_ACTIVE);
334 $metadata = $it->current();
337 if (!$metadata) {
338 return false;
341 $this->normalizeMetadata($metadata);
342 return $metadata;
346 * Get metadata of multiple items
348 * @param array $normalizedKeys
349 * @return array Associative array of keys and metadata
351 * @triggers getMetadatas.pre(PreEvent)
352 * @triggers getMetadatas.post(PostEvent)
353 * @triggers getMetadatas.exception(ExceptionEvent)
355 protected function internalGetMetadatas(array & $normalizedKeys)
357 $keysRegExp = array();
358 foreach ($normalizedKeys as $normalizedKey) {
359 $keysRegExp[] = preg_quote($normalizedKey, '/');
362 $options = $this->getOptions();
363 $namespace = $options->getNamespace();
364 if ($namespace === '') {
365 $pattern = '/^(' . implode('|', $keysRegExp) . ')' . '$/';
366 } else {
367 $prefix = $namespace . $options->getNamespaceSeparator();
368 $pattern = '/^' . preg_quote($prefix, '/') . '(' . implode('|', $keysRegExp) . ')' . '$/';
370 $format = APC_ITER_ALL ^ APC_ITER_VALUE ^ APC_ITER_TYPE ^ APC_ITER_REFCOUNT;
371 $it = new BaseApcIterator('user', $pattern, $format, 100, APC_LIST_ACTIVE);
372 $result = array();
373 $prefixL = strlen($prefix);
374 foreach ($it as $internalKey => $metadata) {
375 // @see http://pecl.php.net/bugs/bug.php?id=22564
376 if (!apc_exists($internalKey)) {
377 continue;
380 $this->normalizeMetadata($metadata);
381 $result[substr($internalKey, $prefixL)] = & $metadata;
384 return $result;
387 /* writing */
390 * Internal method to store an item.
392 * @param string $normalizedKey
393 * @param mixed $value
394 * @return bool
395 * @throws Exception\ExceptionInterface
397 protected function internalSetItem(& $normalizedKey, & $value)
399 $options = $this->getOptions();
400 $namespace = $options->getNamespace();
401 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
402 $internalKey = $prefix . $normalizedKey;
403 $ttl = $options->getTtl();
405 if (!apc_store($internalKey, $value, $ttl)) {
406 $type = is_object($value) ? get_class($value) : gettype($value);
407 throw new Exception\RuntimeException(
408 "apc_store('{$internalKey}', <{$type}>, {$ttl}) failed"
412 return true;
416 * Internal method to store multiple items.
418 * @param array $normalizedKeyValuePairs
419 * @return array Array of not stored keys
420 * @throws Exception\ExceptionInterface
422 protected function internalSetItems(array & $normalizedKeyValuePairs)
424 $options = $this->getOptions();
425 $namespace = $options->getNamespace();
426 if ($namespace === '') {
427 return array_keys(apc_store($normalizedKeyValuePairs, null, $options->getTtl()));
430 $prefix = $namespace . $options->getNamespaceSeparator();
431 $internalKeyValuePairs = array();
432 foreach ($normalizedKeyValuePairs as $normalizedKey => &$value) {
433 $internalKey = $prefix . $normalizedKey;
434 $internalKeyValuePairs[$internalKey] = &$value;
437 $failedKeys = apc_store($internalKeyValuePairs, null, $options->getTtl());
438 $failedKeys = array_keys($failedKeys);
440 // remove prefix
441 $prefixL = strlen($prefix);
442 foreach ($failedKeys as & $key) {
443 $key = substr($key, $prefixL);
446 return $failedKeys;
450 * Add an item.
452 * @param string $normalizedKey
453 * @param mixed $value
454 * @return bool
455 * @throws Exception\ExceptionInterface
457 protected function internalAddItem(& $normalizedKey, & $value)
459 $options = $this->getOptions();
460 $namespace = $options->getNamespace();
461 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
462 $internalKey = $prefix . $normalizedKey;
463 $ttl = $options->getTtl();
465 if (!apc_add($internalKey, $value, $ttl)) {
466 if (apc_exists($internalKey)) {
467 return false;
470 $type = is_object($value) ? get_class($value) : gettype($value);
471 throw new Exception\RuntimeException(
472 "apc_add('{$internalKey}', <{$type}>, {$ttl}) failed"
476 return true;
480 * Internal method to add multiple items.
482 * @param array $normalizedKeyValuePairs
483 * @return array Array of not stored keys
484 * @throws Exception\ExceptionInterface
486 protected function internalAddItems(array & $normalizedKeyValuePairs)
488 $options = $this->getOptions();
489 $namespace = $options->getNamespace();
490 if ($namespace === '') {
491 return array_keys(apc_add($normalizedKeyValuePairs, null, $options->getTtl()));
494 $prefix = $namespace . $options->getNamespaceSeparator();
495 $internalKeyValuePairs = array();
496 foreach ($normalizedKeyValuePairs as $normalizedKey => $value) {
497 $internalKey = $prefix . $normalizedKey;
498 $internalKeyValuePairs[$internalKey] = $value;
501 $failedKeys = apc_add($internalKeyValuePairs, null, $options->getTtl());
502 $failedKeys = array_keys($failedKeys);
504 // remove prefix
505 $prefixL = strlen($prefix);
506 foreach ($failedKeys as & $key) {
507 $key = substr($key, $prefixL);
510 return $failedKeys;
514 * Internal method to replace an existing item.
516 * @param string $normalizedKey
517 * @param mixed $value
518 * @return bool
519 * @throws Exception\ExceptionInterface
521 protected function internalReplaceItem(& $normalizedKey, & $value)
523 $options = $this->getOptions();
524 $namespace = $options->getNamespace();
525 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
526 $internalKey = $prefix . $normalizedKey;
528 if (!apc_exists($internalKey)) {
529 return false;
532 $ttl = $options->getTtl();
533 if (!apc_store($internalKey, $value, $ttl)) {
534 $type = is_object($value) ? get_class($value) : gettype($value);
535 throw new Exception\RuntimeException(
536 "apc_store('{$internalKey}', <{$type}>, {$ttl}) failed"
540 return true;
544 * Internal method to remove an item.
546 * @param string $normalizedKey
547 * @return bool
548 * @throws Exception\ExceptionInterface
550 protected function internalRemoveItem(& $normalizedKey)
552 $options = $this->getOptions();
553 $namespace = $options->getNamespace();
554 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
555 return apc_delete($prefix . $normalizedKey);
559 * Internal method to remove multiple items.
561 * @param array $normalizedKeys
562 * @return array Array of not removed keys
563 * @throws Exception\ExceptionInterface
565 protected function internalRemoveItems(array & $normalizedKeys)
567 $options = $this->getOptions();
568 $namespace = $options->getNamespace();
569 if ($namespace === '') {
570 return apc_delete($normalizedKeys);
573 $prefix = $namespace . $options->getNamespaceSeparator();
574 $internalKeys = array();
575 foreach ($normalizedKeys as $normalizedKey) {
576 $internalKeys[] = $prefix . $normalizedKey;
579 $failedKeys = apc_delete($internalKeys);
581 // remove prefix
582 $prefixL = strlen($prefix);
583 foreach ($failedKeys as & $key) {
584 $key = substr($key, $prefixL);
587 return $failedKeys;
591 * Internal method to increment an item.
593 * @param string $normalizedKey
594 * @param int $value
595 * @return int|bool The new value on success, false on failure
596 * @throws Exception\ExceptionInterface
598 protected function internalIncrementItem(& $normalizedKey, & $value)
600 $options = $this->getOptions();
601 $namespace = $options->getNamespace();
602 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
603 $internalKey = $prefix . $normalizedKey;
604 $ttl = $options->getTtl();
605 $value = (int) $value;
606 $newValue = apc_inc($internalKey, $value);
608 // initial value
609 if ($newValue === false) {
610 $ttl = $options->getTtl();
611 $newValue = $value;
612 if (!apc_add($internalKey, $newValue, $ttl)) {
613 throw new Exception\RuntimeException(
614 "apc_add('{$internalKey}', {$newValue}, {$ttl}) failed"
619 return $newValue;
623 * Internal method to decrement an item.
625 * @param string $normalizedKey
626 * @param int $value
627 * @return int|bool The new value on success, false on failure
628 * @throws Exception\ExceptionInterface
630 protected function internalDecrementItem(& $normalizedKey, & $value)
632 $options = $this->getOptions();
633 $namespace = $options->getNamespace();
634 $prefix = ($namespace === '') ? '' : $namespace . $options->getNamespaceSeparator();
635 $internalKey = $prefix . $normalizedKey;
636 $value = (int) $value;
637 $newValue = apc_dec($internalKey, $value);
639 // initial value
640 if ($newValue === false) {
641 $ttl = $options->getTtl();
642 $newValue = -$value;
643 if (!apc_add($internalKey, $newValue, $ttl)) {
644 throw new Exception\RuntimeException(
645 "apc_add('{$internalKey}', {$newValue}, {$ttl}) failed"
650 return $newValue;
653 /* status */
656 * Internal method to get capabilities of this adapter
658 * @return Capabilities
660 protected function internalGetCapabilities()
662 if ($this->capabilities === null) {
663 $marker = new stdClass();
664 $capabilities = new Capabilities(
665 $this,
666 $marker,
667 array(
668 'supportedDatatypes' => array(
669 'NULL' => true,
670 'boolean' => true,
671 'integer' => true,
672 'double' => true,
673 'string' => true,
674 'array' => true,
675 'object' => 'object',
676 'resource' => false,
678 'supportedMetadata' => array(
679 'internal_key',
680 'atime', 'ctime', 'mtime', 'rtime',
681 'size', 'hits', 'ttl',
683 'minTtl' => 1,
684 'maxTtl' => 0,
685 'staticTtl' => true,
686 'ttlPrecision' => 1,
687 'useRequestTime' => (bool) ini_get('apc.use_request_time'),
688 'expiredRead' => false,
689 'maxKeyLength' => 5182,
690 'namespaceIsPrefix' => true,
691 'namespaceSeparator' => $this->getOptions()->getNamespaceSeparator(),
695 // update namespace separator on change option
696 $this->getEventManager()->attach('option', function ($event) use ($capabilities, $marker) {
697 $params = $event->getParams();
699 if (isset($params['namespace_separator'])) {
700 $capabilities->setNamespaceSeparator($marker, $params['namespace_separator']);
704 $this->capabilities = $capabilities;
705 $this->capabilityMarker = $marker;
708 return $this->capabilities;
711 /* internal */
714 * Normalize metadata to work with APC
716 * @param array $metadata
717 * @return void
719 protected function normalizeMetadata(array & $metadata)
721 $metadata['internal_key'] = $metadata['key'];
722 $metadata['ctime'] = $metadata['creation_time'];
723 $metadata['atime'] = $metadata['access_time'];
724 $metadata['rtime'] = $metadata['deletion_time'];
725 $metadata['size'] = $metadata['mem_size'];
726 $metadata['hits'] = $metadata['num_hits'];
728 unset(
729 $metadata['key'],
730 $metadata['creation_time'],
731 $metadata['access_time'],
732 $metadata['deletion_time'],
733 $metadata['mem_size'],
734 $metadata['num_hits']