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$ 47 * @link http://pear.php.net/package/Net_DNS2 48 * @since File available since Release 1.1.0 49 * 50 */ 51 52/** 53 * A class to provide simple dns lookup caching. 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 64{ 65 /* 66 * the filename of the cache file 67 */ 68 protected $cache_file = ''; 69 70 /* 71 * the local data store for the cache 72 */ 73 protected $cache_data = array(); 74 75 /* 76 * the size of the cache to use 77 */ 78 protected $cache_size = 0; 79 80 /* 81 * the cache serializer 82 */ 83 protected $cache_serializer; 84 85 /* 86 * an internal flag to make sure we don't load the cache content more 87 * than once per instance. 88 */ 89 protected $cache_opened = false; 90 91 /** 92 * returns true/false if the provided key is defined in the cache 93 * 94 * @param string $key the key to lookup in the local cache 95 * 96 * @return boolean 97 * @access public 98 * 99 */ 100 public function has($key) 101 { 102 return isset($this->cache_data[$key]); 103 } 104 105 /** 106 * returns the value for the given key 107 * 108 * @param string $key the key to lookup in the local cache 109 * 110 * @return mixed returns the cache data on sucess, false on error 111 * @access public 112 * 113 */ 114 public function get($key) 115 { 116 if (isset($this->cache_data[$key])) { 117 118 if ($this->cache_serializer == 'json') { 119 return json_decode($this->cache_data[$key]['object']); 120 } else { 121 return unserialize($this->cache_data[$key]['object']); 122 } 123 } else { 124 125 return false; 126 } 127 } 128 129 /** 130 * adds a new key/value pair to the cache 131 * 132 * @param string $key the key for the new cache entry 133 * @param mixed $data the data to store in cache 134 * 135 * @return void 136 * @access public 137 * 138 */ 139 public function put($key, $data) 140 { 141 $ttl = 86400 * 365; 142 143 // 144 // clear the rdata values 145 // 146 $data->rdata = ''; 147 $data->rdlength = 0; 148 149 // 150 // find the lowest TTL, and use that as the TTL for the whole cached 151 // object. The downside to using one TTL for the whole object, is that 152 // we'll invalidate entries before they actuall expire, causing a 153 // real lookup to happen. 154 // 155 // The upside is that we don't need to require() each RR type in the 156 // cache, so we can look at their individual TTL's on each run- we only 157 // unserialize the actual RR object when it's get() from the cache. 158 // 159 foreach ($data->answer as $index => $rr) { 160 161 if ($rr->ttl < $ttl) { 162 $ttl = $rr->ttl; 163 } 164 165 $rr->rdata = ''; 166 $rr->rdlength = 0; 167 } 168 foreach ($data->authority as $index => $rr) { 169 170 if ($rr->ttl < $ttl) { 171 $ttl = $rr->ttl; 172 } 173 174 $rr->rdata = ''; 175 $rr->rdlength = 0; 176 } 177 foreach ($data->additional as $index => $rr) { 178 179 if ($rr->ttl < $ttl) { 180 $ttl = $rr->ttl; 181 } 182 183 $rr->rdata = ''; 184 $rr->rdlength = 0; 185 } 186 187 $this->cache_data[$key] = array( 188 189 'cache_date' => time(), 190 'ttl' => $ttl 191 ); 192 193 if ($this->cache_serializer == 'json') { 194 $this->cache_data[$key]['object'] = json_encode($data); 195 } else { 196 $this->cache_data[$key]['object'] = serialize($data); 197 } 198 } 199 200 /** 201 * runs a clean up process on the cache data 202 * 203 * @return void 204 * @access protected 205 * 206 */ 207 protected function clean() 208 { 209 if (count($this->cache_data) > 0) { 210 211 // 212 // go through each entry and adjust their TTL, and remove entries that 213 // have expired 214 // 215 $now = time(); 216 217 foreach ($this->cache_data as $key => $data) { 218 219 $diff = $now - $data['cache_date']; 220 221 if ($data['ttl'] <= $diff) { 222 223 unset($this->cache_data[$key]); 224 } else { 225 226 $this->cache_data[$key]['ttl'] -= $diff; 227 $this->cache_data[$key]['cache_date'] = $now; 228 } 229 } 230 } 231 } 232 233 /** 234 * runs a clean up process on the cache data 235 * 236 * @return mixed 237 * @access protected 238 * 239 */ 240 protected function resize() 241 { 242 if (count($this->cache_data) > 0) { 243 244 // 245 // serialize the cache data 246 // 247 if ($this->cache_serializer == 'json') { 248 $cache = json_encode($this->cache_data); 249 } else { 250 $cache = serialize($this->cache_data); 251 } 252 253 // 254 // only do this part if the size allocated to the cache storage 255 // is smaller than the actual cache data 256 // 257 if (strlen($cache) > $this->cache_size) { 258 259 while (strlen($cache) > $this->cache_size) { 260 261 // 262 // go through the data, and remove the entries closed to 263 // their expiration date. 264 // 265 $smallest_ttl = time(); 266 $smallest_key = null; 267 268 foreach ($this->cache_data as $key => $data) { 269 270 if ($data['ttl'] < $smallest_ttl) { 271 272 $smallest_ttl = $data['ttl']; 273 $smallest_key = $key; 274 } 275 } 276 277 // 278 // unset the key with the smallest TTL 279 // 280 unset($this->cache_data[$smallest_key]); 281 282 // 283 // re-serialize 284 // 285 if ($this->cache_serializer == 'json') { 286 $cache = json_encode($this->cache_data); 287 } else { 288 $cache = serialize($this->cache_data); 289 } 290 } 291 } 292 293 if ( ($cache == 'a:0:{}') || ($cache == '{}') ) { 294 return null; 295 } else { 296 return $cache; 297 } 298 } 299 300 return null; 301 } 302}; 303 304/* 305 * Local variables: 306 * tab-width: 4 307 * c-basic-offset: 4 308 * c-hanging-comment-ender-p: nil 309 * End: 310 */ 311?> 312