r100164 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r100163‎ | r100164 | r100165 >
Date:21:36, 18 October 2011
Author:blobaugh
Status:deferred (Comments)
Tags:
Comment:
Updated the architecture for the FileBackend to support multiple data stores registered at the same time through and external interface
Modified paths:
  • /branches/FileBackend/phase3/includes/filerepo/AbstractFileStore.php (added) (history)
  • /branches/FileBackend/phase3/includes/filerepo/FileBackend.php (modified) (history)
  • /branches/FileBackend/phase3/includes/filerepo/dataStores (added) (history)
  • /branches/FileBackend/phase3/includes/filerepo/dataStores/LocalFileSystemDataStore.php (added) (history)
  • /branches/FileBackend/phase3/includes/filerepo/dataStores/MemcachedDataStore.php (added) (history)

Diff [purge]

Index: branches/FileBackend/phase3/includes/filerepo/AbstractFileStore.php
@@ -0,0 +1,42 @@
 2+<?php
 3+
 4+/**
 5+ * A particular data store may not support every operation. If it does not support
 6+ * an operation that should return -1. It should not throw an exception as
 7+ * the operation in question may be naively called from a loop that does not
 8+ * check for support
 9+ */
 10+abstract class AbstractFileStore {
 11+
 12+ abstract store( $params ) {
 13+ return -1;
 14+ }
 15+
 16+ abstract relocate( $params ) {
 17+ return -1;
 18+ }
 19+
 20+ abstract copy( $params ) {
 21+ return -1;
 22+ }
 23+
 24+ abstract delete( $params ) {
 25+ return -1;
 26+ }
 27+
 28+ abstract move( $params ) {
 29+ return -1;
 30+ }
 31+
 32+ abstract concatinate( $params ) {
 33+ return -1;
 34+ }
 35+
 36+ abstract fileExists( $params ) {
 37+ return -1;
 38+ }
 39+
 40+ abstract getLocalCopy( $params ) {
 41+ return -1;
 42+ }
 43+} // end class
\ No newline at end of file
Property changes on: branches/FileBackend/phase3/includes/filerepo/AbstractFileStore.php
___________________________________________________________________
Added: svn:eol-style
144 + native
Index: branches/FileBackend/phase3/includes/filerepo/dataStores/MemcachedDataStore.php
@@ -0,0 +1,8 @@
 2+<?php
 3+
 4+/**
 5+ * Ehh? This could be an interesting one to implement. Could be set as the
 6+ * primary data store for registered data stores in FileBackend. That would
 7+ * cause it to be read first before hitting the real data store. It would also
 8+ * instantly populate the cache with newly stored files
 9+ */
\ No newline at end of file
Property changes on: branches/FileBackend/phase3/includes/filerepo/dataStores/MemcachedDataStore.php
___________________________________________________________________
Added: svn:eol-style
110 + native
Index: branches/FileBackend/phase3/includes/filerepo/dataStores/LocalFileSystemDataStore.php
@@ -0,0 +1,6 @@
 2+<?php
 3+
 4+/**
 5+
 6+ * @todo Create a module for the FileBackend that extends AbstractFileStore to implement the logic for using the local file system as a data store
 7+ */
\ No newline at end of file
Property changes on: branches/FileBackend/phase3/includes/filerepo/dataStores/LocalFileSystemDataStore.php
___________________________________________________________________
Added: svn:eol-style
18 + native
Index: branches/FileBackend/phase3/includes/filerepo/FileBackend.php
@@ -1,123 +1,232 @@
22 <?php
33
 4+/**
 5+ * Handles all operations on real files. The FileBacked is designed to be an
 6+ * abstraction layer that allows developers to create a new class that extends
 7+ * this class to use any arbitrary data store for media uploads. To manipulate
 8+ * files contained within the current MediaWiki installation the dev/extension
 9+ * writer need only to interact with the doOps() method in this class
 10+ *
 11+ * PLEASE PLEASE leave feedback on improving this file abstraction layer
 12+ *
 13+ * @todo Implement streamFile
 14+ * @todo Implement enumFiles
 15+ * @todo Design and implement smart file chunking uploads
 16+ * @todo Fill in $this->validOperations via reflection into AbstractDataStore
 17+ * @todo implement a method to ensure there is a primary store that registerDataStore can use
 18+ * @todo Alter registerDataStore with the above to set incoming data store as primary if one does not exist
 19+ * @todo Alter registerDataStore to alter the current primary to false if isPrimaryStore is set to true on incoming
 20+ * @todo Register data store in global and existing in includes/filerepo/dataStores inside of constructor
 21+ */
422 abstract class FileBackend {
523
 24+ /*
 25+ * This could potentially be populated via reflection. Look at the methods
 26+ * available in the AbstratDataStore object
 27+ */
 28+ protected $validOperations = array('store'/* add a new file to data store */,
 29+ 'relocate' /* used to relocate all files in store */,
 30+ 'copy',
 31+ 'delete',
 32+ 'move',
 33+ 'concatinate',
 34+ 'fileExists',
 35+ 'getFileProps',
 36+ 'getLocalCopy'
 37+ /* 'streamFile' not yet implemented , */
 38+ /* 'enumFiles' not yet implemented*/
 39+ );
640
 41+ private $registeredDataStores = array();
 42+
 43+ /**
 44+ * Constructor, currently does nothing
 45+ */
746 public function __construct();
847
948
 49+
 50+ /**
 51+ * This is the main entry point into the file system back end. Callers will
 52+ * supply a list of operations to be performed (almost like a script) as an
 53+ * array. This class will then handle handing the operations off to the
 54+ * correct file store module
 55+ *
 56+ * For more information about a specific operation see the abstract method
 57+ * definitions comment block
 58+ *
 59+ * Using $ops
 60+ * $ops is an array of arrays. The first array holds a list of operations.
 61+ * The inner array contains the parameters, E.G:
 62+ * <code>
 63+ * $ops = array(
 64+ * array('operation' => 'store',
 65+ * 'src' => '/tmp/uploads/picture.png',
 66+ * 'dest' => 'zone/uploadedFilename.png'
 67+ * )
 68+ * );
 69+ * </code>
 70+ * @param Array $ops - Array of arrays containing N operations to execute IN ORDER
 71+ * @return Status
 72+ */
1073 public function doOps($ops) {
1174 if(!is_array($ops)) {
1275 throw new MWException(__METHOD__ . " not provided with an operations array");
1376 }
1477
 78+ $statusObject = ''; // some sort of status object that can hold other status objects
 79+
1580 foreach($ops AS $op) {
16 -
17 - switch ($op['operations']) {
 81+ switch ($op['operation']) {
1882 case 'move':
19 - $this->move($params);
 83+ $statusObject->append($this->commonCaller('move', $op));
2084 break;
2185 case 'delete':
22 - $this->delete($params);
 86+ $statusObject->append($this->commonCaller('delete', $op));
2387 break;
2488 case 'copy':
25 - $result = $this->copy();
 89+ $statusObject->append($this->copy());
 90+ break;
 91+ case 'getFileProps':
 92+ $tmpFile = $this->getLocalCopy();
 93+ $statusObject->append($this->getFileProps($tmpFile));
2694 default:
27 - throw new MWException("$op unknown in " . __METHOD__);
 95+ $statusObject->append('Unknown data store operation ' . $op['operation']);
2896
2997 }
3098 }
 99+
 100+ return 'STATUS OBJECT';
31101 }
32102
33 -
34103 /**
35 - * Store a file to a given destination.
36104 *
37 - * @param $srcPath String: source path or virtual URL
38 - * @param $dstZone String: destination zone
39 - * @param $dstRel String: destination relative path
40 - * @param $flags Integer: bitwise combination of the following flags:
41 - * self::DELETE_SOURCE Delete the source file after upload
42 - * self::OVERWRITE Overwrite an existing destination file instead of failing
43 - * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
44 - * same contents as the source
45 - * @return FileRepoStatus
 105+ * @param <type> $dataStoreObject
 106+ * @param <type> $isPrimaryStore
46107 */
47 - abstract function store( $srcPath, $dstZone, $dstRel, $flags = 0 );
 108+ public function registerDataStoreModule($dataStoreObject, $isPrimaryStore = false) {
 109+ if(is_subclassof($dataStoreObject, 'AbstractDataStore')) {
 110+ $this->registeredDataStores[] = array($dataSourceObject, $isPrimaryStore);
 111+ }
 112+ }
48113
49 - /**
50 - * Verify that a file exists in the file store
51 - *
52 - * @param String $file
53 - * @param Integer $flags
54 - * @return Boolean
55 - */
56 - abstract function fileExists( $file, $flags = 0 );
57 -
58114 /**
59 - * Move a file to the deletion archive.
60 - * If no valid deletion archive exists, this may either delete the file
61 - * or throw an exception, depending on the preference of the repository
62 - * @param $srcRel Mixed: relative path for the file to be deleted
63 - * @param $archiveRel Mixed: relative path for the archive location.
64 - * Relative to a private archive directory.
65 - * @return FileRepoStatus object
66 - */
67 - abstract function delete( $srcRel, $archiveRel );
68 -
69 - /**
70 - * Moves a file from one place to another in the file store
 115+ * Ensure that there are data stores registered. If not then register the
 116+ * local file system as the default data store
71117 *
72 - * @param String $srcRel - Path to source file
73 - * @param String $destRel - Path to new destination
74 - * @return Boolean
 118+ * @todo Create local data store object and set as default if no store exists
75119 */
76 - abstract function move( $srcRel, $destRel );
 120+ private function ensureRegisteredDataStore() {
 121+ if(empty($this->registeredDataStores)) {
 122+ // $this->registerDataStoreModule(new LocalFileSystemDataStore())
 123+ }
 124+ }
77125
78 - abstract function copy ( $src, $dest );
79 -
80 -
81 -
82 -
83 -
84 -
85126 /**
86 - * Retreive a copy of a file from the file store and place it in the local
87 - * $wgTmpDirectory. A new TempLocalFile object should be created and returned
88 - * that contains the local path to the file
89 - *
90 - * Please overload this class inside your storage module
91 - *
92 - * @return TempLocalFile
 127+ * The commonCaller() method is used for operations that contain the same
 128+ * code as many other options. It should be used as often as possible to
 129+ * reduce code duplication
 130+ * @param String $operation
 131+ * @param Array $params
 132+ * @return Status object of some sort
93133 */
94 - abstract function getLocalCopy( $file );
95 -
96 - /**
97 - * Return an associative array containing the file properties
98 - *
99 - * @param String $file
100 - * @return Array
101 - */
102 - public function getFileProps( $file ) {
103 - $file = $this->getLocalCopy( $file );
104 - return File::getPropsFromPath( $file->getPath() );
 134+ private function commonCaller($operation, $params) {
 135+ $statusObject = ''; // new Status object of some sort
 136+ foreach($this->registeredDataStores AS $store) {
 137+ $statusObject->append($store->$operation($params));
 138+ }
 139+ return $statusObject;
105140 }
106141
107 - /**
108 - * Returns an associative array containing a listing of the names of the
109 - * thumbnail files associated with the provided image file
110 - *
111 - * Please overload this class inside your storage module
112 - *
113 - * @param String $file - Name of file to retreive thumbnail listing for
114 - * @retrun Array
115 - */
116 - abstract function getThumbnailList( $file );
117142
 143+// /**
 144+// * Store a file to a given destination.
 145+// *
 146+// * @param $srcPath String: source path or virtual URL
 147+// * @param $dstZone String: destination zone
 148+// * @param $dstRel String: destination relative path
 149+// * @param $flags Integer: bitwise combination of the following flags:
 150+// * self::DELETE_SOURCE Delete the source file after upload
 151+// * self::OVERWRITE Overwrite an existing destination file instead of failing
 152+// * self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
 153+// * same contents as the source
 154+// * @return FileRepoStatus
 155+// */
 156+// abstract function store( $srcPath, $dstZone, $dstRel, $flags = 0 );
 157+//
 158+// /**
 159+// * Verify that a file exists in the file store
 160+// *
 161+// * @param String $file
 162+// * @param Integer $flags
 163+// * @return Boolean
 164+// */
 165+// abstract function fileExists( $file, $flags = 0 );
 166+//
 167+// /**
 168+// * Move a file to the deletion archive.
 169+// * If no valid deletion archive exists, this may either delete the file
 170+// * or throw an exception, depending on the preference of the repository
 171+// * @param $srcRel Mixed: relative path for the file to be deleted
 172+// * @param $archiveRel Mixed: relative path for the archive location.
 173+// * Relative to a private archive directory.
 174+// * @return FileRepoStatus object
 175+// */
 176+// abstract function delete( $srcRel, $archiveRel );
 177+//
 178+// /**
 179+// * Moves a file from one place to another in the file store
 180+// *
 181+// * @param String $srcRel - Path to source file
 182+// * @param String $destRel - Path to new destination
 183+// * @return Boolean
 184+// */
 185+// abstract function move( $srcRel, $destRel );
 186+//
 187+// abstract function copy ( $src, $dest );
 188+//
 189+//
 190+//
 191+//
 192+//
 193+//
 194+// /**
 195+// * Retreive a copy of a file from the file store and place it in the local
 196+// * $wgTmpDirectory. A new TempLocalFile object should be created and returned
 197+// * that contains the local path to the file
 198+// *
 199+// * Please overload this class inside your storage module
 200+// *
 201+// * @return TempLocalFile
 202+// */
 203+// abstract function getLocalCopy( $file );
 204+//
 205+// /**
 206+// * Return an associative array containing the file properties
 207+// *
 208+// * @param String $file
 209+// * @return Array
 210+// */
 211+// public function getFileProps( $file ) {
 212+// $file = $this->getLocalCopy( $file );
 213+// return File::getPropsFromPath( $file->getPath() );
 214+// }
 215+//
 216+// /**
 217+// * Returns an associative array containing a listing of the names of the
 218+// * thumbnail files associated with the provided image file
 219+// *
 220+// * Please overload this class inside your storage module
 221+// *
 222+// * @param String $file - Name of file to retreive thumbnail listing for
 223+// * @retrun Array
 224+// */
 225+// abstract function getThumbnailList( $file );
 226+//
 227+//
 228+//
 229+// public function addChunk() { throw new MWException( __METHOD__ . ' not yet implemented.' ); }
 230+// public function concatenateChunks() { throw new MWException( __METHOD__ . ' not yet implemented.' ); }
118231
119 -
120 - public function addChunk() { throw new MWException( __METHOD__ . ' not yet implemented.' ); }
121 - public function concatenateChunks() { throw new MWException( __METHOD__ . ' not yet implemented.' ); }
122 -
123232
124233 } // end class
\ No newline at end of file

Comments

#Comment by Nikerabbit (talk | contribs)   06:03, 19 October 2011

Typo concatinate?

#Comment by Aaron Schulz (talk | contribs)   21:49, 21 October 2011

IMO: I'd rather see a subclass of AbstractFileStore called FileBackendMultiWrite. AbstractFileStore should be renamed to AbstractFileBackend for consistency and made into an interface.

Also the registerDataStoreModule() functionality should just go in a factory constructor, as we don't backends getting tacked on throughout execution.

Status & tagging log