summaryrefslogtreecommitdiff
path: root/core/classes/cache/FileCache.php
blob: fb7eee5f7570741f3253361ac15dd484ed26f3d1 (plain)
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
<?php

/* FileCache
 * ---
 * Saves serialized data into filesystem.
 * Use it for expensive database-queries.
 * Performanve on a NVMe-SSD drive is really great;
 * (even better than MemCached and Redis)
 * performance on a typical HDD is just fair.
 *
 * NOTE:
 * Memcached and Redis are much faster cache-technologies
 * and generally recommended; but they are not always available;
 * FileCache is (almost) always available;
 * 
 * Before tou decide on your caching technology
 * run some benchmarks.
 */
class FileCache implements Cache_interface
{

    /** store
     * ---
     * serializes and saves data in a file
     * along with TTL (time-to-live)
     */
    public function set(string $key, $data, int $ttl)
    {
        // filename is a hashed 48-hex-digit string
        // probability of collision = exp( (-k*(k-1)) / 2N )
        // ex: for 10tril.samples P(collision) = 1.5E-11%
        $filename = FILECACHE_PATH . sha1($key);

        // Opening file for write
        $h = fopen($filename, 'w');
        if (!$h) throw new Exception('Can not write to cache');

        // Serialize along with the TTL
        $data = serialize( array(
            time() + $ttl,      // array[0] holds expiration time
            $data)              // array[1] holds the actual data
        );

        if (fwrite($h,$data) === false) {
          throw new Exception('Can not write to cache');
        }
        fclose($h);
    }


    /** fetch
     * ---
     * feth data for certain key
     * @param $key (string)
     * @return fetched $data -or- false on failure
     */
    public function get(string $key)
    {
        $filename = FILECACHE_PATH . sha1($key);

        // can not read the cache-file? return false
        if (!file_exists($filename) || !is_readable($filename)) return false;

        $data = file_get_contents($filename);   // get cache-file contents
        $data = @unserialize($data);            // unserialize

        if (!$data) {

           // Unlinking the file when unserializing failed
           unlink($filename);
           return false;

        }

        // checking if the data was expired
        if (time() > $data[0]) {

           // Unlinking
           unlink($filename);
           return false;

        }

        return $data[1];
    }


    public function flush(int $olderThan = 0)
    {
        return false;   // reply false until implementation
    }

}