]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/ExternalStoreDB.php
MediaWiki 1.15.4-scripts
[autoinstalls/mediawiki.git] / includes / ExternalStoreDB.php
1 <?php
2
3 /**
4  * External database storage will use one (or more) separate connection pools
5  * from what the main wiki uses. If we load many revisions, such as when doing
6  * bulk backups or maintenance, we want to keep them around over the lifetime
7  * of the script.
8  *
9  * Associative array of LoadBalancer objects, indexed by cluster name.
10  */
11 global $wgExternalLoadBalancers;
12 $wgExternalLoadBalancers = array();
13
14 /**
15  * One-step cache variable to hold base blobs; operations that
16  * pull multiple revisions may often pull multiple times from
17  * the same blob. By keeping the last-used one open, we avoid
18  * redundant unserialization and decompression overhead.
19  */
20 global $wgExternalBlobCache;
21 $wgExternalBlobCache = array();
22
23 /**
24  * DB accessable external objects
25  * @ingroup ExternalStorage
26  */
27 class ExternalStoreDB {
28
29         /** @todo Document.*/
30         function &getLoadBalancer( $cluster ) {
31                 return wfGetLBFactory()->getExternalLB( $cluster );
32         }
33
34         /** @todo Document.*/
35         function &getSlave( $cluster ) {
36                 $lb =& $this->getLoadBalancer( $cluster );
37                 return $lb->getConnection( DB_SLAVE );
38         }
39
40         /** @todo Document.*/
41         function &getMaster( $cluster ) {
42                 $lb =& $this->getLoadBalancer( $cluster );
43                 return $lb->getConnection( DB_MASTER );
44         }
45
46         /** @todo Document.*/
47         function getTable( &$db ) {
48                 $table = $db->getLBInfo( 'blobs table' );
49                 if ( is_null( $table ) ) {
50                         $table = 'blobs';
51                 }
52                 return $table;
53         }
54
55         /**
56          * Fetch data from given URL
57          * @param string $url An url of the form DB://cluster/id or DB://cluster/id/itemid for concatened storage.
58          */
59         function fetchFromURL( $url ) {
60                 $path = explode( '/', $url );
61                 $cluster  = $path[2];
62                 $id       = $path[3];
63                 if ( isset( $path[4] ) ) {
64                         $itemID = $path[4];
65                 } else {
66                         $itemID = false;
67                 }
68
69                 $ret =& $this->fetchBlob( $cluster, $id, $itemID );
70
71                 if ( $itemID !== false && $ret !== false ) {
72                         return $ret->getItem( $itemID );
73                 }
74                 return $ret;
75         }
76
77         /**
78          * Fetch a blob item out of the database; a cache of the last-loaded
79          * blob will be kept so that multiple loads out of a multi-item blob
80          * can avoid redundant database access and decompression.
81          * @param $cluster
82          * @param $id
83          * @param $itemID
84          * @return mixed
85          * @private
86          */
87         function &fetchBlob( $cluster, $id, $itemID ) {
88                 global $wgExternalBlobCache;
89                 $cacheID = ( $itemID === false ) ? "$cluster/$id" : "$cluster/$id/";
90                 if( isset( $wgExternalBlobCache[$cacheID] ) ) {
91                         wfDebug( "ExternalStoreDB::fetchBlob cache hit on $cacheID\n" );
92                         return $wgExternalBlobCache[$cacheID];
93                 }
94
95                 wfDebug( "ExternalStoreDB::fetchBlob cache miss on $cacheID\n" );
96
97                 $dbr =& $this->getSlave( $cluster );
98                 $ret = $dbr->selectField( $this->getTable( $dbr ), 'blob_text', array( 'blob_id' => $id ) );
99                 if ( $ret === false ) {
100                         wfDebugLog( 'ExternalStoreDB', "ExternalStoreDB::fetchBlob master fallback on $cacheID\n" );
101                         // Try the master
102                         $dbw =& $this->getMaster( $cluster );
103                         $ret = $dbw->selectField( $this->getTable( $dbw ), 'blob_text', array( 'blob_id' => $id ) );
104                         if( $ret === false) {
105                                 wfDebugLog( 'ExternalStoreDB', "ExternalStoreDB::fetchBlob master failed to find $cacheID\n" );
106                         }
107                 }
108                 if( $itemID !== false && $ret !== false ) {
109                         // Unserialise object; caller extracts item
110                         $ret = unserialize( $ret );
111                 }
112
113                 $wgExternalBlobCache = array( $cacheID => &$ret );
114                 return $ret;
115         }
116
117         /**
118          * Insert a data item into a given cluster
119          *
120          * @param $cluster String: the cluster name
121          * @param $data String: the data item
122          * @return string URL
123          */
124         function store( $cluster, $data ) {
125                 $dbw = $this->getMaster( $cluster );
126                 $id = $dbw->nextSequenceValue( 'blob_blob_id_seq' );
127                 $dbw->insert( $this->getTable( $dbw ), 
128                         array( 'blob_id' => $id, 'blob_text' => $data ), 
129                         __METHOD__ );
130                 $id = $dbw->insertId();
131                 if ( $dbw->getFlag( DBO_TRX ) ) {
132                         $dbw->immediateCommit();
133                 }
134                 return "DB://$cluster/$id";
135         }
136 }