1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 3 4/** 5 * DNS Library for handling lookups and updates. 6 * 7 * PHP Version 5 8 * 9 * Copyright (c) 2010, Mike Pultz <mike@mikepultz.com>. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * * Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * * Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in 21 * the documentation and/or other materials provided with the 22 * distribution. 23 * 24 * * Neither the name of Mike Pultz nor the names of his contributors 25 * may be used to endorse or promote products derived from this 26 * software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 32 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 34 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 36 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGE. 40 * 41 * @category Networking 42 * @package Net_DNS2 43 * @author Mike Pultz <mike@mikepultz.com> 44 * @copyright 2010 Mike Pultz <mike@mikepultz.com> 45 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 46 * @version SVN: $Id: Shm.php 160 2012-07-18 03:57:32Z mike.pultz $ 47 * @link http://pear.php.net/package/Net_DNS2 48 * @since File available since Release 1.1.0 49 * 50 */ 51 52/** 53 * Shared Memory-based caching for the Net_DNS2_Cache class 54 * 55 * @category Networking 56 * @package Net_DNS2 57 * @author Mike Pultz <mike@mikepultz.com> 58 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 59 * @link http://pear.php.net/package/Net_DNS2 60 * @see Net_DNS2_Packet 61 * 62 */ 63class Net_DNS2_Cache_Shm extends Net_DNS2_Cache 64{ 65 /* 66 * resource id of the shared memory cache 67 */ 68 private $_cache_id = false; 69 70 /* 71 * the IPC key 72 */ 73 private $_cache_file_tok = -1; 74 75 /** 76 * open a cache object 77 * 78 * @param string $cache_file path to a file to use for cache storage 79 * @param integer $size the size of the shared memory segment to create 80 * @param string $serializer the name of the cache serialize to use 81 * 82 * @throws Net_DNS2_Exception 83 * @access public 84 * @return void 85 * 86 */ 87 public function open($cache_file, $size, $serializer) 88 { 89 $this->cache_size = $size; 90 $this->cache_file = $cache_file; 91 $this->cache_serializer = $serializer; 92 93 // 94 // make sure the file exists first 95 // 96 if (!file_exists($cache_file)) { 97 98 if (file_put_contents($cache_file, '') === false) { 99 100 throw new Net_DNS2_Exception( 101 'failed to create empty SHM file: ' . $cache_file, 102 Net_DNS2_Lookups::E_CACHE_SHM_FILE 103 ); 104 } 105 } 106 107 // 108 // convert the filename to a IPC key 109 // 110 $this->_cache_file_tok = ftok($cache_file, 't'); 111 if ($this->_cache_file_tok == -1) { 112 113 throw new Net_DNS2_Exception( 114 'failed on ftok() file: ' . $this->_cache_file_tok, 115 Net_DNS2_Lookups::E_CACHE_SHM_FILE 116 ); 117 } 118 119 // 120 // try to open an existing cache; if it doesn't exist, then there's no 121 // cache, and nothing to do. 122 // 123 $this->_cache_id = @shmop_open($this->_cache_file_tok, 'w', 0, 0); 124 if ($this->_cache_id !== false) { 125 126 // 127 // this returns the size allocated, and not the size used, but it's 128 // still a good check to make sure there's space allocated. 129 // 130 $allocated = shmop_size($this->_cache_id); 131 if ($allocated > 0) { 132 133 // 134 // read the data from the shared memory segment 135 // 136 $data = trim(shmop_read($this->_cache_id, 0, $allocated)); 137 if ( ($data !== false) && (strlen($data) > 0) ) { 138 139 // 140 // unserialize and store the data 141 // 142 $decoded = null; 143 144 if ($this->cache_serializer == 'json') { 145 146 $decoded = json_decode($data, true); 147 } else { 148 149 $decoded = unserialize($data); 150 } 151 152 if (is_array($decoded) == true) { 153 154 $this->cache_data = $decoded; 155 } else { 156 157 $this->cache_data = array(); 158 } 159 160 // 161 // call clean to clean up old entries 162 // 163 $this->clean(); 164 } 165 } 166 } 167 } 168 169 /** 170 * Destructor 171 * 172 * @access public 173 * 174 */ 175 public function __destruct() 176 { 177 // 178 // if there's no cache file set, then there's nothing to do 179 // 180 if (strlen($this->cache_file) == 0) { 181 return; 182 } 183 184 $fp = fopen($this->cache_file, 'r'); 185 if ($fp !== false) { 186 187 // 188 // lock the file 189 // 190 flock($fp, LOCK_EX); 191 192 // 193 // check to see if we have an open shm segment 194 // 195 if ($this->_cache_id === false) { 196 197 // 198 // try opening it again, incase it was created by another 199 // process in the mean time 200 // 201 $this->_cache_id = @shmop_open( 202 $this->_cache_file_tok, 'w', 0, 0 203 ); 204 if ($this->_cache_id === false) { 205 206 // 207 // otherwise, create it. 208 // 209 $this->_cache_id = @shmop_open( 210 $this->_cache_file_tok, 'c', 0, $this->cache_size 211 ); 212 } 213 } 214 215 // 216 // get the size allocated to the segment 217 // 218 $allocated = shmop_size($this->_cache_id); 219 220 // 221 // read the contents 222 // 223 $data = trim(shmop_read($this->_cache_id, 0, $allocated)); 224 225 // 226 // if there was some data 227 // 228 if ( ($data !== false) && (strlen($data) > 0) ) { 229 230 // 231 // unserialize and store the data 232 // 233 $c = $this->cache_data; 234 235 $decoded = null; 236 237 if ($this->cache_serializer == 'json') { 238 239 $decoded = json_decode($data, true); 240 } else { 241 242 $decoded = unserialize($data); 243 } 244 245 if (is_array($decoded) == true) { 246 247 $this->cache_data = array_merge($c, $decoded); 248 } 249 } 250 251 // 252 // delete the segment 253 // 254 shmop_delete($this->_cache_id); 255 256 // 257 // clean the data 258 // 259 $this->clean(); 260 261 // 262 // clean up and write the data 263 // 264 $data = $this->resize(); 265 if (!is_null($data)) { 266 267 // 268 // re-create segment 269 // 270 $this->_cache_id = @shmop_open( 271 $this->_cache_file_tok, 'c', 0644, $this->cache_size 272 ); 273 if ($this->_cache_id === false) { 274 return; 275 } 276 277 $o = shmop_write($this->_cache_id, $data, 0); 278 } 279 280 // 281 // close the segment 282 // 283 shmop_close($this->_cache_id); 284 285 // 286 // unlock 287 // 288 flock($fp, LOCK_UN); 289 290 // 291 // close the file 292 // 293 fclose($fp); 294 } 295 } 296}; 297 298/* 299 * Local variables: 300 * tab-width: 4 301 * c-basic-offset: 4 302 * c-hanging-comment-ender-p: nil 303 * End: 304 */ 305?> 306