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