Wikia code/includes/memcached-client.php

From mediawiki.org
--- D:\Programming\SVN\mediawiki\branches\REL1_16\phase3\includes\memcached-client.php	2011-07-18 22:31:28.344726600 +0100
+++ D:\Programming\SVN\wikia\trunk\includes\memcached-client.php	2011-08-17 15:28:46.679687500 +0100
@@ -230,6 +230,12 @@
 	 */
 	var $_connect_attempts;
 
+   /**
+    * Internal memoization to avoid unnecessary network requests
+    * If a get() is done twice in a single request use the stored value
+    */
+   var $_dupe_cache;
+
 	// }}}
 	// }}}
 	// {{{ methods
@@ -255,6 +261,7 @@
 
 		$this->_cache_sock = array();
 		$this->_host_dead = array();
+		$this->_dupe_cache = array();
 
 		$this->_timeout_seconds = 0;
 		$this->_timeout_microseconds = $wgMemCachedTimeout;
@@ -311,6 +318,8 @@
 			return false;
 		}
 
+		unset($this->_dupe_cache[$key]);
+
 		$sock = $this->get_sock( $key );
 		if ( !is_resource( $sock ) ) {
 			return false;
@@ -327,7 +336,7 @@
 		$res = trim( fgets( $sock ) );
 
 		if ( $this->_debug ) {
-			$this->_debugprint( sprintf( "MemCache: delete %s (%s)\n", $key, $res ) );
+			$this->_debugprint( sprintf( "MemCache: delete %s (%s)\n", $key, $res ), 2 );
 		}
 
 		if ( $res == "DELETED" ) {
@@ -386,7 +395,7 @@
 		wfProfileIn( __METHOD__ );
 
 		if ( $this->_debug ) {
-			$this->_debugprint( "get($key)\n" );
+			$this->_debugprint( "get($key)\n", 2 );
 		}
 
 		if ( !$this->_active ) {
@@ -403,6 +412,14 @@
 
 		@$this->stats['get']++;
 
+        // Memoize duplicate memcache requests for the same key in the same request
+		if (isset($this->_dupe_cache[$key])) {
+			wfProfileIn ( __METHOD__ . "::$key !DUPE");
+			wfProfileOut ( __METHOD__ . "::$key !DUPE");
+			wfProfileOut( __METHOD__ );
+			return $this->_dupe_cache[$key];
+		}
+
 		$cmd = "get $key\r\n";
 		if ( !$this->_safe_fwrite( $sock, $cmd, strlen( $cmd ) ) ) {
 			$this->_dead_sock( $sock );
@@ -415,12 +432,24 @@
 
 		if ( $this->_debug ) {
 			foreach ( $val as $k => $v ) {
-				$this->_debugprint( sprintf( "MemCache: sock %s got %s\n", serialize( $sock ), $k ) );
+				$this->_debugprint( sprintf( "MemCache: sock %s got %s\n", serialize( $sock ), $k ), 3 );
+			}
 			}
+
+		// Owen wants to get more detailed profiling info
+		if (isset ($val[$key])) {
+			$this->_dupe_cache[$key] = $val[$key];
+			wfProfileIn ( __METHOD__ . "::$key !HIT");
+			wfProfileOut ( __METHOD__ . "::$key !HIT");
+		} else {
+			$this->_dupe_cache[$key] = null;
+			wfProfileIn ( __METHOD__ . "::$key !MISS");
+			wfProfileOut ( __METHOD__ . "::$key !MISS");
 		}
 
 		wfProfileOut( __METHOD__ );
-		return @$val[$key];
+		return isset($val[$key]) ? $val[$key] : null;
+		//return @$val[$key];
 	}
 
 	// }}}
@@ -477,7 +506,7 @@
 
 		if ( $this->_debug ) {
 			foreach ( $val as $k => $v ) {
-				$this->_debugprint( sprintf( "MemCache: got %s\n", $k ) );
+				$this->_debugprint( sprintf( "MemCache: got %s\n", $k ), 3 );
 			}
 		}
 
@@ -676,7 +705,7 @@
 		}
 		if ( !$sock ) {
 			if ( $this->_debug ) {
-				$this->_debugprint( "Error connecting to $host: $errstr\n" );
+				$this->_debugprint( "Error connecting to $host: $errstr\n", 1 );
 			}
 			return false;
 		}
@@ -802,6 +831,7 @@
 		}
 
 		$key = is_array( $key ) ? $key[1] : $key;
+		unset($this->_dupe_cache[$key]);
 		@$this->stats[$cmd]++;
 		if ( !$this->_safe_fwrite( $sock, "$cmd $key $amt\r\n" ) ) {
 			return $this->_dead_sock( $sock );
@@ -850,7 +880,7 @@
 				if ( $offset != $len + 2 ) {
 					// Something is borked!
 					if ( $this->_debug ) {
-						$this->_debugprint( sprintf( "Something is borked!  key %s expecting %d got %d length\n", $rkey, $len + 2, $offset ) );
+						$this->_debugprint( sprintf( "Something is borked!  key %s expecting %d got %d length\n", $rkey, $len + 2, $offset ), 1 );
 					}
 
 					unset( $ret[$rkey] );
@@ -869,7 +899,7 @@
 				}
 
 			} else {
-				$this->_debugprint( "Error parsing memcached response\n" );
+				$this->_debugprint( "Error parsing memcached response\n", 1 );
 				return 0;
 			}
 		}
@@ -899,6 +929,9 @@
 			return false;
 		}
 
+		// Memoize duplicate memcache requests for the same key in the same request
+		$this->_dupe_cache[$key] = $val;
+
 		@$this->stats[$cmd]++;
 
 		$flags = 0;
@@ -907,7 +940,7 @@
 			$val = serialize( $val );
 			$flags |= self::SERIALIZED;
 			if ( $this->_debug ) {
-				$this->_debugprint( sprintf( "client: serializing data as it is not scalar\n" ) );
+				$this->_debugprint( sprintf( "client: serializing data as it is not scalar\n" ), 2 );
 			}
 		}
 
@@ -921,7 +954,7 @@
 
 			if ( $c_len < $len * ( 1 - self::COMPRESSION_SAVINGS ) ) {
 				if ( $this->_debug ) {
-					$this->_debugprint( sprintf( "client: compressing data; was %d bytes is now %d bytes\n", $len, $c_len ) );
+					$this->_debugprint( sprintf( "client: compressing data; was %d bytes is now %d bytes\n", $len, $c_len ), 3 );
 				}
 				$val = $c_val;
 				$len = $c_len;
@@ -935,7 +968,7 @@
 		$line = trim( fgets( $sock ) );
 
 		if ( $this->_debug ) {
-			$this->_debugprint( sprintf( "%s %s (%s)\n", $cmd, $key, $line ) );
+			$this->_debugprint( sprintf( "%s %s (%s)\n", $cmd, $key, $line ), 3 );
 		}
 		if ( $line == "STORED" ) {
 			return true;
@@ -980,7 +1013,7 @@
 		return $this->_cache_sock[$host];
 	}
 
-	function _debugprint( $str ) {
+	function _debugprint( $str, $level = 1 ) {
 		print( $str );
 	}
 
@@ -1045,7 +1078,25 @@
 // }}}
 
 class MemCachedClientforWiki extends MWMemcached {
-	function _debugprint( $text ) {
-		wfDebug( "memcached: $text" );
+	function _debugprint( $text, $level = 1 ) {
+		global $wgMemCachedDebugLevel;
+		if( $level <= $wgMemCachedDebugLevel ) {
+			error_log( "memcached: $text" );
+		}
+	}
+	/* Wikia change begin - @author: garth */
+	public function delete( $key, $time = 0 ) {
+		global $wgSharedDB, $wgExternalSharedDB, $wgCityId, $wgDisableMemCachedReplication;
+
+		// handle uncyclo, staff/internal case
+		// @todo -- use configuration variable for that
+		if( $wgDisableMemCachedReplication === false && !wfReadOnly( ) && !empty( $wgCityId ) ) {
+			$db = (empty( $wgSharedDB ) ) ? $wgExternalSharedDB : $wgSharedDB;
+			$dbw = wfGetDB( DB_MASTER, array(), $db );
+			$dbw->insert('memcached', array('memkey' => $key), __METHOD__ );
+			$dbw->commit(); // for ajax
+		}
+		return parent::delete($key, $time);
 	}
+	/* Wikia change end */
 }