00001 <?php
00002
00017 abstract class SnapCache extends SObject {
00019 private static $CACHE_ID = array('Directory' => array(), 'Resource' => array(),
00020 'Version' => array(),
00021 'Permission' => array(),
00022 'DirectoryUserPermission' => array(),
00023 'DirectoryGroupPermission' => array(),
00024 'ResourceUserPermission' => array(),
00025 'ResourceGroupPermission' => array());
00027 private static $ID_TO_PATH = array('Directory' => array(), 'Resource' => array(), 'Version' => array());
00029 private static $CACHE_PATH = array('Directory' => array(), 'Resource' => array(), 'Version' => array());
00030
00032 private static $ID_CACHE_MISSES = 0;
00034 private static $ID_CACHE_HITS = 0;
00036 private static $PATH_CACHE_MISSES = 0;
00038 private static $PATH_CACHE_HITS = 0;
00039
00041 private static $useApc = true;
00043 private static $useCache = true;
00044
00046 private static $APC_EXISTS = false;
00047
00049 private static $TYPE_MAP = array(
00050 'Directory' => 'D',
00051 'Resource' => 'R',
00052 'Permission' => 'P',
00053 'DirectoryUserPermission' => 'DUP',
00054 'ResourceUserPermission' => 'RUP',
00055 'DirectoryGroupPermission' => 'DGP',
00056 'ResourceGroupPermission' => 'RGP',
00057 'Version' => 'VP'
00058 );
00059
00068 public static function init($useCache = true, $useApc = true) {
00069 self::$APC_EXISTS = function_exists('apc_clear_cache');
00070 self::$useApc = $useApc;
00071 self::$useCache = $useCache;
00072 if(!self::$useApc && self::$APC_EXISTS)
00073 apc_clear_cache('user');
00074 }
00075
00084 public static function setEnableAPC($enable, $clear = false) {
00085 if(!self::$APC_EXISTS)
00086 $enable = false;
00087 self::$useApc = $enable ? true : false;
00088 if($clear && !$enable && self::$APC_EXISTS) {
00089 apc_clear_cache('user');
00090 }
00091 }
00092
00097 public static function usingApc() {
00098 return self::$useApc;
00099 }
00100
00108 public static function setEnableCache($enable, $clear = false) {
00109 self::$useCache = $enable ? true : false;
00110 if($clear && !$enable) {
00111 self::$CACHE_ID = array('Directory' => array(), 'Resource' => array(), 'Version' => array(),
00112 'Permission' => array(), 'DirectoryUserPermission' => array(), 'ResourceUserPermission' => array(),
00113 'DirectoryGroupPermission' => array(), 'ResourceGroupPermission' => array());
00114 self::$ID_TO_PATH = array('Directory' => array(), 'Resource' => array(), 'Version' => array());
00115 self::$CACHE_PATH = array('Directory' => array(), 'Resource' => array(), 'Version' => array());
00116 }
00117 if(!$enable)
00118 self::setEnableAPC(false, $clear);
00119 }
00120
00125 public static function usingCache() {
00126 return self::$useCache;
00127 }
00128
00139 public static function putById($type, $id, $obj) {
00140 if(!self::$useCache) return;
00141 self::$CACHE_ID[$type][$id] = $obj;
00142 if(!isset(self::$ID_TO_PATH[$type][$id]))
00143 self::$ID_TO_PATH[$type][$id] = array();
00144 if(self::$useApc) {
00145 apc_store('snap2.1_CI_'.self::$TYPE_MAP[$type].$id, serialize($obj));
00146 }
00147 }
00148
00159 public static function getById($type, $id) {
00160 if(!self::$useCache) return null;
00161 if(self::$APC_EXISTS && self::$useApc && !isset(self::$CACHE_ID[$type][$id])) {
00162 $obj = apc_fetch('snap2.1_CI_'.self::$TYPE_MAP[$type].$id);
00163 if($obj === false)
00164 return null;
00165 $obj = unserialize($obj);
00166 self::$CACHE_ID[$type][$id] = $obj;
00167 self::$ID_CACHE_HITS++;
00168 return $obj;
00169 }
00170 if(isset(self::$CACHE_ID[$type][$id])) {
00171 self::$ID_CACHE_HITS++;
00172 return self::$CACHE_ID[$type][$id];
00173 }
00174
00175 self::$ID_CACHE_MISSES++;
00176 return null;
00177 }
00178
00187 public static function deleteById($type, $id) {
00188 if(!self::$useCache) return;
00189 unset(self::$CACHE_ID[$type][$id]);
00190 foreach(self::$ID_TO_PATH[$type][$id] as $path => $dummy)
00191 unset(self::$CACHE_PATH[$type][$path]);
00192 unset(self::$ID_TO_PATH[$type][$id]);
00193 if(self::$APC_EXISTS && self::$useApc)
00194 apc_delete('snap2.1_CI_'.self::$TYPE_MAP[$type].$id);
00195 }
00196
00209 public static function putByPath($type, $path, $obj, $isCanon = false) {
00210 if(!self::$useCache) return;
00211 self::$CACHE_PATH[$type][$path] = $obj;
00212 self::$CACHE_ID[$type][$obj->getId()] = $obj;
00213 if(!isset(self::$ID_TO_PATH[$type][$obj->getId()]))
00214 self::$ID_TO_PATH[$type][$obj->getId()] = array();
00215 self::$ID_TO_PATH[$type][$obj->getId()][$path] = true;
00216 if($isCanon)
00217 self::$ID_TO_PATH[$type][$obj->getId()][0] = $path;
00218 if(self::$APC_EXISTS && self::$useApc) {
00219 apc_store('snap2.1_CI_'.self::$TYPE_MAP[$type].$obj->getId(), serialize($obj));
00220 apc_store('snap2.1_CP_'.self::$TYPE_MAP[$type].$path, serialize($obj));
00221 }
00222 }
00223
00234 public static function getByPath($type, $path) {
00235 if(!self::$useCache) return null;
00236 if(self::$APC_EXISTS && self::$useApc && !isset(self::$CACHE_PATH[$type][$path])) {
00237 $obj = apc_fetch('snap2.1_CP_'.self::$TYPE_MAP[$type].$path);
00238 if($obj === false)
00239 return null;
00240 $obj = unserialize($obj);
00241 self::$CACHE_PATH[$type][$path] = $obj;
00242 self::$CACHE_ID[$type][$obj->getId()] = $obj;
00243 if(!isset(self::$ID_TO_PATH[$type][$obj->getId()]))
00244 self::$ID_TO_PATH[$type][$obj->getId()] = array();
00245 self::$ID_TO_PATH[$type][$obj->getId()][$path] = $obj;
00246 self::$PATH_CACHE_HITS++;
00247 return $obj;
00248 }
00249 if(isset(self::$CACHE_PATH[$type][$path])) {
00250 self::$PATH_CACHE_HITS++;
00251 return self::$CACHE_PATH[$type][$path];
00252 }
00253
00254 self::$PATH_CACHE_MISSES++;
00255 return null;
00256 }
00257
00266 public static function getPathsById($type, $id) {
00267 if(!self::$useCache) return null;
00268 if(isset(self::$ID_TO_PATH[$type][$id])) {
00269 self::$PATH_CACHE_HITS++;
00270 return self::$ID_TO_PATH[$type][$id];
00271 }
00272
00273 self::$PATH_CACHE_MISSES++;
00274
00275 return null;
00276 }
00277
00286 public static function deleteByPath($type, $path) {
00287 if(!self::$useCache) return;
00288 if(!isset(self::$CACHE_PATH[$type][$path]))
00289 return;
00290 $obj = self::$CACHE_PATH[$type][$path];
00291 unset(self::$CACHE_PATH[$type][$path]);
00292 if($obj && isset(self::$ID_TO_PATH[$type][$obj->getId()])) {
00293 unset(self::$ID_TO_PATH[$type][$obj->getId()][$path]);
00294 }
00295 if(self::$APC_EXISTS && self::$useApc)
00296 apc_delete('snap2.1_CI_'.self::$TYPE_MAP[$type].$path);
00297 }
00298
00309 public static function updateById($type, $id) {
00310
00311 if(!isset(self::$CACHE_ID[$type][$id]))
00312 return true;
00313 if(self::$APC_EXISTS && self::$useApc) {
00314 apc_store('snap2.1_CI_'.self::$TYPE_MAP[$type].$id, $objSer = serialize(self::$CACHE_ID[$type][$id]));
00315 if(!isset(self::$ID_TO_PATH[$type][$id]))
00316 self::$ID_TO_PATH[$type][$id] = array();
00317 else
00318 foreach(self::$ID_TO_PATH[$type][$id] as $path => $obj)
00319 apc_store('snap2.1_CP_'.self::$TYPE_MAP[$type].$path, $objSer);
00320 }
00321 return true;
00322 }
00323
00332 public static function clearObjectCache($name) {
00333
00334
00335 self::$CACHE_ID[$name] = array();
00336 }
00337
00346 public static function getObjectCache($name) {
00347 if(!self::$useCache) return array();
00348 return self::$CACHE_ID[$name];
00349 }
00350
00355 public static function showStats() {
00356 if(!self::$useCache)
00357 return;
00358 $idTotal = self::$ID_CACHE_HITS + self::$ID_CACHE_MISSES;
00359 $pathTotal = self::$PATH_CACHE_HITS + self::$PATH_CACHE_MISSES;
00360 if($idTotal != 0) {
00361 $idHitPC = number_format((self::$ID_CACHE_HITS / $idTotal) * 100, 2);
00362 $idMissPC = number_format((self::$ID_CACHE_MISSES / $idTotal) * 100, 2);
00363 }
00364 else {
00365 $idHitPC = "N/A";
00366 $idMissPC = "N/A";
00367 }
00368 if($pathTotal != 0) {
00369 $pHitPC = number_format((self::$PATH_CACHE_HITS / $pathTotal) * 100, 2);
00370 $pMissPC = number_format((self::$PATH_CACHE_MISSES / $pathTotal) * 100, 2);
00371 }
00372 else {
00373 $pHitPC = "N/A";
00374 $pMissPC = "N/A";
00375 }
00376 SErrorManager::setDebug('Cache statistics:<br />'
00377 . 'ID Cache Hits: ' . self::$ID_CACHE_HITS . ' (' . $idHitPC . '%)<br />'
00378 . 'ID Cache Misses: ' . self::$ID_CACHE_MISSES . ' (' . $idMissPC . '%)<br />'
00379 . 'Path Cache Hits: ' . self::$PATH_CACHE_HITS . ' (' . $pHitPC . '%)<br />'
00380 . 'Path Cache Misses: ' . self::$PATH_CACHE_MISSES . ' (' . $pMissPC . '%)');
00381 }
00382
00387 public static function dumpCache() {
00388 if(!self::$useCache) {
00389 SErrorManager::setDebug('Cache disabled');
00390 return;
00391 }
00392
00393 $msg = 'Cache Dump:<br /><b>ID Cache:</b><ul>';
00394 foreach(self::$CACHE_ID as $type => $cache) {
00395 $msg .= '<li>' . $type . '<ul>';
00396 foreach($cache as $id => $obj) {
00397 $msg .= '<li>ID: ' . $id . '<br />';
00398 $msg .= $obj->toCacheDump();
00399 $msg .= '</li>';
00400 }
00401 $msg .= '</ul></li>';
00402 }
00403 $msg .= '</ul>';
00404
00405 $msg .= '<b>Path Cache:</b><ul>';
00406 foreach(self::$CACHE_PATH as $type => $cache) {
00407 $msg .= '<li>' . $type . '<ul>';
00408 foreach($cache as $path => $obj) {
00409 $msg .= '<li>Path: ' . $path . '; ID: ' . $obj->getId() . '<br />';
00410 $msg .= $obj->toCacheDump();
00411 $msg .= '</li>';
00412 }
00413 $msg .= '</ul></li>';
00414 }
00415 $msg .= '</ul>';
00416
00417 SErrorManager::setDebug($msg);
00418 }
00419 }
00420
00421 ?>