source: trunk/common/cache.php @ 1164

Revision 1164, 8.2 KB checked in by btataroiu@…, 3 weeks ago (diff)

Make infoarena compatible with HPHP.

  • Implemented APC caching support since eaccelerator is not compatible with HPHP and although we support memcached, we do not use it on live.
  • Replaced instances of create_function_cached with php anonymous functions. This bumps the PHP version requirement to 5.3, but it allows the code to work with HPHP, since dynamic function generation is replaced with staticly analyzable functions. This also removes a horrible, terrible hack in Textile.php which was storing the current instance of the Textile class being processed as a static variable so that it could be accessed by anonymous functions.
  • Replaced occurrences of assert with log_assert.
  • When running under HPHP, IA_HPHP_ENV is defined and is used to bypass some incompatible code (redundant ini configuration checks).
  • Fixed some includes that were dependent on the working directory being www/
  • Included a sample HPHP configuration file and a Makefile with compilation commands.

REVIEW URL:  http://reviewboard.infoarena.ro/r/182/

  • Property svn:eol-style set to native
Line 
1<?php
2require_once(IA_ROOT_DIR . "common/string.php");
3
4// Check if there is something in the cache newer that date.
5// If date is null age doesn't matter.
6// Date must be unix timestamp.
7// Old stuff is deleted.
8//
9// Only returns true/false.
10
11// Used internally to determine file path from cache_id
12function _disk_cache_path($cache_id) {
13    return IA_ROOT_DIR . "cache/" . $cache_id;
14}
15
16// Recursively delete directories
17function _recursive_delete($path) {
18    $path = realpath($path);
19    log_assert($path != IA_ROOT_DIR . "cache/" &&
20               starts_with($path, IA_ROOT_DIR . "cache/"));
21    foreach (glob($path . "/*") as $file_name) {
22        if (is_dir($file_name)) {
23            _recursive_delete($file_name);
24        } else if (is_file($file_name)) {
25            unlink($file_name);
26        }
27    }
28    rmdir($path);
29}
30
31function disk_cache_has($cache_id, $date = null) {
32    $file_name = _disk_cache_path($cache_id);
33
34    if (!@is_readable($file_name)) {
35        return false;
36    } else {
37        if (is_null($date) || $date === false) {
38            return true;
39        }
40
41        // Check mtime
42        $mtime = @filemtime($file_name);
43
44        // Delete old stuff.
45        if ($mtime === false || $mtime < $date) {
46            @unlink($fname);
47            return false;
48        } else {
49            return true;
50        }
51    }
52}
53
54// Get an object from the cache, or FALSE if nothing is found.
55function disk_cache_get($cache_id) {
56    $file_name = _disk_cache_path($cache_id);
57
58    if (@is_readable($file_name)) {
59        if (IA_LOG_DISK_CACHE) {
60            log_print("CACHE: DISK: HIT on $cache_id");
61        }
62        return file_get_contents($file_name);
63    } else {
64        if (IA_LOG_DISK_CACHE) {
65            log_print("CACHE: DISK: MISS on $cache_id");
66        }
67        return false;
68    }
69}
70
71// If $cache_id is in cache, then pass it to the client.
72// Fails if not found.
73function disk_cache_serve($cache_id, $http_file_name, $mime_type = null) {
74    require_once(IA_ROOT_DIR . 'www/utilities.php');
75    $file_name = _disk_cache_path($cache_id);
76
77    if (IA_LOG_DISK_CACHE) {
78        log_print("CACHE: DISK: SERVE $cache_id");
79    }
80    http_serve($file_name, $http_file_name, $mime_type);
81}
82
83// Place an object in the cache.
84// Object should expire after $ttl, but it's only a hint.
85// Always returns $buffer.
86function disk_cache_set($cache_id, $buffer, $ttl = 0) {
87    $file_name = _disk_cache_path($cache_id);
88
89    if (!is_dir(dirname($file_name))) {
90        log_assert(!file_exists(dirname($file_name)),
91                   "Cache directory contains invalid files");
92
93        $old_umask = umask(0);
94        @mkdir(dirname($file_name), 0777, true);
95        umask($old_umask);
96    }
97    $ret = @file_put_contents($file_name, $buffer, LOCK_EX);
98
99    if (IA_LOG_DISK_CACHE) {
100        if ($ret) {
101            log_print("CACHE: DISK: SET $cache_id");
102        } else {
103            log_warn("CACHE: DISK: FAIL SET $cache_id");
104        }
105    }
106
107    return $buffer;
108}
109
110// Delete something from the disk cache.
111function disk_cache_delete($cache_id) {
112    $file_name = _disk_cache_path($cache_id);
113    @unlink($file_name);
114}
115
116// Delete the entire disk cache
117function disk_cache_purge() {
118    foreach (glob(IA_ROOT_DIR . "cache/*", GLOB_ONLYDIR) as $dir_name) {
119        _recursive_delete($dir_name);
120    }
121
122    foreach (glob(IA_ROOT_DIR . "cache/*") as $file_name) {
123        unlink($file_name);
124    }
125}
126
127//
128// Memory caching implementation depends on IA_MEM_CACHE_METHOD.
129// There are only four functions, which should be enough for just about everything.
130//
131// You can store arrays, ints, string, null but not booleans because they're
132// used by the mem_cache_get function. You could store booleans as 0/1 however.
133//
134// FUNCTIONS:
135//      mem_cache_get gets an object from the cache, or FALSE if not found.
136//      A null result means it a null value was stored.
137//
138//      mem_cache_set places an object in the cache with a certain ttl and
139//      returns the untouched object. Booleans can't be stored.
140//
141//      mem_cache_delete removes something from the cache, use this when the
142//      object is no longer valid.
143//
144//      mem_cache_purge deletes everything from the cache. Try to avoid calling it.
145//
146if (IA_MEM_CACHE_METHOD == 'none') {
147
148    // Fake cache implementation/
149
150    function mem_cache_get($cache_id) {
151        return false;
152    }
153
154    function mem_cache_set($cache_id, $object, $ttl = IA_MEM_CACHE_EXPIRATION) {
155        return $object;
156    }
157
158    function mem_cache_delete($cache_id) {
159    }
160
161    function mem_cache_purge() {
162    }
163
164} else if (IA_MEM_CACHE_METHOD == 'eaccelerator') {
165
166    // eAccelerator SHM memory cache
167
168    function mem_cache_get($cache_id) {
169        $res = eaccelerator_get($cache_id);
170        if ($res === null) {
171            if (IA_LOG_MEM_CACHE) {
172                log_print("MEM CACHE: miss on $cache_id");
173            }
174            return false;
175        } else {
176            if (IA_LOG_MEM_CACHE) {
177                log_print("MEM CACHE: hit on $cache_id");
178            }
179            return unserialize($res);
180        }
181    }
182
183    function mem_cache_set($cache_id, $object, $ttl = IA_MEM_CACHE_EXPIRATION) {
184        log_assert($object !== 'false', "Can't cache false values");
185        eaccelerator_put($cache_id, serialize($object), $ttl);
186
187        if (IA_LOG_MEM_CACHE) {
188            log_print("MEM CACHE: store $cache_id");
189        }
190
191        return $object;
192    }
193
194    function mem_cache_delete($cache_id) {
195        eaccelerator_rm($cache_id);
196        if (IA_LOG_MEM_CACHE) {
197            log_print("MEM CACHE: delete $cache_id");
198        }
199    }
200
201    // Purge the entire SHM cache.
202    // FIXME: This does not work
203    function mem_cache_purge() {
204        if (IA_LOG_MEM_CACHE) {
205            log_print("MEM CACHE: purge");
206        }
207        eaccelerator_gc();
208    }
209
210} else if (IA_MEM_CACHE_METHOD == 'memcached') {
211
212    // memcached cache implementation.
213
214    $_memcache = memcache_pconnect('localhost');
215
216    function mem_cache_get($cache_id) {
217        global $_memcache;
218        $res = memcache_get($_memcache, $cache_id);
219        if ($res === false) {
220            if (IA_LOG_MEM_CACHE) {
221                log_print("MEM CACHE: miss on $cache_id");
222            }
223            return false;
224        } else {
225            if (IA_LOG_MEM_CACHE) {
226                log_print("MEM CACHE: hit on $cache_id");
227            }
228            return unserialize($res);
229        }
230    }
231
232    function mem_cache_set($cache_id, $object, $ttl = IA_MEM_CACHE_EXPIRATION) {
233        global $_memcache;
234        log_assert($object !== 'false', "Can't cache false values");
235        memcache_set($_memcache, $cache_id, serialize($object), 0, $ttl);
236
237        if (IA_LOG_MEM_CACHE) {
238            log_print("MEM CACHE: store $cache_id");
239        }
240        return $object;
241    }
242
243    function mem_cache_delete($cache_id) {
244        global $_memcache;
245        memcache_delete($_memcache, $cache_id);
246
247        if (IA_LOG_MEM_CACHE) {
248            log_print("MEM CACHE: delete $cache_id");
249        }
250    }
251
252    function mem_cache_purge() {
253        global $_memcache;
254        memcache_flush($_memcache);
255
256        if (IA_LOG_MEM_CACHE) {
257            log_print("MEM CACHE: purge");
258        }
259    }
260
261} else if (IA_MEM_CACHE_METHOD == 'apc') {
262    // APC cache implementation
263    function mem_cache_get($cache_id) {
264        $res = apc_fetch($cache_id);
265        if ($res === false) {
266            if (IA_LOG_MEM_CACHE) {
267                log_print("MEM CACHE: miss on $cache_id");
268            }
269            return false;
270        } else {
271            if (IA_LOG_MEM_CACHE) {
272                log_print("MEM CACHE: hit on $cache_id");
273            }
274            return unserialize($res);
275        }
276    }
277
278    function mem_cache_set($cache_id, $object, $ttl = IA_MEM_CACHE_EXPIRATION) {
279        log_assert($object !== 'false', "Can't cache false values");
280        apc_store($cache_id, serialize($object), $ttl);
281
282        if (IA_LOG_MEM_CACHE) {
283            log_print("MEM CACHE: store $cache_id");
284        }
285        return $object;
286    }
287
288    function mem_cache_delete($cache_id) {
289        apc_delete($cache_id);
290        if (IA_LOG_MEM_CACHE) {
291            log_print("MEM CACHE: delete $cache_id");
292        }
293    }
294
295    function mem_cache_purge() {
296        if (IA_LOG_MEM_CACHE) {
297            log_print("MEM CACHE: purge");
298        }
299        apc_clear_cache();
300    }
301}
302
303?>
Note: See TracBrowser for help on using the repository browser.