Skip to content

Commit 1af17bf

Browse files
authored
Update elcache.php
1 parent caca9ce commit 1af17bf

File tree

1 file changed

+72
-29
lines changed

1 file changed

+72
-29
lines changed

elcache.php

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,32 @@
22
/*
33
Author: Turab Garip
44
https://github.com/Turab
5+
Version: 1.0.1
56
License: GNU GPL v3
67
*/
78

89
namespace Ellibs\Elcache;
910

11+
use Exception;
12+
1013
// Maybe later make a layer and move different types of caches to other files?
1114
class FileCache {
1215

1316
private $path;
1417
private $options;
1518
private $data;
1619
private $hash;
20+
private $init_time;
21+
private $context;
1722

1823
public function __construct(array $options) {
1924

2025
$this->options = $options;
21-
$this->path = $this->options['path'] . '/elcache.php';
26+
$this->init_time = microtime(true);
27+
$this->path = $this->options['path'] . '/elcache.' . $this->options['context'] . '.php';
2228

23-
if (!is_writable($this->options['path'])) {
24-
throw new \Exception('Cache path is not writable!');
25-
}
29+
if (!is_writable($this->options['path']))
30+
throw new Exception('Cache path is not writable!');
2631

2732
// Create an empty cache file if it doesn't exist
2833
if (!file_exists($this->path)) {
@@ -33,15 +38,20 @@ public function __construct(array $options) {
3338
return;
3439
}
3540

36-
$data = file_get_contents($this->path);
41+
list($this->data, $this->hash) = $this->retrieve_file($this->path);
42+
}
43+
44+
private function retrieve_file($file): array {
45+
$data = file_get_contents($file);
3746
$data = substr($data, 9, -6);
38-
$this->hash = crc32($data);
47+
$hash = crc32($data);
3948
$data = unserialize($data);
40-
$this->data = is_array($data) ? $data : []; // If data is corrupt, fall back to an empty array
49+
// If data is corrupt, fall back to an empty array
50+
return array(is_array($data) ? $data : [], $hash);
4151
}
4252

43-
public function set(string $key, $value, int $expiry): void {
44-
$this->data[$key] = array($value, $expiry);
53+
public function set(string $key, $value, int $ttl): void {
54+
$this->data[$key] = array($value, $ttl);
4555
}
4656

4757
public function get(?string $key = null) {
@@ -52,24 +62,36 @@ public function revoke(string $key): void {
5262
unset($this->data[$key]);
5363
}
5464

65+
/**
66+
* @throws Exception
67+
*/
5568
public function purge_expired($then_write = false): void {
5669
$now = time();
5770
foreach ($this->data as $key => $cache) {
58-
list (, $expiry) = $cache;
59-
if ($now > $expiry)
71+
list (, $ttl) = $cache;
72+
if ($now > $ttl)
6073
$this->revoke($key);
6174
}
6275
if ($then_write)
6376
$this->write();
6477
}
6578

79+
/**
80+
* @throws Exception
81+
*/
6682
public function purge_all($hard = false): void {
6783
$this->data = [];
6884
$hard ? unlink($this->path) : $this->write(true);
6985
}
7086

7187
public function write($force = false): void {
88+
$size = $this->options['max_buffer'] * 1024;
7289
$data = serialize($this->data);
90+
91+
if (strlen($data) > $size)
92+
throw new Exception('Cache data is longer than it is allowed to be!
93+
Either increase the allowed size or revoke keys more occasionally.');
94+
7395
$hash = crc32($data);
7496
// Write the file only if it's forced or cache is updated
7597
if ($force || $hash != $this->hash) {
@@ -78,7 +100,16 @@ public function write($force = false): void {
78100
}
79101
}
80102

103+
/**
104+
* @throws Exception
105+
*/
81106
public function __destruct() {
107+
// Check if there were other inits that might have modified the cache
108+
if (filemtime($this->path) > $this->init_time) {
109+
// Re-read the file, because it is modified by another init during our runtime
110+
list($addition, ) = $this->retrieve_file($this->path);
111+
$this->data = array_merge($addition, $this->data);
112+
}
82113
$this->write();
83114
}
84115
}
@@ -95,47 +126,54 @@ class Cache {
95126

96127
private static $cache;
97128
private static $options = array(
98-
// Path to store the cache file in
129+
// Path to store the cache files in
99130
'path' => '/tmp',
100-
// Default expiry is 1 hour
101-
'default_expiry' => 3600
131+
// Default context (Each context will have its own cache file)
132+
'context' => 'default',
133+
// Maximum allowed size for the cache, in Kibibytes
134+
'max_buffer' => 4096,
135+
// Default expiry (time-to-live) is 1 hour
136+
'ttl' => 3600
102137
);
103138

104-
public static function init(?array $options = []) {
139+
/**
140+
* @throws Exception
141+
*/
142+
public static function init(array $options = []) {
105143
if (self::$cache === null) {
106144
self::$options = array_merge(self::$options, $options);
107145
self::$cache = new FileCache(self::$options);
108146
}
109147
self::purge_expired();
110148
}
111149

112-
public static function get(string $key, $with_expiry = false) {
150+
public static function get(string $key, $with_ttl = false) {
113151
$cache = self::$cache->get($key);
114152
if ($cache !== null) {
115-
list($value, $expiry) = $cache;
153+
list($value, $ttl) = $cache;
116154
// Return with expiry information or only the value
117-
if ($expiry > time())
118-
return !$with_expiry ? $value : $cache;
155+
if ($ttl > time())
156+
return !$with_ttl ? $value : $cache;
119157
// If it is expired, don't return but rather destroy
120158
self::revoke($key);
121159
}
122-
return !$with_expiry ? null : [null, 0];
160+
return !$with_ttl ? null : [null, 0];
123161
}
124162

125-
public static function set(string $key, $value = null, ?int $expiry = null) {
126-
if ($expiry === null)
127-
$expiry = self::get_option('default_expiry');
128-
// Non-positive expiry or null value means revoke
129-
if ($expiry < 1 || $value === null) {
130-
self::revoke($key);
163+
public static function set(string $key, $value = null, ?int $ttl = null) {
164+
if ($ttl === null)
165+
$ttl = self::get_option('ttl');
166+
if ($ttl > 0 && $value !== null) {
167+
self::$cache->set($key, $value, $ttl + time());
131168
return;
132169
}
133-
$expiry += time();
134-
self::$cache->set($key, $value, $expiry);
170+
// Non-positive expiry or null value means revoke
171+
self::revoke($key);
135172
}
136173

137174
public static function check(string $key, $value, $strict = false): bool {
138-
return !$strict ? self::get($key) == $value : self::get($key) === $value;
175+
$cache = self::get($key);
176+
return !$strict ? $cache == $value : $cache === $value;
139177
}
140178

141179
public static function revoke(string $key) {
@@ -158,4 +196,9 @@ public static function write($force = false) {
158196
public static function get_option(string $option) {
159197
return self::$options[$option] ?? null;
160198
}
199+
200+
// Kill the cache handler (Maybe for reinitializing with a different context.)
201+
public function close() {
202+
self::$cache = null;
203+
}
161204
}

0 commit comments

Comments
 (0)