}
}
+/**
+ * Send a line giving PHP memory usage.
+ * @param $exact Bool : print exact values instead of kilobytes (default: false)
+ */
+function wfDebugMem( $exact = false ) {
+ $mem = memory_get_usage();
+ if( !$exact ) {
+ $mem = floor( $mem / 1024 ) . ' kilobytes';
+ } else {
+ $mem .= ' bytes';
+ }
+ wfDebug( "Memory usage: $mem\n" );
+}
+
/**
* Send a line to a supplementary debug log file, if configured, or main debug log if not.
* $wgDebugLogGroups[$logGroup] should be set to a filename to send to a separate log.
* log file is specified, (default true)
*/
function wfDebugLog( $logGroup, $text, $public = true ) {
- global $wgDebugLogGroups;
+ global $wgDebugLogGroups, $wgShowHostnames;
if( $text{strlen( $text ) - 1} != "\n" ) $text .= "\n";
if( isset( $wgDebugLogGroups[$logGroup] ) ) {
$time = wfTimestamp( TS_DB );
$wiki = wfWikiID();
- wfErrorLog( "$time $wiki: $text", $wgDebugLogGroups[$logGroup] );
+ if ( $wgShowHostnames ) {
+ $host = wfHostname();
+ } else {
+ $host = '';
+ }
+ wfErrorLog( "$time $host $wiki: $text", $wgDebugLogGroups[$logGroup] );
} else if ( $public === true ) {
wfDebug( $text, true );
}
}
/**
- * Log to a file without getting "file size exceeded" signals
+ * Log to a file without getting "file size exceeded" signals.
+ *
+ * Can also log to TCP or UDP with the syntax udp://host:port/prefix. This will
+ * send lines to the specified port, prefixed by the specified prefix and a space.
*/
function wfErrorLog( $text, $file ) {
- wfSuppressWarnings();
- $exists = file_exists( $file );
- $size = $exists ? filesize( $file ) : false;
- if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
- error_log( $text, 3, $file );
+ if ( substr( $file, 0, 4 ) == 'udp:' ) {
+ if ( preg_match( '!^(tcp|udp):(?://)?\[([0-9a-fA-F:]+)\]:(\d+)(?:/(.*))?$!', $file, $m ) ) {
+ // IPv6 bracketed host
+ $protocol = $m[1];
+ $host = $m[2];
+ $port = $m[3];
+ $prefix = isset( $m[4] ) ? $m[4] : false;
+ } elseif ( preg_match( '!^(tcp|udp):(?://)?([a-zA-Z0-9-]+):(\d+)(?:/(.*))?$!', $file, $m ) ) {
+ $protocol = $m[1];
+ $host = $m[2];
+ $port = $m[3];
+ $prefix = isset( $m[4] ) ? $m[4] : false;
+ } else {
+ throw new MWException( __METHOD__.": Invalid UDP specification" );
+ }
+ // Clean it up for the multiplexer
+ if ( strval( $prefix ) !== '' ) {
+ $text = preg_replace( '/^/m', $prefix . ' ', $text );
+ if ( substr( $text, -1 ) != "\n" ) {
+ $text .= "\n";
+ }
+ }
+
+ $sock = fsockopen( "$protocol://$host", $port );
+ if ( !$sock ) {
+ return;
+ }
+ fwrite( $sock, $text );
+ fclose( $sock );
+ } else {
+ wfSuppressWarnings();
+ $exists = file_exists( $file );
+ $size = $exists ? filesize( $file ) : false;
+ if ( !$exists || ( $size !== false && $size + strlen( $text ) < 0x7fffffff ) ) {
+ error_log( $text, 3, $file );
+ }
+ wfRestoreWarnings();
}
- wfRestoreWarnings();
}
/**
$options = array($options);
}
+ foreach( $options as $option ) {
+ if( !in_array( $option, array( 'parse', 'parseinline', 'escape',
+ 'escapenoentities', 'replaceafter', 'parsemag', 'content',
+ 'language' ) ) ) {
+ trigger_error( "wfMsgExt called with incorrect parameter $option",
+ E_USER_WARNING );
+ }
+ }
+
if( in_array('content', $options) ) {
$forContent = true;
$langCode = true;
* @return string
*/
function wfHostname() {
- if ( function_exists( 'posix_uname' ) ) {
- // This function not present on Windows
- $uname = @posix_uname();
- } else {
- $uname = false;
- }
- if( is_array( $uname ) && isset( $uname['nodename'] ) ) {
- return $uname['nodename'];
- } else {
- # This may be a virtual server.
- return $_SERVER['SERVER_NAME'];
+ static $host;
+ if ( is_null( $host ) ) {
+ if ( function_exists( 'posix_uname' ) ) {
+ // This function not present on Windows
+ $uname = @posix_uname();
+ } else {
+ $uname = false;
+ }
+ if( is_array( $uname ) && isset( $uname['nodename'] ) ) {
+ $host = $uname['nodename'];
+ } else {
+ # This may be a virtual server.
+ $host = $_SERVER['SERVER_NAME'];
+ }
}
+ return $host;
}
/**
// Reset the 'Content-Encoding' field set by this handler
// so we can start fresh.
header( 'Content-Encoding:' );
+ break;
}
}
}
}
function wfGetCachedNotice( $name ) {
- global $wgOut, $parserMemc;
+ global $wgOut, $wgRenderHashAppend, $parserMemc;
$fname = 'wfGetCachedNotice';
wfProfileIn( $fname );
}
}
- $cachedNotice = $parserMemc->get( wfMemcKey( $name ) );
+ // Use the extra hash appender to let eg SSL variants separately cache.
+ $key = wfMemcKey( $name . $wgRenderHashAppend );
+ $cachedNotice = $parserMemc->get( $key );
if( is_array( $cachedNotice ) ) {
if( md5( $notice ) == $cachedNotice['hash'] ) {
$notice = $cachedNotice['html'];
if( $needParse ) {
if( is_object( $wgOut ) ) {
$parsed = $wgOut->parse( $notice );
- $parserMemc->set( wfMemcKey( $name ), array( 'html' => $parsed, 'hash' => md5( $notice ) ), 600 );
+ $parserMemc->set( $key, array( 'html' => $parsed, 'hash' => md5( $notice ) ), 600 );
$notice = $parsed;
} else {
wfDebug( 'wfGetCachedNotice called for ' . $name . ' with no $wgOut available' );
passthru( $cmd, $retval );
$output = ob_get_contents();
ob_end_clean();
+
+ if ( $retval == 127 ) {
+ wfDebugLog( 'exec', "Possibly missing executable file: $cmd\n" );
+ }
return $output;
}
* will always return the same object, unless the underlying connection or load
* balancer is manually destroyed.
*/
-function &wfGetDB( $db = DB_LAST, $groups = array(), $wiki = false ) {
+function &wfGetDB( $db, $groups = array(), $wiki = false ) {
return wfGetLB( $wiki )->getConnection( $db, $groups, $wiki );
}