shUseURLCache)) {
register_shutdown_function('shWriteURLCacheToDisk');
}
function sh_var_export( $cache, $start) {
// export content of array $cache, inserting a numeric key starting at $start
$size = count($cache);
if (empty($size)) return '';
$ret = '';
for ($i=0; $i<$size; $i++) { // use for instead of foreach to reduce memory usage
// new version, smaller RAM footprint
$ret .= "\n".'$shURLDiskCache['.$start++.']=\''.$cache[$i].'\';';
}
// new version, less ram footprint
return $ret;
}
function shWriteURLCacheToDisk() {
global $shURLDiskCache, $shURLMemCache, $shURLCacheFileName, $sefConfig, $shURLCacheCreationDate;
if (!count($shURLMemCache)) return; // nothing to do, no new URL to write to disk
$now = time();
if (!file_exists($shURLCacheFileName)) {
$cache = 'version.'
if (!defined(\'_VALID_MOS\')) die(\'Direct Access to this location is not allowed.\');
$shURLCacheCreationDate = '.$now.';'."\n";
} else {
$cache = ' SH404SEF_URL_CACHE_TTL*86400) { // cache must be cleared
$GLOBALS['shURLDiskCache'] = array();
unlink($shURLCacheFileName);
$shURLCacheCreationDate = $now;
$cache = 'version.'
if (!defined(\'_VALID_MOS\')) die(\'Direct Access to this location is not allowed.\');
$shURLCacheCreationDate = '.$now.';'."\n";
}
}
}
}
$count = count( $shURLDiskCache);
$cache .= sh_var_export( $shURLMemCache, $count); // only need to write memory cache, ie: those URL added since last read of cache from disk
$cache .= "\n".'?'.'>';
$cacheFile=fopen( $shURLCacheFileName,'ab');
if ($cacheFile) {
fwrite( $cacheFile, $cache);
fclose( $cacheFile);
}
}
// fetch an URL from cache, return null if not found
function shGetSefURLFromCache($string, &$url) {
global $sefConfig, $shURLCacheMisses, $shURLCacheHits, $shURLCacheMissesList;
if (!$sefConfig->shUseURLCache) {
$url = null;
$shURLCacheMisses += 1;
return sh404SEF_URLTYPE_NONE;
}
shLoadURLCache();
$diskCacheSize = count($GLOBALS['shURLDiskCache']);
$memCacheSize = count($GLOBALS['shURLMemCache']);
if (empty($diskCacheSize) && empty($memCacheSize)) {
$url = null;
$shURLCacheMisses += 1;
return sh404SEF_URLTYPE_NONE;
}
$string = htmlentities( $string, ENT_QUOTES);
for ($i=0; $i<$diskCacheSize; $i++) {
if (strpos($GLOBALS['shURLDiskCache'][$i], $string) !== false) {
$tmp = explode('#', $GLOBALS['shURLDiskCache'][$i]); // cache format : non-sef#sef#type
if ($string == $tmp[0]) {
$url = $tmp[1];
_log('Retrieved SEF from disk cache : '.$url.' => '.html_entity_decode( $tmp[0], ENT_QUOTES).'('.$tmp[2].')');
$shURLCacheHits += 1;
return $tmp[2];
}
}
}
for ($i=0; $i<$memCacheSize; $i++) {
if (strpos($GLOBALS['shURLMemCache'][$i], $string) !== false) {
$tmp = explode('#', $GLOBALS['shURLMemCache'][$i]); // cache format : non-sef#sef#type
if ($string == $tmp[0]) {
$url = $tmp[1];
_log('Retrieved SEF from mem cache : '.$url.' => '.html_entity_decode( $tmp[0], ENT_QUOTES).'('.$tmp[2].')');
$shURLCacheHits += 1;
return $tmp[2];
}
}
}
$shURLCacheMisses += 1;
$shURLCacheMissesList[] = $string;
return sh404SEF_URLTYPE_NONE;
}
// fetch an URL from cache, return null if not found
function shGetNonSefURLFromCache($string, &$url) {
global $sefConfig;
if (!$sefConfig->shUseURLCache) {
$url = null;
return sh404SEF_URLTYPE_NONE;
}
shLoadURLCache();
$diskCacheSize = count($GLOBALS['shURLDiskCache']);
$memCacheSize = count($GLOBALS['shURLMemCache']);
if (empty($diskCacheSize) && empty($memCacheSize)) {
$url = null;
return sh404SEF_URLTYPE_NONE;
}
for ($i=0; $i<$diskCacheSize; $i++) {
if (strpos($GLOBALS['shURLDiskCache'][$i], $string) !== false) {
$tmp = explode('#', $GLOBALS['shURLDiskCache'][$i]); // cache format : non-sef#sef#type
$nonSef = html_entity_decode( $tmp[0], ENT_QUOTES);
if ($string == $tmp[1]) {
$url = $nonSef;
_log('Retrieved Non SEF from disk cache : '.$url.' => '.$tmp[1].'('.$tmp[2].')');
return $tmp[2];
}
}
}
for ($i=0; $i<$memCacheSize; $i++) {
if (strpos($GLOBALS['shURLMemCache'][$i], $string) !== false) {
$tmp = explode('#', $GLOBALS['shURLMemCache'][$i]); // cache format : non-sef#sef#type
$nonSef = html_entity_decode( $tmp[0], ENT_QUOTES);
if ($string == $tmp[1]) {
$url = $nonSef;
_log('Retrieved Non SEF from mem cache : '.$url.' => '.$tmp[1].'('.$tmp[2].')');
return $tmp[2];
}
}
}
return sh404SEF_URLTYPE_NONE;
}
function shAddSefURLToCache( $nonSefURL, $sefURL, $URLType) {
global $sefConfig, $shURLMemCache, $shURLTotalCount;
if (!$sefConfig->shUseURLCache) return null;
if ($shURLTotalCount >= $sefConfig->shMaxURLInCache) return null; // v 1.2.4.c added total cache size control
// Filter out non sef url which include &mosmsg, as I don't want to have a cache entry for every single msg
// that can be thrown at me, including every 404 error
if (strpos(strtolower($nonSefURL), '&mosmsg')) return null;
$count = count($shURLMemCache);
// new cache format : non-sef#sef#type
$shURLMemCache[$count] = htmlentities( $nonSefURL, ENT_QUOTES).'#'.$sefURL.'#'.$URLType;
_log('Adding to URL cache : '.$sefURL.' <= '.$nonSefURL);
$shURLTotalCount++; // v 1.2.4.c added total cache size control
return true;
}
function shRemoveURLFromCache( $nonSefURLList) {
global $sefConfig, $shURLMemCache, $shURLDiskCache, $shURLTotalCount;
if (!$sefConfig->shUseURLCache || empty($nonSefURLList)) return null;
$foundInDiskCache = false;
$foundInMemCache = false;
foreach ($nonSefURLList as $nonSefURL) {
if (!empty($shURLMemCache)) {
foreach ($shURLMemCache as $cacheItem) { // look up in memory cache
$tmp = explode('#', $cacheItem);
$cacheNonSef = html_entity_decode( $tmp[0], ENT_QUOTES);
if ($cacheNonSef == $nonSefURL) {
unset($cacheItem);
$shURLTotalCount--;
$foundInMemCache = true;
break;
}
}
}
if (!empty($shURLDiskCache)) {
foreach ($shURLDiskCache as $cacheItem) { // look up disk cache
$tmp = explode('#', $cacheItem);
$cacheNonSef = html_entity_decode( $tmp[0], ENT_QUOTES);
if ($cacheNonSef == $nonSefURL) {
unset($cacheItem);
$shURLTotalCount--;
$foundInDiskCache = true;
break;
}
}
}
}
if ($foundInMemCache) {
$shURLMemCache = array_values($shURLMemCache); // simply reindex mem cache
return;
}
if ($foundInDiskCache) { // we need to remove these url from the disk cache file
// to make it simpler, I simply rewrite the complete file
$shURLMemCache = (empty($shURLMemCache) ?
array_values($shURLDiskCache)
:array_merge($shURLDiskCache, $shURLMemCache));
$shURLDiskCache = array(); // don't need disk cache anymore, as all URL are in mem cache
// so we remove both on disk cache and in memory copy of on disk cache
if (file_exists(sh404SEF_FRONT_ABS_PATH.'cache/shCacheContent.php'))
unlink(sh404SEF_FRONT_ABS_PATH.'cache/shCacheContent.php');
// no need to write new URL list in disk file, as this will be done automatically at shutdown
}
}
// load cached URL from disk into an array in memory
function shLoadURLCache() {
global $shURLDiskCache, $shURLCacheFileName, $shURLTotalCount, $shURLMemCache;
static $shDiskCacheLoaded = false;
if (!$shDiskCacheLoaded) {
_log('Cache not loaded - trying to load '.$shURLCacheFileName);
if (file_exists( $shURLCacheFileName)) {
$startMem = function_exists('memory_get_usage')? memory_get_usage():'unavailable';
_log('Including cache file (mem = '.$startMem.')');
$GLOBALS['shURLDiskCache'] = array(); // erase global, not local copy
include($shURLCacheFileName);
$endMem = function_exists('memory_get_usage')? memory_get_usage():'unavailable';
$shDiskCacheLoaded = !empty($shURLDiskCache);
$shURLTotalCount = !empty($shURLDiskCache) ? count($shURLDiskCache) : 0;
_log('Cache file included : '.($startMem == 'unavailable' ? $startMem: $endMem-$startMem).' bytes used, '.$shURLTotalCount.' URLs');
} else {
$GLOBALS['shURLDiskCache'] = array();
$shDiskCacheLoaded = false;
_log('Cache file does not exists');
}
}
}
function shShowCacheStats() {
global $shURLCacheMisses, $shURLCacheMissesList, $shURLCacheHits;
$cacheTotal = $shURLCacheMisses+$shURLCacheHits;
echo 'Cache hits : '. $shURLCacheHits . " [".(int)(100*$shURLCacheHits/$cacheTotal) .']
';
echo 'Cache misses : '. $shURLCacheMisses . " [".(int)(100*$shURLCacheMisses/$cacheTotal). ']
';
echo 'Cache total : '. $cacheTotal . '
';
echo '
Misses list';
foreach($shURLCacheMissesList as $url) {
echo '
'.$url.'