return $text;
}
-
/* Caching functions */
- function tryFileCache() {
+ function tryFileCache() {
+ global $wgTitle;
+
if($this->isFileCacheable()) {
- if($this->isFileCacheGood()) {
- wfDebug( " tryFileCache() - about to load\n" );
- $this->loadFromFileCache();
+ $cache = new CacheManager( $wgTitle );
+ if($cache->isFileCacheGood( $this->mTouched )) {
+ wfDebug( " tryFileCache() - about to load\n" );
+ $cache->loadFromFileCache();
exit;
} else {
- wfDebug( " tryFileCache() - starting buffer\n" );
- ob_start( array(&$this, 'saveToFileCache' ) );
+ wfDebug( " tryFileCache() - starting buffer\n" );
+ ob_start( array(&$cache, 'saveToFileCache' ) );
}
} else {
wfDebug( " tryFileCache() - not cacheable\n" );
}
- function fileCacheName() {
- global $wgTitle, $wgFileCacheDirectory, $wgLang;
- if( !$this->mFileCache ) {
- $hash = md5( $key = $wgTitle->getDbkey() );
- if( $wgTitle->getNamespace() )
- $key = $wgLang->getNsText( $wgTitle->getNamespace() ) . ":" . $key;
- $key = str_replace( ".", "%2E", urlencode( $key ) );
- $hash1 = substr( $hash, 0, 1 );
- $hash2 = substr( $hash, 0, 2 );
- $this->mFileCache = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
- wfDebug( " fileCacheName() - {$this->mFileCache}\n" );
- }
- return $this->mFileCache;
- }
-
- function isFileCacheGood() {
- global $wgUser, $wgCacheEpoch;
- if(!file_exists( $fn = $this->fileCacheName() ) ) return false;
- $cachetime = wfUnix2Timestamp( filemtime( $fn ) );
- $good = (( $this->mTouched <= $cachetime ) &&
- ($wgCacheEpoch <= $cachetime ));
- wfDebug(" isFileCacheGood() - cachetime $cachetime, touched {$this->mTouched} epoch {$wgCacheEpoch}, good $good\n");
- return $good;
- }
-
- function loadFromFileCache() {
- global $wgUseGzip, $wgOut;
- wfDebug(" loadFromFileCache()\n");
- $filename=$this->fileCacheName();
- $filenamegz = "{$filename}.gz";
- $wgOut->sendCacheControl();
- if( $wgUseGzip
- && wfClientAcceptsGzip()
- && file_exists( $filenamegz)
- && ( filemtime( $filenamegz ) >= filemtime( $filename ) ) ) {
- wfDebug(" sending gzip\n");
- header( "Content-Encoding: gzip" );
- header( "Vary: Accept-Encoding" );
- $filename = $filenamegz;
- }
- readfile( $filename );
- }
-
- function saveToFileCache( $text ) {
- global $wgUseGzip, $wgCompressByDefault;
- if(strcmp($text,"") == 0) return "";
-
- wfDebug(" saveToFileCache()\n", false);
- $filename=$this->fileCacheName();
- $mydir2=substr($filename,0,strrpos($filename,"/")); # subdirectory level 2
- $mydir1=substr($mydir2,0,strrpos($mydir2,"/")); # subdirectory level 1
- if(!file_exists($mydir1)) { mkdir($mydir1,0775); } # create if necessary
- if(!file_exists($mydir2)) { mkdir($mydir2,0775); }
-
- $f = fopen( $filename, "w" );
- if($f) {
- $now = wfTimestampNow();
- fwrite( $f, str_replace( "</html>",
- "<!-- Cached $now -->\n</html>",
- $text ) );
- fclose( $f );
- if( $wgUseGzip and $wgCompressByDefault ) {
- $start = microtime();
- wfDebug(" saving gzip\n");
- $gzout = gzencode( str_replace( "</html>",
- "<!-- Cached/compressed $now -->\n</html>",
- $text ) );
- if( $gzout === false ) {
- wfDebug(" failed to gzip compress, sending plaintext\n");
- return $text;
- }
- if( $f = fopen( "{$filename}.gz", "w" ) ) {
- fwrite( $f, $gzout );
- fclose( $f );
- $end = microtime();
-
- list($usec1, $sec1) = explode(" ",$start);
- list($usec2, $sec2) = explode(" ",$end);
- $interval = ((float)$usec2 + (float)$sec2) -
- ((float)$usec1 + (float)$sec1);
- wfDebug(" saved gzip in $interval\n");
- } else {
- wfDebug(" failed to write gzip, still sending\n" );
- }
- if(wfClientAcceptsGzip()) {
- header( "Content-Encoding: gzip" );
- header( "Vary: Accept-Encoding" );
- wfDebug(" sending NEW gzip now...\n" );
- return $gzout;
- }
- }
- }
- return $text;
- }
}
--- /dev/null
+<?
+
+include_once( "Title.php" );
+
+class CacheManager {
+ var $mTitle, $mFileCache;
+
+ function CacheManager( &$title ) {
+ $this->mTitle =& $title;
+ $this->mFileCache = "";
+ }
+
+ function fileCacheName() {
+ global $wgFileCacheDirectory, $wgLang;
+ if( !$this->mFileCache ) {
+ $hash = md5( $key = $this->mTitle->getDbkey() );
+ if( $this->mTitle->getNamespace() )
+ $key = $wgLang->getNsText( $this->mTitle->getNamespace() ) . ":" . $key;
+ $key = str_replace( ".", "%2E", urlencode( $key ) );
+
+ $hash1 = substr( $hash, 0, 1 );
+ $hash2 = substr( $hash, 0, 2 );
+ $this->mFileCache = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
+
+ if($this->useGzip())
+ $this->mFileCache .= ".gz";
+
+ wfDebug( " fileCacheName() - {$this->mFileCache}\n" );
+ }
+ return $this->mFileCache;
+ }
+
+ function isFileCached() {
+ return file_exists( $this->fileCacheName() );
+ }
+
+ function fileCacheTime() {
+ return wfUnix2Timestamp( filemtime( $this->fileCacheName() ) );
+ }
+
+ function isFileCacheGood( $timestamp ) {
+ global $wgUser, $wgCacheEpoch;
+
+ if( !$this->isFileCached() ) return false;
+
+ $cachetime = $this->fileCacheTime();
+ $good = (( $timestamp <= $cachetime ) &&
+ ( $wgCacheEpoch <= $cachetime ));
+
+ wfDebug(" isFileCacheGood() - cachetime $cachetime, touched {$this->mTouched} epoch {$wgCacheEpoch}, good $good\n");
+ return $good;
+ }
+
+ function useGzip() {
+ global $wgUseGzip;
+ return $wgUseGzip;
+ }
+
+ /* In handy string packages */
+ function fetchRawText() {
+ return file_get_contents( $this->fileCacheName() );
+ }
+
+ function fetchPageText() {
+ if( $this->useGzip() ) {
+ /* Why is there no gzfile_get_contents() or gzdecode()? */
+ return implode( "", gzfile( $this->fileCacheName() ) );
+ } else {
+ return $this->fetchRawText();
+ }
+ }
+
+ /* Working directory to/from output */
+ function loadFromFileCache() {
+ global $wgOut;
+ wfDebug(" loadFromFileCache()\n");
+
+ $filename=$this->fileCacheName();
+ $wgOut->sendCacheControl();
+
+ if( $this->useGzip() ) {
+ if( wfClientAcceptsGzip() ) {
+ header( "Content-Encoding: gzip" );
+ readfile( $filename );
+ } else {
+ /* Send uncompressed */
+ readgzfile( $filename );
+ }
+ } else {
+ readfile( $filename );
+ }
+ }
+
+ function checkCacheDirs() {
+ $filename = $this->fileCacheName();
+ $mydir2=substr($filename,0,strrpos($filename,"/")); # subdirectory level 2
+ $mydir1=substr($mydir2,0,strrpos($mydir2,"/")); # subdirectory level 1
+
+ if(!file_exists($mydir1)) { mkdir($mydir1,0775); } # create if necessary
+ if(!file_exists($mydir2)) { mkdir($mydir2,0775); }
+ }
+
+ function saveToFileCache( $text ) {
+ if(strcmp($text,"") == 0) return "";
+
+ wfDebug(" saveToFileCache()\n", false);
+
+ $this->checkCacheDirs();
+
+ $f = fopen( $this->fileCacheName(), "w" );
+ if($f) {
+ $now = wfTimestampNow();
+ if( $this->useGzip() ) {
+ $rawtext = str_replace( "</html>",
+ "<!-- Cached/compressed $now -->\n</html>",
+ $text );
+ $text = gzencode( $rawtext );
+ } else {
+ $text = str_replace( "</html>",
+ "<!-- Cached $now -->\n</html>",
+ $text );
+ }
+ fwrite( $f, $text );
+ fclose( $f );
+ if( $this->useGzip() ) {
+ if( wfClientAcceptsGzip() ) {
+ header( "Content-Encoding: gzip" );
+ header( "Vary: Accept-Encoding" );
+ return $text;
+ } else {
+ return $rawtext;
+ }
+ } else {
+ return $text;
+ }
+ }
+ return $text;
+ }
+
+}
+
+?>
<?
global $IP;
include_once( "$IP/FulltextStoplist.php" );
+include_once( "$IP/CacheManager.php" );
$wgLastDatabaseQuery = "";
}
if ( ! $wgDBconnection ) {
- $wgDBconnection = mysql_pconnect( $wgDBserver, $wgDBuser,
- $wgDBpassword ) or die( $noconn .
- "\n<p><b>" . htmlspecialchars(mysql_error()) . "</b></p>\n" . $helpme );
+ @$wgDBconnection = mysql_pconnect( $wgDBserver, $wgDBuser, $wgDBpassword )
+ or wfEmergencyAbort();
+
if( !mysql_select_db( $wgDBname, $wgDBconnection ) ) {
+ /* Persistent connections may become stuck in an unusable state */
wfDebug( "Persistent connection is broken?\n", true );
- $wgDBconnection = mysql_connect( $wgDBserver, $wgDBuser,
- $wgDBpassword ) or die( $noconn .
- "\n<p><b>" . htmlspecialchars(mysql_error()) . "</b> (tried non-p connect)</p>\n" . $helpme );
- mysql_select_db( $wgDBname, $wgDBconnection ) or die( $nodb .
- "\n<p><b>" . htmlspecialchars(mysql_error()) . "</b> (tried non-p connect)</p>\n" . $helpme );
- }
+ @$wgDBconnection = mysql_connect( $wgDBserver, $wgDBuser, $wgDBpassword )
+ or wfEmergencyAbort();
+
+ @mysql_select_db( $wgDBname, $wgDBconnection )
+ or wfEmergencyAbort();
+ }
}
# mysql_ping( $wgDBconnection );
return $wgDBconnection;
}
+/* Call this function if we couldn't contact the database...
+ We'll try to use the cache to display something in the meantime */
+function wfEmergencyAbort( $msg = "" ) {
+ global $wgTitle, $wgUseFileCache, $title;
+
+ if($msg == "") $msg = wfMsg( "noconnect" );
+ $text = $msg;
+
+ if($wgUseFileCache) {
+ if($wgTitle) {
+ $t =& $wgTitle;
+ } else {
+ if($title) {
+ $t = Title::newFromURL( $title );
+ } else {
+ $t = Title::newFromText( wfMsg("mainpage") );
+ }
+ }
+
+ $cache = new CacheManager( $t );
+ if( $cache->isFileCached() ) {
+ $msg = "<p style='color: red'><b>$msg<br>\n" .
+ wfMsg( "cachederror" ) . "</b></p>\n";
+
+ $tag = "<div id='article'>";
+ $text = str_replace(
+ $tag,
+ $tag . $msg,
+ $cache->fetchPageText() );
+ }
+ }
+
+ /* Don't cache error pages! They cause no end of trouble... */
+ header( "Cache-control: none" );
+ header( "Pragma: nocache" );
+ echo $text;
+ exit;
+}
+
function wfQuery( $sql, $fname = "" )
{
global $wgLastDatabaseQuery, $wgOut;
if( $this->mLastModified != "" ) {
wfDebug( "** private caching; {$this->mLastModified} **\n", false );
header( "Cache-Control: private, must-revalidate, max-age=0" );
+ header( "Vary: Accept-Encoding" );
header( "Last-modified: {$this->mLastModified}" );
} else {
wfDebug( "** no caching **\n", false );
header( "Cache-Control: no-cache" ); # Experimental - see below
header( "Pragma: no-cache" );
+ header( "Vary: Accept-Encoding" );
header( "Last-modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT" );
}
header( "Expires: Mon, 15 Jan 2001 00:00:00 GMT" ); # Cachers always validate the page!
\"$1\"
from within function \"$2\".
MySQL returned error \"$3: $4\".\n",
-"noconnect" => "Could not connect to DB on $1",
+"noconnect" => "Sorry! The wiki is experiencing some technical difficulties, and cannot contact the database server.",
"nodb" => "Could not select database $1",
+"cachederror" => "The following is a cached copy of the requested page, and may not be up to date.",
"readonly" => "Database locked",
"enterlockreason" => "Enter a reason for the lock, including an estimate
of when the lock will be released",