-
-
Notifications
You must be signed in to change notification settings - Fork 133
/
Apc.php
202 lines (173 loc) · 5.06 KB
/
Apc.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?php
/*
* This file is part of the Stash package.
*
* (c) Robert Hafner <tedivm@tedivm.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Stash\Driver;
use Stash;
use Stash\Exception\RuntimeException;
use Stash\Interfaces\DriverInterface;
/**
* The APC driver is a wrapper for the APC extension, which allows developers to store data in memory.
*
* @package Stash
* @author Robert Hafner <tedivm@tedivm.com>
*/
class Apc implements DriverInterface
{
/**
* Default maximum time an Item will be stored.
*
* @var int
*/
protected $ttl = 300;
/**
* This is an install specific namespace used to segment different applications from interacting with each other
* when using APC. It's generated by creating an md5 of this file's location.
*
* @var string
*/
protected $apcNamespace;
/**
* The number of records \ApcIterator will grab at once.
*
* @var int
*/
protected $chunkSize = 100;
/**
* Initializes the driver.
*
* @throws RuntimeException 'Extension is not installed.'
*/
public function __construct()
{
if (!static::isAvailable()) {
throw new RuntimeException('Extension is not installed.');
}
}
/**
* This function should takes an array which is used to pass option values to the driver.
*
* * ttl - This is the maximum time the item will be stored.
* * namespace - This should be used when multiple projects may use the same library.
*
* @param array $options
* @throws \Stash\Exception\RuntimeException
*/
public function setOptions(array $options = array())
{
if (isset($options['ttl']) && is_numeric($options['ttl'])) {
$this->ttl = (int) $options['ttl'];
}
$this->apcNamespace = isset($options['namespace']) ? $options['namespace'] : md5(__FILE__);
}
/**
* {@inheritdoc}
*/
public function __destruct()
{
}
/**
* {@inheritdoc}
*/
public function getData($key)
{
$keyString = self::makeKey($key);
$success = null;
$data = apc_fetch($keyString, $success);
return $success ? $data : false;
}
/**
* {@inheritdoc}
*/
public function storeData($key, $data, $expiration)
{
$life = $this->getCacheTime($expiration);
return apc_store($this->makeKey($key), array('data' => $data, 'expiration' => $expiration), $life);
}
/**
* {@inheritdoc}
*/
public function clear($key = null)
{
if (!isset($key)) {
return apc_clear_cache('user');
} else {
$keyRegex = '[' . $this->makeKey($key) . '*]';
$chunkSize = isset($this->chunkSize) && is_numeric($this->chunkSize) ? $this->chunkSize : 100;
do {
$emptyIterator = true;
$it = new \APCIterator('user', $keyRegex, \APC_ITER_KEY, $chunkSize);
foreach ($it as $item) {
$emptyIterator = false;
apc_delete($item['key']);
}
} while (!$emptyIterator);
}
return true;
}
/**
* {@inheritdoc}
*/
public function purge()
{
$now = time();
$keyRegex = '[' . $this->makeKey(array()) . '*]';
$chunkSize = isset($this->chunkSize) && is_numeric($this->chunkSize) ? $this->chunkSize : 100;
$it = new \APCIterator('user', $keyRegex, \APC_ITER_KEY, $chunkSize);
foreach ($it as $item) {
$success = null;
$data = apc_fetch($item['key'], $success);
if ($success && is_array($data) && $data['expiration'] <= $now) {
apc_delete($item['key']);
}
}
return true;
}
/**
* This driver is available if the apc extension is present and loaded on the system.
*
* @return bool
*/
public static function isAvailable()
{
// HHVM has some of the APC extension, but not all of it.
if (!class_exists('\APCIterator')) {
return false;
}
return (extension_loaded('apc') && ini_get('apc.enabled'))
&& ((php_sapi_name() !== 'cli') || ini_get('apc.enable_cli'));
}
/**
* Turns a key array into a string.
*
* @param array $key
* @return string
*/
protected function makeKey($key)
{
$keyString = md5(__FILE__) . '::'; // make it unique per install
if (isset($this->apcNamespace)) {
$keyString .= $this->apcNamespace . '::';
}
foreach ($key as $piece) {
$keyString .= $piece . '::';
}
return $keyString;
}
/**
* Converts a timestamp into a TTL.
*
* @param int $expiration
* @return int
*/
protected function getCacheTime($expiration)
{
$life = $expiration - time();
return $this->ttl < $life ? $this->ttl : $life;
}
}