CacheRAM::singleton()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
3
namespace Cachearium\Backend;
4
5
use Cachearium\CacheAbstract;
6
use Cachearium\CacheKey;
7
use Cachearium\CacheData;
8
use Cachearium\CacheLogEnum;
9
use Cachearium\Exceptions\NotCachedException;
10
11
12
/**
13
 * This class caches on local RAM, only for the duration of this execution.
14
 *
15
 * It's a very simple implementation. It's reasonably inneficient because it
16
 * a 3-level array, but it does invalidation correctly.
17
 *
18
 * This is useful for data that is loaded many times in one execution but
19
 * which may change constantly, or in servers that have no external cache
20
 * support for a quick speedup.
21
 */
22
class CacheRAM extends CacheAbstract {
23
	private $storage = array(); // storage
24
25
	private $memoryLimit = 500000000;
26
27
	// @codeCoverageIgnoreStart
28
	/**
29
	 * Cache constructor (this is a singleton).
30
	 *
31
	 * @return CacheRAM The cache singleton.
32
	 *
33
	 */
34
	static public function singleton() {
35
		static $instances;
36
37
		if (!isset($instances)) {
38
			$instances = new CacheRAM();
39
		}
40
		return $instances;
41
	}
42
43
	// Prevent users to clone the instance
44
	public function __clone() {
45
		trigger_error('Cloning is not allowed.', LH_TRIGGER_UNEXPECTED);
46
	}
47
	// @codeCoverageIgnoreEnd
48
49
	/**
50
	 * Constructor.
51
	 * @codeCoverageIgnore
52
	 */
53
	private function __construct() {
54
	}
55
56
	protected function hashKey(CacheKey $k) {
57
		return $this->namespace . $k->base . $k->id . serialize($k->sub);
58
	}
59
60
	/**
61
	 * @param CacheKey $k
62
	 * @throws CacheInvalidDataException
63
	 * @codeCoverageIgnore
64
	 */
65
	private function checkValidArgs(CacheKey $k) {
66
		if (is_array($k->base) || is_array($k->id)) {
67
			throw new CacheInvalidDataException('Invalid get parameter');
68
		}
69
	}
70
71
	/**
72
	 * (non-PHPdoc)
73
	 * @see \Cachearium\CacheAbstract::getData($k)
74
	 */
75
	public function getData(CacheKey $k) {
76
		$cd = CacheData::unserialize($this->get($k));
77
78
		if ($cd->checkUpdateToDate($this)) {
79
			return $cd;
80
		}
81
		$this->delete($k);
82
		throw new NotCachedException();
83
	}
84
85
	public function increment($value, CacheKey $k, $default = 0) {
86
		// @codeCoverageIgnoreStart
87
		if (!$this->enabled) {
88
			return $default;
89
		}
90
		// @codeCoverageIgnoreEnd
91
92
		if (!is_string($k->sub)) {
93
			$sub = md5(serialize($k->sub));
94
		}
95
		else {
96
			$sub = $k->sub;
97
		}
98
		$this->checkValidArgs($k);
99
100
		$idx = $this->namespace . $k->base . $k->id;
101
		if (isset($this->storage[$idx]) && isset($this->storage[$idx][$sub])) {
102
			$this->storage[$idx][$sub] += $value;
103
		}
104
		else {
105
			$this->storage[$idx][$sub] = $default;
106
		}
107
		return $this->storage[$idx][$sub];
108
	}
109
110
	public function get(CacheKey $k) {
111
		// @codeCoverageIgnoreStart
112
		if (!$this->enabled) {
113
			throw new NotCachedException();
114
		}
115
		// @codeCoverageIgnoreEnd
116
117
		if (!is_string($k->sub)) {
118
			$sub = md5(serialize($k->sub));
119
		}
120
		else {
121
			$sub = $k->sub;
122
		}
123
		$this->checkValidArgs($k);
124
125
		$idx = $this->namespace . $k->base . $k->id;
126
		if (isset($this->storage[$idx])
127
			and array_key_exists($sub, $this->storage[$idx])
128
		) {
129
			$this->log(CacheLogEnum::ACCESSED, $k);
130
			return $this->storage[$idx][$sub];
131
		}
132
		$this->log(CacheLogEnum::MISSED, $k);
133
		throw new NotCachedException();
134
	}
135
136
	public function store($data, CacheKey $k, $lifetime = 0) {
137
		// @codeCoverageIgnoreStart
138
		if (!$this->enabled) {
139
			return false;
140
		}
141
		// @codeCoverageIgnoreEnd
142
143
		if (!is_string($k->sub)) {
144
			$sub = md5(serialize($k->sub));
145
		}
146
		else {
147
			$sub = $k->sub;
148
		}
149
		$this->checkValidArgs($k);
150
151
		$this->storage[$this->namespace . $k->base . $k->id][$sub] = $data;
152
		return true;
153
	}
154
155
	public function delete(CacheKey $k) {
156
		if (!is_string($k->sub)) {
157
			$sub = md5(serialize($k->sub));
158
		}
159
		else {
160
			$sub = $k->sub;
161
		}
162
163
		$this->checkValidArgs($k);
164
165
		unset($this->storage[$this->namespace . $k->base . $k->id][$sub]);
166
		return true;
167
	}
168
169
	public function cleanP($base, $id) {
170
		unset($this->storage[$this->namespace . $base . $id]);
171
		return true;
172
	}
173
174
	public function clear() {
175
		$this->storage = array();
176
		return true;
177
	}
178
179
	public function getMemoryLimit($memoryLimit) {
180
		return $this->memoryLimit;
181
	}
182
183
	/**
184
	 *
185
	 * @param integer $memoryLimit
186
	 * @return \Cachearium\Backend\CacheRAM
187
	 */
188
	public function setMemoryLimit($memoryLimit) {
189
		$this->memoryLimit = $memoryLimit;
190
		return $this;
191
	}
192
193
	/**
194
	 * Clears cache if PHP memory usage is above a chosen limit
195
	 * This checks the ENTIRE PHP memory usage, which may be a lot more
196
	 * than what is used by this backend.
197
	 *
198
	 * @return boolean
199
	 */
200
	public function limitRAM() {
201
		if (memory_get_usage() > $this->memoryLimit) {
202
			$this->clear();
203
		}
204
		return true;
205
	}
206
207
	/**
208
	 * (non-PHPdoc)
209
	 * @see CacheAbstract::prefetch()
210
	 * @codeCoverageIgnore
211
	 */
212
	public function prefetch($data) {
213
		// nothing.
214
	}
215
216
	/**
217
	 * @codeCoverageIgnore
218
	 */
219
	public function report() {
220
		if ($this->should_log == false) {
221
			return;
222
		}
223
		echo '<div><h2>Cache RAM system</h2>';
224
		echo '<h3>System is: ' . ($this->enabled ? 'enabled' : 'disabled') . '</h3>';
225
		$stats = array_fill_keys(array_keys(CacheLogEnum::getNames()), 0);
226
		echo '<ul>';
227
		foreach ($this->cache_log as $entry) {
228
			echo '<li>' . CacheLogEnum::getName($entry['status']) . $entry['message'] . '</li>';
229
			$stats[$entry['status']]++;
230
		}
231
		echo '</ul>';
232
233
		echo '<ul>';
234
		foreach ($stats as $key => $val) {
235
			echo '<li>' . CacheLogEnum::getName($key) . '=' . $val . '</li>';
236
		}
237
		echo '</ul>';
238
239
		echo '</ul></div>';
240
	}
241
}
242