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