1<?php 2// +----------------------------------------------------------------------+ 3// | PEAR :: Cache | 4// +----------------------------------------------------------------------+ 5// | Copyright (c) 1997-2003 The PHP Group | 6// +----------------------------------------------------------------------+ 7// | This source file is subject to version 2.0 of the PHP license, | 8// | that is bundled with this package in the file LICENSE, and is | 9// | available at through the world-wide-web at | 10// | http://www.php.net/license/2_02.txt. | 11// | If you did not receive a copy of the PHP license and are unable to | 12// | obtain it through the world-wide-web, please send a note to | 13// | license@php.net so we can mail you a copy immediately. | 14// +----------------------------------------------------------------------+ 15// | Authors: Ulf Wendel <ulf.wendel@phpdoc.de> | 16// +----------------------------------------------------------------------+ 17// 18// $Id: msession.php 178289 2005-01-26 09:47:28Z dufuz $ 19 20require_once 'Cache/Container.php'; 21 22/** 23* Stores cache contents in msessions. 24* 25* WARNING: experimental, untested 26* 27* @author Ulf Wendel <ulf.wendel@phpdoc.de> 28* @version $Id: msession.php 178289 2005-01-26 09:47:28Z dufuz $ 29*/ 30class Cache_Container_msession extends Cache_Container 31{ 32 /** 33 * Length of the Cache-Identifier 34 * 35 * Note that the PEAR-Cache prefixes the ID with an md5() value 36 * of the cache-group. A good value for the id_length 37 * depends on the maximum number of entries per cache group. 38 * 39 * @var int 40 */ 41 var $id_length = 32; 42 43 44 /** 45 * Use msession_uniq to create a unique SID. 46 * 47 * @var boolean 48 */ 49 var $uniq = true; 50 51 52 /** 53 * Establish a connection to a msession server? 54 * 55 * @var boolean 56 */ 57 var $connect = true; 58 59 60 /** 61 * msession host 62 * 63 * @var string 64 */ 65 var $host = null; 66 67 68 /** 69 * msession port 70 * 71 * @var string 72 */ 73 var $port = null; 74 75 76 /** 77 * mesession server connection 78 * 79 * @var resource msession 80 */ 81 var $ms = null; 82 83 84 function Cache_Container_msession($options = '') 85 { 86 if (is_array($options)) { 87 $this->setOptions($options, array_merge($this->allowed_options, array('id_length', 'uniq', 'host', 'port', 'connect'))); 88 } 89 if ($connect) { 90 if ($this->host == null) { 91 new Cache_Error('No host specified.', __FILE__, __LINE__); 92 } 93 if ($this->port == null) { 94 new Cache_Error('No port specified.', __FILE__, __LINE__); 95 } 96 if (!($this->ms = msession_connect($this->host, $this->port))) { 97 new Cache_Error('Can not connect to the sever using host "' . $this->host . '" on port "' . $this->port . '"', __FILE__, __LINE__); 98 } 99 } 100 101 } // end func contructor 102 103 function fetch($id, $group) 104 { 105 $id = strtoupper(md5($group)) . $id; 106 $group = msession_get($id, '_pear_cache_data', null); 107 108 if ($data == null) { 109 return array(null, null, null); 110 } 111 return array($data['expires'], $data['cachedata'], $data['userdata']); 112 } // end func fetch 113 114 /** 115 * Stores a dataset. 116 * 117 * WARNING: If you supply userdata it must not contain any linebreaks, 118 * otherwise it will break the filestructure. 119 */ 120 function save($id, $cachedata, $expires, $group, $userdata) 121 { 122 $this->flushPreload($id, $group); 123 124 $cachedata = $this->encode($cachedata); 125 $expires_abs = $this->getExpiresAbsolute($expires); 126 127 $size = 1 + strlen($cachedata) + strlen($expires_abs) + strlen($userdata) + strlen($group); 128 $size += strlen($size); 129 130 $data = array( 131 'cachedata' => $cachedata, 132 'expires' => $expires_abs, 133 'userdata' => $userdata 134 ); 135 $id = strtoupper(md5($group)) . $id; 136 137 msession_lock($id); 138 139 if (!msession_set($id, '_pear_cache', true)) { 140 msession_unlock($id); 141 return new Cache_Error("Can't write cache data.", __FILE__, __LINE__); 142 } 143 144 if (!msession_set($id, '_pear_cache_data', $data)) { 145 msession_unlock($id); 146 return new Cache_Error("Can't write cache data.", __FILE__, __LINE__); 147 } 148 149 if (!msession_set($id, '_pear_cache_group', $group)) { 150 msession_unlock($id); 151 return new Cache_Error("Can't write cache data.", __FILE__, __LINE__); 152 } 153 154 if (!msession_set($id, '_pear_cache_size', $size)) { 155 msession_unlock($id); 156 return new Cache_Error("Can't write cache data.", __FILE__, __LINE__); 157 } 158 159 // let msession do some GC as well 160 // note that msession works different from the PEAR Cache. 161 // msession deletes an entry if it has not been used for n-seconds. 162 // PEAR Cache deletes after n-seconds. 163 if ($expires != 0) { 164 msession_timeout($id, $expires); 165 } 166 msession_unlock($id); 167 168 return true; 169 } // end func save 170 171 function remove($id, $group) 172 { 173 $this->flushPreload($id, $group); 174 return msession_destroy(strtoupper(md5($group)) . $id); 175 } // end func remove 176 177 function flush($group) 178 { 179 $this->flushPreload(); 180 181 $sessions = msession_find('_pear_cache_group', $group); 182 if (empty($sessions)) { 183 return 0; 184 } 185 186 foreach ($sessions as $k => $id) 187 messsion_destroy($id); 188 189 return count($sessions); 190 } // end func flush 191 192 function idExists($id, $group) 193 { 194 return (msession_get(strtoupper(md5($group)) . $id, '_pear_cache_group', null) == null) ? false : true; 195 } // end func idExists 196 197 /** 198 * Deletes all expired files. 199 * 200 * Note: garbage collection should cause lot's of network traffic. 201 * 202 * @param integer Maximum lifetime in seconds of an no longer used/touched entry 203 * @throws Cache_Error 204 */ 205 function garbageCollection($maxlifetime) 206 { 207 $this->flushPreload(); 208 209 $sessions = msession_find('_pear_cache', true); 210 if (empty($sessions)) 211 return true; 212 213 $total = 0; 214 $entries = array(); 215 216 foreach ($sessions as $k => $id) { 217 $data = msession_get($id, '_pear_cache_data', null); 218 if (null == $data) { 219 continue; 220 } 221 222 if ($data['expires'] <= time()) { 223 msession_destroy($id); 224 continue; 225 } 226 227 $size = msession_get($id, '_pear_cache_size', null); 228 $total += $size; 229 $entries[$data['expires']] = array($id, $size); 230 } 231 232 if ($total > $this->highwater) { 233 234 krsort($entries); 235 reset($entries); 236 237 while ($total > $this->lowwater && list($expires, $entry) = each($entries)) { 238 msession_destroy($entry[0]); 239 $total -= $entry[1]; 240 } 241 242 } 243 244 return true; 245 } // end func garbageCollection 246 247} // end class file 248?>