Ticket #314: Shmop.php

File Shmop.php, 4.8 kB (added by alexsancho, 11 months ago)

Shmop Cache Driver

Line 
1<?php defined('SYSPATH') or die('No direct script access.');
2/**
3 * Shmop-based Cache driver.
4 *
5 * @package    Cache
6 * @author     Kohana Team
7 * @copyright  (c) 2007-2008 Kohana Team
8 * @license    http://kohanaphp.com/license.html
9 */
10class Cache_Shmop_Driver implements Cache_Driver {
11
12    protected $key;
13    protected $index;
14    protected $segment;
15
16    public function __construct()
17    {
18        if ( ! extension_loaded('shmop'))
19            throw new Kohana_Exception('cache.extension_not_loaded', 'shmop');
20
21        $this->key = Config::item('cache_shmop.key');
22        $this->index = Config::item('cache_shmop.index');
23        $this->segment = Config::item('cache_shmop.segment');
24
25    }
26
27    public function get($key)
28    {
29        if ($shm_id = @shmop_open($this->key, "a", 0, 0))
30        {
31            // Get the size of the structure
32            $size = @shmop_read ($shm_id, 0, 4);
33            $size = hexdec ($size);
34
35            if ($size > 0)
36            {
37            // Read the structure
38            $structure = @shmop_read ($shm_id, 4, $size);
39            $structure = unserialize($structure);
40            @shmop_close ($shm_id);
41
42            if (isset($structure[$key]))
43            {
44                $seg_id = @shmop_open($this->key + $structure[$key], "a", 0, 0);
45
46                if ($seg_id)
47                {
48                    // Get the size of the structure
49                    $cache_size = @shmop_read ($seg_id, 0, 4);
50                    $cache_size = hexdec ($cache_size);
51                    $cache_data = @shmop_read ($seg_id, 4, $cache_size);
52                    @shmop_close($seg_id);
53
54                    return $cache_data;
55                }
56            }
57            }
58            @shmop_close ($shm_id);
59        }
60        return false;
61    }
62
63    public function set($id, $data, $tags, $expiration)
64    {
65        count($tags) and Log::add('error', 'Cache: tags are unsupported by the APC driver');
66
67        if ($struc_id = shmop_open($this->key, "c", 0644, $this->index))
68        {
69            // Get the size of the structure
70            $size = @shmop_read ($struc_id, 0, 4);
71            $size = hexdec ($size);
72
73            // Fetch the structure
74            $structure = array();
75
76            if ($size > 0)
77            {
78            $structure = shmop_read ($struc_id, 4, $size);
79            $structure = unserialize($structure);
80            }
81
82            $highest = 0;
83            reset ($structure);
84            while (list($k, $v) = each ($structure))
85            {
86            if ($v > $highest)
87            {
88                $highest = $v;
89            }
90            }
91
92            for ($i = 1; $i <= $highest + 1; $i++)
93            {
94            if ( ! in_array($i, $structure))
95            {
96                $segment = $i;
97                break;
98            }
99            }
100
101            $delete =  (isset($structure[$id])) ? $structure[$id] : false;
102
103            if ($seg_id = shmop_open($this->key + $segment, "c", 0644, $this->segment))
104            {
105            // Store data
106            $seg_size = strlen($data);
107            $seg_size = sprintf ('%04X', $seg_size);
108
109            shmop_write($seg_id, $seg_size, 0);
110            shmop_write($seg_id, $data, 4);
111            shmop_close($seg_id);
112
113            // Update structure
114            $structure[$id] = $segment;
115
116            // Store the structure
117            $struc_data = serialize ($structure);
118            $struc_size = strlen($struc_data);
119            $struc_size = sprintf ('%04X', $struc_size);
120
121            shmop_write($struc_id, $struc_size, 0);
122            shmop_write($struc_id, $struc_data, 4);
123            shmop_close($struc_id);
124
125            // Delete old segment
126            if ($delete)
127            {
128                $del_id = shmop_open($this->key + $delete, "w", 0, 0);
129                shmop_delete($del_id);
130                shmop_close($del_id);
131            }
132            return true;
133            }
134            shmop_close($struc_id);
135        }
136        return false;
137    }
138
139    public function find($tag)
140    {
141        return FALSE;
142    }
143
144    public function delete($id, $tag = FALSE)
145    {
146        if($struc_id = shmop_open($this->key, "c", 0644, $this->index))
147        {
148            $size = @shmop_read ($struc_id, 0, 4);
149            $size = hexdec ($size);
150           
151            if($size > 0)
152            {
153            $structure = shmop_read ($struc_id, 4, $size);
154            $structure = unserialize($structure);
155           
156            if ($id === true)
157            {   
158                while(list($k, $v) = each($structure))
159                {
160                // Delete old segment
161                $del_id = shmop_open($this->key + $v, "w", 0, 0);
162                shmop_delete($del_id);
163                shmop_close($del_id);
164                }
165                $structure = array();
166                // Store the structure
167                $struc_data = serialize($structure);
168                $struc_size = strlen($struc_data);
169                $struc_size = sprintf ('%04X', $struc_size);
170                shmop_write($struc_id, $struc_size, 0);
171                shmop_write($struc_id, $struc_data, 4);
172                shmop_close($struc_id);
173               
174                return true;
175            }
176            elseif ($tag == false and isset($structure[$id]))
177            {
178                $delete = $structure[$id];
179                // Update structure
180                unset($structure[$id]);
181                // Store the structure
182                $struc_data = serialize($structure);
183                $struc_size = strlen($struc_data);
184                $struc_size = sprintf('%04X', $struc_size);
185                shmop_write($struc_id, $struc_size, 0);
186                shmop_write($struc_id, $struc_data, 4);
187                shmop_close($struc_id);
188                // Delete old segment
189                $del_id = shmop_open($this->key + $delete, "w", 0, 0);
190                shmop_delete($del_id);
191                shmop_close($del_id);
192
193                return true;
194            }
195            else
196            {
197                    return true;
198            }
199            }
200        }
201        return false;
202    }
203
204    public function delete_expired()
205    {
206        return TRUE;
207    }
208
209} // End Cache Shmop Driver