CappedMemoryCache.php 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OCP\Cache;
  8. use OCP\ICache;
  9. /**
  10. * In-memory cache with a capacity limit to keep memory usage in check
  11. *
  12. * Uses a simple FIFO expiry mechanism
  13. *
  14. * @since 25.0.0
  15. * @template T
  16. * @template-implements \ArrayAccess<string,T>
  17. */
  18. class CappedMemoryCache implements ICache, \ArrayAccess {
  19. private int $capacity;
  20. /** @var T[] */
  21. private array $cache = [];
  22. /**
  23. * @inheritdoc
  24. * @since 25.0.0
  25. */
  26. public function __construct(int $capacity = 512) {
  27. $this->capacity = $capacity;
  28. }
  29. /**
  30. * @inheritdoc
  31. * @since 25.0.0
  32. */
  33. public function hasKey($key): bool {
  34. return isset($this->cache[$key]);
  35. }
  36. /**
  37. * @return ?T
  38. * @since 25.0.0
  39. */
  40. public function get($key) {
  41. return $this->cache[$key] ?? null;
  42. }
  43. /**
  44. * @inheritdoc
  45. * @param string $key
  46. * @param T $value
  47. * @param int $ttl
  48. * @since 25.0.0
  49. * @return bool
  50. */
  51. public function set($key, $value, $ttl = 0): bool {
  52. if (is_null($key)) {
  53. $this->cache[] = $value;
  54. } else {
  55. $this->cache[$key] = $value;
  56. }
  57. $this->garbageCollect();
  58. return true;
  59. }
  60. /**
  61. * @since 25.0.0
  62. */
  63. public function remove($key): bool {
  64. unset($this->cache[$key]);
  65. return true;
  66. }
  67. /**
  68. * @inheritdoc
  69. * @since 25.0.0
  70. */
  71. public function clear($prefix = ''): bool {
  72. $this->cache = [];
  73. return true;
  74. }
  75. /**
  76. * @since 25.0.0
  77. */
  78. public function offsetExists($offset): bool {
  79. return $this->hasKey($offset);
  80. }
  81. /**
  82. * @inheritdoc
  83. * @return T
  84. * @since 25.0.0
  85. */
  86. #[\ReturnTypeWillChange]
  87. public function &offsetGet($offset) {
  88. return $this->cache[$offset];
  89. }
  90. /**
  91. * @inheritdoc
  92. * @param string $offset
  93. * @param T $value
  94. * @since 25.0.0
  95. */
  96. public function offsetSet($offset, $value): void {
  97. $this->set($offset, $value);
  98. }
  99. /**
  100. * @inheritdoc
  101. * @since 25.0.0
  102. */
  103. public function offsetUnset($offset): void {
  104. $this->remove($offset);
  105. }
  106. /**
  107. * @return T[]
  108. * @since 25.0.0
  109. */
  110. public function getData(): array {
  111. return $this->cache;
  112. }
  113. /**
  114. * @since 25.0.0
  115. */
  116. private function garbageCollect(): void {
  117. while (count($this->cache) > $this->capacity) {
  118. reset($this->cache);
  119. $key = key($this->cache);
  120. $this->remove($key);
  121. }
  122. }
  123. /**
  124. * @inheritdoc
  125. * @since 25.0.0
  126. */
  127. public static function isAvailable(): bool {
  128. return true;
  129. }
  130. }