From 41d6bf368bda2d6c86ae4aadffb3428460b3e03c Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 16 Sep 2005 12:00:23 +0000 Subject: [PATCH] * Correct blob caching to reduce redundant blob loads on backups --- RELEASE-NOTES | 1 + includes/ExternalStoreDB.php | 65 ++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 5f15b0b92c..6541a093ed 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -109,6 +109,7 @@ fully support the editing toolbar, but was found to be too confusing. * (bug 1423) LanguageJa.php update * Clean up duplicate code for selection of changeslist style * (bug 3475) anon contrib links on Special:Newpages +* Correct blob caching to reduce redundant blob loads on backups === Caveats === diff --git a/includes/ExternalStoreDB.php b/includes/ExternalStoreDB.php index 3c61726523..d07e23b4d1 100644 --- a/includes/ExternalStoreDB.php +++ b/includes/ExternalStoreDB.php @@ -11,20 +11,38 @@ require_once( 'LoadBalancer.php' ); /** @package MediaWiki */ +/** + * External database storage will use one (or more) separate connection pools + * from what the main wiki uses. If we load many revisions, such as when doing + * bulk backups or maintenance, we want to keep them around over the lifetime + * of the script. + * + * Associative array of LoadBalancer objects, indexed by cluster name. + */ +global $wgExternalLoadBalancers; +$wgExternalLoadBalancers = array(); + +/** + * One-step cache variable to hold base blobs; operations that + * pull multiple revisions may often pull multiple times from + * the same blob. By keeping the last-used one open, we avoid + * redundant unserialization and decompression overhead. + */ +global $wgExternalBlobCache; +$wgExternalBlobCache = array(); + class ExternalStoreDB { - var $loadBalancers = array(); - /** * Fetch data from given URL * @param string $url An url */ function &getLoadBalancer( $cluster ) { - global $wgExternalServers; - if ( !array_key_exists( $cluster, $this->loadBalancers ) ) { - $this->loadBalancers[$cluster] = LoadBalancer::newFromParams( $wgExternalServers[$cluster] ); + global $wgExternalServers, $wgExternalLoadBalancers; + if ( !array_key_exists( $cluster, $wgExternalLoadBalancers ) ) { + $wgExternalLoadBalancers[$cluster] = LoadBalancer::newFromParams( $wgExternalServers[$cluster] ); } - return $this->loadBalancers[$cluster]; + return $wgExternalLoadBalancers[$cluster]; } function &getSlave( $cluster ) { @@ -51,14 +69,39 @@ class ExternalStoreDB { $itemID = false; } - $dbr =& $this->getSlave( $cluster ); - $ret = $dbr->selectField( 'blobs', 'blob_text', array( 'blob_id' => $id ) ); + $ret =& $this->fetchBlob( $cluster, $id, $itemID ); if ( $itemID !== false ) { - # Unserialise object and get item - $obj = unserialize( $ret ); - $ret = $obj->getItem( $itemID ); + return $ret->getItem( $itemID ); + } + return $ret; + } + + /** + * Fetch a blob item out of the database; a cache of the last-loaded + * blob will be kept so that multiple loads out of a multi-item blob + * can avoid redundant database access and decompression. + * @return mixed + * @access private + */ + function &fetchBlob( $cluster, $id, $itemID ) { + global $wgExternalBlobCache; + $cacheID = ( $itemID === false ) ? "$cluster/$id" : "$cluster/$id/"; + if( isset( $wgExternalBlobCache[$cacheID] ) ) { + wfDebug( "ExternalStoreDB::fetchBlob cache hit on $cacheID\n" ); + return $wgExternalBlobCache[$cacheID]; + } + + wfDebug( "ExternalStoreDB::fetchBlob cache miss on $cacheID\n" ); + + $dbr =& $this->getSlave( $cluster ); + $ret = $dbr->selectField( 'blobs', 'blob_text', array( 'blob_id' => $id ) ); + if( $itemID !== false ) { + // Unserialise object; caller extracts item + $ret = unserialize( $ret ); } + + $wgExternalBlobCache = array( $cacheID => &$ret ); return $ret; } -- 2.20.1