From a37f67909f638fad9d1ba67881c2e78148c9c597 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Mon, 21 Jan 2013 14:40:15 -0800 Subject: [PATCH] [ExternalStore] Refactored external store classes to use a base class. * Added ExternalStoreMedium base class * Moved up two functions in ExternalStoreDB * Various documentation tweaks Change-Id: I6790aab7799609422e7af4fb31d2ad60610298ec --- includes/AutoLoader.php | 1 + includes/externalstore/ExternalStore.php | 38 ++++--- includes/externalstore/ExternalStoreDB.php | 102 ++++++++---------- includes/externalstore/ExternalStoreHttp.php | 20 ++-- .../externalstore/ExternalStoreMedium.php | 58 ++++++++++ 5 files changed, 136 insertions(+), 83 deletions(-) create mode 100644 includes/externalstore/ExternalStoreMedium.php diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index c1889756b9..8096ed6dc1 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -94,6 +94,7 @@ $wgAutoloadLocalClasses = array( 'ExternalStore' => 'includes/externalstore/ExternalStore.php', 'ExternalStoreDB' => 'includes/externalstore/ExternalStoreDB.php', 'ExternalStoreHttp' => 'includes/externalstore/ExternalStoreHttp.php', + 'ExternalStoreMedium' => 'includes/externalstore/ExternalStoreMedium.php', 'ExternalUser' => 'includes/ExternalUser.php', 'FakeTitle' => 'includes/FakeTitle.php', 'Fallback' => 'includes/Fallback.php', diff --git a/includes/externalstore/ExternalStore.php b/includes/externalstore/ExternalStore.php index 55c1acf676..8bf1ca976a 100644 --- a/includes/externalstore/ExternalStore.php +++ b/includes/externalstore/ExternalStore.php @@ -25,18 +25,21 @@ */ /** - * Constructor class for data kept in external repositories. + * Constructor class for key/value blob data kept in external repositories. * * Objects in external stores are defined by a special URL. The URL is of - * the form ":///". When an object - * is inserted into a store, the calling code uses a partial URL of the form - * "://" and receives the full object URL on success. + * the form ":///". The protocal is used + * to determine what ExternalStoreMedium class is used. The location identifies + * particular storage instances or database clusters for store class to use. + * + * When an object is inserted into a store, the calling code uses a partial URL of + * the form "://" and receives the full object URL on success. * This is useful since object names can be sequential IDs, UUIDs, or hashes. * Callers are not responsible for unique name generation. * * External repositories might be populated by maintenance/async * scripts, thus partial moving of data may be possible, as well - * as possibility to have any storage format (i.e. for archives) + * as the possibility to have any storage format (i.e. for archives). * * @ingroup ExternalStorage */ @@ -44,9 +47,9 @@ class ExternalStore { /** * Get an external store object of the given type, with the given parameters * - * @param $proto String: type of external storage, should be a value in $wgExternalStores - * @param $params Array: associative array of parameters for the ExternalStore object. - * @return ExternalStore|bool ExternalStore class or false on error + * @param $proto string Type of external storage, should be a value in $wgExternalStores + * @param $params array Associative array of ExternalStoreMedium parameters + * @return ExternalStoreMedium|bool The store class or false on error */ public static function getStoreObject( $proto, array $params = array() ) { global $wgExternalStores; @@ -63,8 +66,8 @@ class ExternalStore { /** * Fetch data from given URL * - * @param $url String: The URL of the text to get - * @param $params Array: associative array of parameters for the ExternalStore object. + * @param $url string The URL of the text to get + * @param $params array Associative array of ExternalStoreMedium parameters * @return string|bool The text stored or false on error * @throws MWException */ @@ -91,9 +94,10 @@ class ExternalStore { * Store a data item to an external store, identified by a partial URL * The protocol part is used to identify the class, the rest is passed to the * class itself as a parameter. - * @param $url - * @param $data - * @param $params array + * + * @param $url String A partial external store URL ("://") + * @param $data string + * @param $params array Associative array of ExternalStoreMedium parameters * @return string|bool The URL of the stored data item, or false on error * @throws MWException */ @@ -121,8 +125,8 @@ class ExternalStore { * This function does not need a url param, it builds it by * itself. It also fails-over to the next possible clusters. * - * @param $data String - * @param $params Array: associative array of parameters for the ExternalStore object. + * @param $data string + * @param $params array Associative array of ExternalStoreMedium parameters * @return string|bool The URL of the stored data item, or false on error * @throws MWException */ @@ -163,8 +167,8 @@ class ExternalStore { } /** - * @param $data - * @param $wiki + * @param $data string + * @param $wiki string * @return string|bool The URL of the stored data item, or false on error * @throws MWException */ diff --git a/includes/externalstore/ExternalStoreDB.php b/includes/externalstore/ExternalStoreDB.php index 172e4f62a1..8e05cfec61 100644 --- a/includes/externalstore/ExternalStoreDB.php +++ b/includes/externalstore/ExternalStoreDB.php @@ -21,16 +21,55 @@ */ /** - * DB accessable external objects + * DB accessable external objects. + * + * In this system, each store "location" maps to a database "cluster". + * The clusters must be defined in the normal LBFactory configuration. + * * @ingroup ExternalStorage */ -class ExternalStoreDB { +class ExternalStoreDB extends ExternalStoreMedium { + /** + * The URL returned is of the form of the form DB://cluster/id + * or DB://cluster/id/itemid for concatened storage. + * + * @see ExternalStoreMedium::fetchFromURL() + */ + public function fetchFromURL( $url ) { + $path = explode( '/', $url ); + $cluster = $path[2]; + $id = $path[3]; + if ( isset( $path[4] ) ) { + $itemID = $path[4]; + } else { + $itemID = false; + } + + $ret =& $this->fetchBlob( $cluster, $id, $itemID ); + + if ( $itemID !== false && $ret !== false ) { + return $ret->getItem( $itemID ); + } + return $ret; + } /** - * @param $params array + * @see ExternalStoreMedium::store() */ - function __construct( $params = array() ) { - $this->mParams = $params; + public function store( $cluster, $data ) { + $dbw = $this->getMaster( $cluster ); + $id = $dbw->nextSequenceValue( 'blob_blob_id_seq' ); + $dbw->insert( $this->getTable( $dbw ), + array( 'blob_id' => $id, 'blob_text' => $data ), + __METHOD__ ); + $id = $dbw->insertId(); + if ( !$id ) { + throw new MWException( __METHOD__.': no insert ID' ); + } + if ( $dbw->getFlag( DBO_TRX ) ) { + $dbw->commit( __METHOD__ ); + } + return "DB://$cluster/$id"; } /** @@ -40,7 +79,7 @@ class ExternalStoreDB { * @return LoadBalancer object */ function &getLoadBalancer( $cluster ) { - $wiki = isset($this->mParams['wiki']) ? $this->mParams['wiki'] : false; + $wiki = isset($this->params['wiki']) ? $this->params['wiki'] : false; return wfGetLBFactory()->getExternalLB( $cluster, $wiki ); } @@ -54,7 +93,7 @@ class ExternalStoreDB { function &getSlave( $cluster ) { global $wgDefaultExternalStore; - $wiki = isset($this->mParams['wiki']) ? $this->mParams['wiki'] : false; + $wiki = isset($this->params['wiki']) ? $this->params['wiki'] : false; $lb =& $this->getLoadBalancer( $cluster ); if ( !in_array( "DB://" . $cluster, (array)$wgDefaultExternalStore ) ) { @@ -74,7 +113,7 @@ class ExternalStoreDB { * @return DatabaseBase object */ function &getMaster( $cluster ) { - $wiki = isset($this->mParams['wiki']) ? $this->mParams['wiki'] : false; + $wiki = isset($this->params['wiki']) ? $this->params['wiki'] : false; $lb =& $this->getLoadBalancer( $cluster ); return $lb->getConnection( DB_MASTER, array(), $wiki ); } @@ -93,29 +132,6 @@ class ExternalStoreDB { return $table; } - /** - * Fetch data from given URL - * @param $url String: an url of the form DB://cluster/id or DB://cluster/id/itemid for concatened storage. - * @return mixed - */ - function fetchFromURL( $url ) { - $path = explode( '/', $url ); - $cluster = $path[2]; - $id = $path[3]; - if ( isset( $path[4] ) ) { - $itemID = $path[4]; - } else { - $itemID = false; - } - - $ret =& $this->fetchBlob( $cluster, $id, $itemID ); - - if ( $itemID !== false && $ret !== false ) { - 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 @@ -162,28 +178,4 @@ class ExternalStoreDB { $externalBlobCache = array( $cacheID => &$ret ); return $ret; } - - /** - * Insert a data item into a given cluster - * - * @param $cluster String: the cluster name - * @param $data String: the data item - * @throws MWException - * @return string URL - */ - function store( $cluster, $data ) { - $dbw = $this->getMaster( $cluster ); - $id = $dbw->nextSequenceValue( 'blob_blob_id_seq' ); - $dbw->insert( $this->getTable( $dbw ), - array( 'blob_id' => $id, 'blob_text' => $data ), - __METHOD__ ); - $id = $dbw->insertId(); - if ( !$id ) { - throw new MWException( __METHOD__.': no insert ID' ); - } - if ( $dbw->getFlag( DBO_TRX ) ) { - $dbw->commit( __METHOD__ ); - } - return "DB://$cluster/$id"; - } } diff --git a/includes/externalstore/ExternalStoreHttp.php b/includes/externalstore/ExternalStoreHttp.php index 311e32b38c..345c17be26 100644 --- a/includes/externalstore/ExternalStoreHttp.php +++ b/includes/externalstore/ExternalStoreHttp.php @@ -26,20 +26,18 @@ * * @ingroup ExternalStorage */ -class ExternalStoreHttp { - +class ExternalStoreHttp extends ExternalStoreMedium { /** - * Fetch data from given URL - * - * @param $url String: the URL - * @return String: the content at $url + * @see ExternalStoreMedium::fetchFromURL() */ - function fetchFromURL( $url ) { - $ret = Http::get( $url ); - return $ret; + public function fetchFromURL( $url ) { + return Http::get( $url ); } - /* XXX: may require other methods, for store, delete, - * whatever, for initial ext storage + /** + * @see ExternalStoreMedium::store() */ + public function store( $cluster, $data ) { + throw new MWException( "ExternalStoreHttp is read-only and does not support store()." ); + } } diff --git a/includes/externalstore/ExternalStoreMedium.php b/includes/externalstore/ExternalStoreMedium.php new file mode 100644 index 0000000000..6794dd5050 --- /dev/null +++ b/includes/externalstore/ExternalStoreMedium.php @@ -0,0 +1,58 @@ +params = $params; + } + + /** + * Fetch data from given external store URL + * + * @param $url string An external store URL + * @return string|bool The text stored or false on error + * @throws MWException + */ + public abstract function fetchFromURL( $url ); + + /** + * Insert a data item into a given location + * + * @param $location string: the location name + * @param $data string: the data item + * @return string|bool The URL of the stored data item, or false on error + * @throws MWException + */ + public abstract function store( $location, $data ); +} -- 2.20.1