00001 <?php
00002
00011 global $wgExternalLoadBalancers;
00012 $wgExternalLoadBalancers = array();
00013
00020 global $wgExternalBlobCache;
00021 $wgExternalBlobCache = array();
00022
00027 class ExternalStoreDB {
00028
00029 function __construct( $params = array() ) {
00030 $this->mParams = $params;
00031 }
00032
00039 function &getLoadBalancer( $cluster ) {
00040 $wiki = isset($this->mParams['wiki']) ? $this->mParams['wiki'] : false;
00041
00042 return wfGetLBFactory()->getExternalLB( $cluster, $wiki );
00043 }
00044
00051 function &getSlave( $cluster ) {
00052 $wiki = isset($this->mParams['wiki']) ? $this->mParams['wiki'] : false;
00053 $lb =& $this->getLoadBalancer( $cluster );
00054 return $lb->getConnection( DB_SLAVE, array(), $wiki );
00055 }
00056
00063 function &getMaster( $cluster ) {
00064 $wiki = isset($this->mParams['wiki']) ? $this->mParams['wiki'] : false;
00065 $lb =& $this->getLoadBalancer( $cluster );
00066 return $lb->getConnection( DB_MASTER, array(), $wiki );
00067 }
00068
00075 function getTable( &$db ) {
00076 $table = $db->getLBInfo( 'blobs table' );
00077 if ( is_null( $table ) ) {
00078 $table = 'blobs';
00079 }
00080 return $table;
00081 }
00082
00087 function fetchFromURL( $url ) {
00088 $path = explode( '/', $url );
00089 $cluster = $path[2];
00090 $id = $path[3];
00091 if ( isset( $path[4] ) ) {
00092 $itemID = $path[4];
00093 } else {
00094 $itemID = false;
00095 }
00096
00097 $ret =& $this->fetchBlob( $cluster, $id, $itemID );
00098
00099 if ( $itemID !== false && $ret !== false ) {
00100 return $ret->getItem( $itemID );
00101 }
00102 return $ret;
00103 }
00104
00115 function &fetchBlob( $cluster, $id, $itemID ) {
00116 global $wgExternalBlobCache;
00117 $cacheID = ( $itemID === false ) ? "$cluster/$id" : "$cluster/$id/";
00118 if( isset( $wgExternalBlobCache[$cacheID] ) ) {
00119 wfDebug( "ExternalStoreDB::fetchBlob cache hit on $cacheID\n" );
00120 return $wgExternalBlobCache[$cacheID];
00121 }
00122
00123 wfDebug( "ExternalStoreDB::fetchBlob cache miss on $cacheID\n" );
00124
00125 $dbr =& $this->getSlave( $cluster );
00126 $ret = $dbr->selectField( $this->getTable( $dbr ), 'blob_text', array( 'blob_id' => $id ) );
00127 if ( $ret === false ) {
00128 wfDebugLog( 'ExternalStoreDB', "ExternalStoreDB::fetchBlob master fallback on $cacheID\n" );
00129
00130 $dbw =& $this->getMaster( $cluster );
00131 $ret = $dbw->selectField( $this->getTable( $dbw ), 'blob_text', array( 'blob_id' => $id ) );
00132 if( $ret === false) {
00133 wfDebugLog( 'ExternalStoreDB', "ExternalStoreDB::fetchBlob master failed to find $cacheID\n" );
00134 }
00135 }
00136 if( $itemID !== false && $ret !== false ) {
00137
00138 $ret = unserialize( $ret );
00139 }
00140
00141 $wgExternalBlobCache = array( $cacheID => &$ret );
00142 return $ret;
00143 }
00144
00152 function store( $cluster, $data ) {
00153 $dbw = $this->getMaster( $cluster );
00154 $id = $dbw->nextSequenceValue( 'blob_blob_id_seq' );
00155 $dbw->insert( $this->getTable( $dbw ),
00156 array( 'blob_id' => $id, 'blob_text' => $data ),
00157 __METHOD__ );
00158 $id = $dbw->insertId();
00159 if ( !$id ) {
00160 throw new MWException( __METHOD__.': no insert ID' );
00161 }
00162 if ( $dbw->getFlag( DBO_TRX ) ) {
00163 $dbw->commit();
00164 }
00165 return "DB://$cluster/$id";
00166 }
00167 }