r107199 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r107198‎ | r107199 | r107200 >
Date:01:38, 24 December 2011
Author:aaron
Status:deferred
Tags:
Comment:
In SwiftFileBackend:
* Updated function names.
* Cleaned up connection handling a bit.
* Use Status object more instead of throwing errors.
* Use parent implementation of doConcatenateInternal().
* Added resolveContainerPath() function to check path length.
* Various other code cleanups.
* Moved down some protected functions and renamed some vars.
Modified paths:
  • /branches/FileBackend/phase3/includes/filerepo/backend/SwiftFileBackend.php (modified) (history)

Diff [purge]

Index: branches/FileBackend/phase3/includes/filerepo/backend/SwiftFileBackend.php
@@ -2,6 +2,8 @@
33 /**
44 * @file
55 * @ingroup FileBackend
 6+ * @author Russ Nelson
 7+ * @author Aaron Schulz
68 */
79
810 /**
@@ -9,16 +11,23 @@
1012 * Status messages should avoid mentioning the Swift account name
1113 * Likewise, error suppression should be used to avoid path disclosure.
1214 *
13 - * @FIXME: resuse connections with auto-connect and don't let connection
14 - * exceptions bubble up from read/write operations.
 15+ * This requires the php-cloudfiles library is present,
 16+ * which is available at https://github.com/rackspace/php-cloudfiles.
 17+ * All of the library classes must be registed in $wgAutoloadClasses.
1518 *
 19+ * @TODO: update MessagesEn for status errors.
 20+ *
1621 * @ingroup FileBackend
1722 */
1823 class SwiftFileBackend extends FileBackend {
19 - protected $swiftUser; // string
20 - protected $swiftKey; // string
21 - protected $swiftAuthUrl; // string
 24+ /** @var CF_Authentication */
 25+ protected $auth; // swift authentication handler
 26+ /** @var CF_Connection */
 27+ protected $conn; // swift connection handle
 28+ protected $connStarted = 0; // integer UNIX timestamp
 29+
2230 protected $swiftProxyUser; // string
 31+ protected $connTTL = 60; // integer seconds
2332
2433 /**
2534 * @see FileBackend::__construct()
@@ -28,308 +37,293 @@
2938 * swiftKey : Authentication key for the above user (used to get sessions)
3039 * swiftProxyUser : Swift user used for end-user hits to proxy server
3140 */
32 - function __construct( array $config ) {
 41+ public function __construct( array $config ) {
3342 parent::__construct( $config );
3443 // Required settings
35 - $this->swiftUser = $config['swiftUser'];
36 - $this->swiftKey = $config['swiftKey'];
37 - $this->swiftAuthUrl = $config['swiftAuthUrl'];
 44+ $this->auth = new CF_Authentication(
 45+ $config['swiftUser'], $config['swiftKey'], $config['swiftAuthUrl'] );
3846 // Optional settings
 47+ $this->connTTL = isset( $config['connTTL'] )
 48+ ? $config['connTTL']
 49+ : 60; // some sane number
3950 $this->swiftProxyUser = isset( $config['swiftProxyUser'] )
4051 ? $config['swiftProxyUser']
4152 : '';
4253 }
4354
4455 /**
45 - * Get a connection to the swift proxy.
46 - *
47 - * @return CF_Connection
 56+ * @see FileBackend::resolveContainerPath()
4857 */
49 - protected function connect() {
50 - $auth = new CF_Authentication(
51 - $this->swiftUser, $this->swiftKey, NULL, $this->swiftAuthUrl );
52 - try {
53 - $auth->authenticate();
54 - } catch ( AuthenticationException $e ) {
55 - throw new MWException( "We can't authenticate ourselves." );
56 - # } catch (InvalidResponseException $e) {
57 - # throw new MWException( __METHOD__ . "unexpected response '$e'" );
 58+ protected function resolveContainerPath( $container, $relStoragePath ) {
 59+ if ( strlen( urlencode( $relStoragePath ) ) > 1024 ) {
 60+ return null; // too long for swift
5861 }
59 - return new CF_Connection( $auth );
 62+ return $relStoragePath;
6063 }
6164
6265 /**
63 - * Given a connection and container name, return the container.
64 - * We KNOW the container should exist, so puke if it doesn't.
65 - *
66 - * @param $conn CF_Connection
67 - *
68 - * @return CF_Container
 66+ * @see FileBackend::doStoreInternal()
6967 */
70 - protected function get_container( $conn, $cont ) {
71 - try {
72 - return $conn->get_container( $cont );
73 - } catch ( NoSuchContainerException $e ) {
74 - throw new MWException( "A container we thought existed, doesn't." );
75 - # } catch (InvalidResponseException $e) {
76 - # throw new MWException( __METHOD__ . "unexpected response '$e'" );
77 - }
78 - }
 68+ function doStoreInternal( array $params ) {
 69+ $status = Status::newGood();
7970
80 - /**
81 - * Copy a file from one place to another place
82 - *
83 - * @param $srcContainer CF_Container
84 - * @param $srcRel String: relative path to the source file.
85 - * @param $dstContainer CF_Container
86 - * @param $dstRel String: relative path to the destination.
87 - */
88 - protected function swiftcopy( $srcContainer, $srcRel, $dstContainer, $dstRel ) {
89 - // The destination must exist already.
90 - $obj = $dstContainer->create_object( $dstRel );
91 - $obj->content_type = 'text/plain'; // overwritten by source object.
92 -
93 - try {
94 - $obj->write( '.' );
95 - } catch ( SyntaxException $e ) {
96 - throw new MWException( "Write failed: $e" );
97 - } catch ( BadContentTypeException $e ) {
98 - throw new MWException( "Missing Content-Type: $e" );
99 - } catch ( MisMatchedChecksumException $e ) {
100 - throw new MWException( __METHOD__ . "should not happen: '$e'" );
 71+ list( $dstCont, $destRel ) = $this->resolveStoragePath( $params['dst'] );
 72+ if ( $destRel === null ) {
 73+ $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
 74+ return $status;
10175 }
10276
103 - try {
104 - $obj = $dstContainer->get_object( $dstRel );
105 - } catch ( NoSuchObjectException $e ) {
106 - throw new MWException( 'The object we just created does not exist: ' .
107 - $dstContainer->name . "/$dstRel: $e" );
 77+ // (a) Get a swift proxy connection
 78+ $conn = $this->getConnection();
 79+ if ( !$conn ) {
 80+ $status->fatal( 'backend-fail-connect' );
 81+ return $status;
10882 }
10983
 84+ // (b) Check the destination container
11085 try {
111 - $srcObj = $srcContainer->get_object( $srcRel );
112 - } catch ( NoSuchObjectException $e ) {
113 - throw new MWException( 'Source file does not exist: ' .
114 - $srcContainer->name . "/$srcRel: $e" );
115 - }
116 -
117 - try {
118 - $dstContainer->copy_object_from($srcObj,$srcContainer,$dstRel);
119 - } catch ( SyntaxException $e ) {
120 - throw new MWException( 'Source file does not exist: ' .
121 - $srcContainer->name . "/$srcRel: $e" );
122 - } catch ( MisMatchedChecksumException $e ) {
123 - throw new MWException( "Checksums do not match: $e" );
 86+ $dContObj = $conn->get_container( $conn, $dstCont );
 87+ } catch ( NoSuchContainerException $e ) {
 88+ $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
 89+ return $status;
 90+ } catch ( InvalidResponseException $e ) {
 91+ $status->fatal( 'backend-fail-connect' );
 92+ return $status;
 93+ } catch ( Exception $e ) { // some other exception?
 94+ $status->fatal( 'backend-fail-internal' );
 95+ return $status;
12496 }
125 - }
12697
127 - /**
128 - * @see FileBackend::doStore()
129 - */
130 - function doStore( array $params ) {
131 - $status = Status::newGood();
132 -
133 - list( $destc, $dest ) = $this->resolveStoragePath( $params['dst'] );
134 - if ( $dest === null ) {
135 - $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
136 - return $status;
137 - }
138 - $conn = $this->connect();
139 - $dstc = $this->get_container( $conn, $destc );
 98+ // (c) Check if the destination object already exists
14099 try {
141 - $objd = $dstc->get_object( $dest );
142 - // if we are still here, it exists.
 100+ $dContObj->get_object( $destRel ); // throws NoSuchObjectException
 101+ // NoSuchObjectException not thrown: file must exist
143102 if ( empty( $params['overwriteDest'] ) ) {
144103 $status->fatal( 'backend-fail-alreadyexists', $params['dst'] );
145104 return $status;
146105 }
147 - $exists = true;
148106 } catch ( NoSuchObjectException $e ) {
149 - $exists = false;
 107+ // NoSuchObjectException thrown: file does not exist
 108+ } catch ( InvalidResponseException $e ) {
 109+ $status->fatal( 'backend-fail-connect' );
 110+ return $status;
 111+ } catch ( Exception $e ) { // some other exception?
 112+ $status->fatal( 'backend-fail-internal' );
 113+ return $status;
150114 }
151115
 116+ // (d) Actually store the object
152117 try {
153 - $obj = $dstc->create_object( $dest);
 118+ $obj = $dContObj->create_object( $destRel );
154119 $obj->load_from_filename( $params['src'], True );
155 - } catch ( SyntaxException $e ) {
156 - throw new MWException( 'missing required parameters' );
157120 } catch ( BadContentTypeException $e ) {
158 - throw new MWException( 'No Content-Type was/could be set' );
159 - } catch (InvalidResponseException $e) {
 121+ $status->fatal( 'backend-fail-contenttype', $params['dst'] );
 122+ } catch ( IOException $e ) {
160123 $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
161 - } catch ( IOException $e ) {
162 - throw new MWException( "error opening file '$e'" );
 124+ } catch ( InvalidResponseException $e ) {
 125+ $status->fatal( 'backend-fail-connect' );
 126+ } catch ( Exception $e ) { // some other exception?
 127+ $status->fatal( 'backend-fail-internal' );
163128 }
 129+
164130 return $status;
165131 }
166132
167133 /**
168 - * @see FileBackend::doCopy()
 134+ * @see FileBackend::doCopyInternal()
169135 */
170 - function doCopy( array $params ) {
 136+ function doCopyInternal( array $params ) {
171137 $status = Status::newGood();
172138
173 - list( $sourcec, $source ) = $this->resolveStoragePath( $params['src'] );
174 - if ( $source === null ) {
 139+ list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
 140+ if ( $srcRel === null ) {
175141 $status->fatal( 'backend-fail-invalidpath', $params['src'] );
176142 return $status;
177143 }
178144
179 - list( $destc, $dest ) = $this->resolveStoragePath( $params['dst'] );
180 - if ( $dest === null ) {
 145+ list( $dstCont, $destRel ) = $this->resolveStoragePath( $params['dst'] );
 146+ if ( $destRel === null ) {
181147 $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
182148 return $status;
183149 }
184150
185 - $conn = $this->connect();
186 - $srcc = $this->get_container( $conn, $sourcec );
187 - $dstc = $this->get_container( $conn, $destc );
 151+ // (a) Get a swift proxy connection
 152+ $conn = $this->getConnection();
 153+ if ( !$conn ) {
 154+ $status->fatal( 'backend-fail-connect' );
 155+ return $status;
 156+ }
 157+
 158+ // (b) Check the source and destination containers
188159 try {
189 - $objd = $dstc->get_object( $dest );
190 - // if we are still here, it exists.
 160+ $sContObj = $this->get_container( $conn, $srcCont );
 161+ $dContObj = $conn->get_container( $conn, $dstCont );
 162+ } catch ( NoSuchContainerException $e ) {
 163+ $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
 164+ return $status;
 165+ } catch ( InvalidResponseException $e ) {
 166+ $status->fatal( 'backend-fail-connect' );
 167+ return $status;
 168+ } catch ( Exception $e ) { // some other exception?
 169+ $status->fatal( 'backend-fail-internal' );
 170+ return $status;
 171+ }
 172+
 173+ // (c) Check if the destination object already exists
 174+ try {
 175+ $dContObj->get_object( $destRel ); // throws NoSuchObjectException
 176+ // NoSuchObjectException not thrown: file must exist
191177 if ( empty( $params['overwriteDest'] ) ) {
192178 $status->fatal( 'backend-fail-alreadyexists', $params['dst'] );
193179 return $status;
194180 }
195 - $exists = true;
196181 } catch ( NoSuchObjectException $e ) {
197 - $exists = false;
 182+ // NoSuchObjectException thrown: file does not exist
 183+ } catch ( InvalidResponseException $e ) {
 184+ $status->fatal( 'backend-fail-connect' );
 185+ return $status;
 186+ } catch ( Exception $e ) { // some other exception?
 187+ $status->fatal( 'backend-fail-internal' );
 188+ return $status;
198189 }
 190+
 191+ // (d) Actually copy the file to the destination
199192 try {
200 - $this->swiftcopy( $srcc, $source, $dstc, $dest );
 193+ $this->swiftcopy( $sContObj, $srcRel, $dContObj, $destRel );
201194 } catch ( InvalidResponseException $e ) {
202 - $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
203 - }
 195+ $status->fatal( 'backend-fail-connect' );
 196+ } catch ( Exception $e ) { // some other exception?
 197+ $status->fatal( 'backend-fail-internal' );
 198+ }
 199+
204200 return $status;
205201 }
206202
207203 /**
208 - * @see FileBackend::doDelete()
 204+ * @see FileBackend::doDeleteInternal()
209205 */
210 - function doDelete( array $params ) {
 206+ function doDeleteInternal( array $params ) {
211207 $status = Status::newGood();
212208
213 - list( $sourcec, $source ) = $this->resolveStoragePath( $params['src'] );
214 - if ( $source === null ) {
 209+ list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
 210+ if ( $srcRel === null ) {
215211 $status->fatal( 'backend-fail-invalidpath', $params['src'] );
216212 return $status;
217213 }
218214
219 - $conn = $this->connect();
220 - $container = $this->get_container( $conn, $sourcec );
 215+ // (a) Get a swift proxy connection
 216+ $conn = $this->getConnection();
 217+ if ( !$conn ) {
 218+ $status->fatal( 'backend-fail-connect' );
 219+ return $status;
 220+ }
221221
 222+ // (b) Check the source container
222223 try {
223 - $obj = $container->get_object( $source );
224 - $exists = true;
 224+ $sContObj = $this->get_container( $conn, $srcCont );
 225+ } catch ( NoSuchContainerException $e ) {
 226+ $status->fatal( 'backend-fail-delete', $params['src'] );
 227+ return $status;
 228+ } catch ( InvalidResponseException $e ) {
 229+ $status->fatal( 'backend-fail-connect' );
 230+ return $status;
 231+ } catch ( Exception $e ) { // some other exception?
 232+ $status->fatal( 'backend-fail-internal' );
 233+ return $status;
 234+ }
 235+
 236+ // (c) Actually delete the object
 237+ try {
 238+ $sContObj->delete_object( $srcRel );
225239 } catch ( NoSuchObjectException $e ) {
226240 if ( empty( $params['ignoreMissingSource'] ) ) {
227241 $status->fatal( 'backend-fail-delete', $params['src'] );
228242 }
229 - $exists = false;
 243+ } catch ( InvalidResponseException $e ) {
 244+ $status->fatal( 'backend-fail-connect' );
 245+ } catch ( Exception $e ) { // some other exception?
 246+ $status->fatal( 'backend-fail-internal' );
230247 }
231248
232 - if ( $exists ) {
233 - try {
234 - $container->delete_object( $source );
235 - } catch ( SyntaxException $e ) {
236 - throw new MWException( "Swift object name not well-formed: '$e'" );
237 - } catch ( NoSuchObjectException $e ) {
238 - throw new MWException( "Swift object we are trying to delete does not exist: '$e'" );
239 - } catch ( InvalidResponseException $e ) {
240 - $status->fatal( 'backend-fail-delete', $params['src'] );
241 - }
242 - }
243 - return $status; // do nothing; either OK or bad status
 249+ return $status;
244250 }
245251
246252 /**
247 - * @see FileBackend::doConcatenate()
 253+ * @see FileBackend::doCopyInternal()
248254 */
249 - function doConcatenate( array $params ) {
 255+ function doCreateInternal( array $params ) {
250256 $status = Status::newGood();
251257
252 - list( $destc, $dest ) = $this->resolveStoragePath( $params['dst'] );
253 - if ( $dest === null ) {
 258+ list( $dstCont, $destRel ) = $this->resolveStoragePath( $params['dst'] );
 259+ if ( $destRel === null ) {
254260 $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
255261 return $status;
256262 }
257263
258 - $conn = $this->connect();
259 - $dstc = $this->get_container( $conn, $destc );
260 - try {
261 - $objd = $dstc->get_object( $dest );
262 - // if we are still here, it exists.
263 - if ( empty( $params['overwriteDest'] ) ) {
264 - $status->fatal( 'backend-fail-alreadyexists', $params['dst'] );
265 - return $status;
266 - }
267 - $exists = true;
268 - } catch ( NoSuchObjectException $e ) {
269 - $exists = false;
 264+ // (a) Get a swift proxy connection
 265+ $conn = $this->getConnection();
 266+ if ( !$conn ) {
 267+ $status->fatal( 'backend-fail-connect' );
 268+ return $status;
270269 }
271270
 271+ // (b) Check the destination container
272272 try {
273 - $biggie = $dstc->create_object( $dest );
 273+ $dContObj = $conn->get_container( $conn, $dstCont );
 274+ } catch ( NoSuchContainerException $e ) {
 275+ $status->fatal( 'backend-fail-create', $params['dst'] );
 276+ return $status;
274277 } catch ( InvalidResponseException $e ) {
275 - $status->fatal( 'backend-fail-opentemp', $tmpPath );
 278+ $status->fatal( 'backend-fail-connect' );
276279 return $status;
277 - }
278 -
279 - foreach ( $params['srcs'] as $virtualSource ) {
280 - list( $sourcec, $source ) = $this->resolveStoragePath( $virtualSource );
281 - if ( $source === null ) {
282 - $status->fatal( 'backend-fail-invalidpath', $virtualSource );
283 - return $status;
284 - }
285 - $srcc = $this->get_container( $conn, $sourcec );
286 - $obj = $srcc->get_object( $source );
287 - $biggie->write( $obj->read() );
288 - }
289 - return $status;
290 - }
291 -
292 - /**
293 - * @see FileBackend::doCopy()
294 - */
295 - function doCreate( array $params ) {
296 - $status = Status::newGood();
297 -
298 - list( $destc, $dest ) = $this->resolveStoragePath( $params['dst'] );
299 - if ( $dest === null ) {
300 - $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
 280+ } catch ( Exception $e ) { // some other exception?
 281+ $status->fatal( 'backend-fail-internal' );
301282 return $status;
302283 }
303284
304 - $conn = $this->connect();
305 - $dstc = $this->get_container( $conn, $destc );
 285+ // (c) Check if the destination object already exists
306286 try {
307 - $objd = $dstc->get_object( $dest );
308 - // if we are still here, it exists.
 287+ $dContObj->get_object( $destRel ); // throws NoSuchObjectException
 288+ // NoSuchObjectException not thrown: file must exist
309289 if ( empty( $params['overwriteDest'] ) ) {
310290 $status->fatal( 'backend-fail-alreadyexists', $params['dst'] );
311291 return $status;
312292 }
313 - $exists = true;
314293 } catch ( NoSuchObjectException $e ) {
315 - $exists = false;
 294+ // NoSuchObjectException thrown: file does not exist
 295+ } catch ( InvalidResponseException $e ) {
 296+ $status->fatal( 'backend-fail-connect' );
 297+ return $status;
 298+ } catch ( Exception $e ) { // some other exception?
 299+ $status->fatal( 'backend-fail-internal' );
 300+ return $status;
316301 }
317302
318 - $obj = $dstc->create_object( $dest );
319 - //FIXME how do we know what the content type is?
320 - // This *should* work...cloudfiles can figure content type from strings too.
321 - $obj->content_type = 'text/plain';
322 -
 303+ // (d) Actually create the object
323304 try {
 305+ $obj = $dContObj->create_object( $destRel );
324306 $obj->write( $params['content'] );
 307+ } catch ( BadContentTypeException $e ) {
 308+ $status->fatal( 'backend-fail-contenttype', $params['dst'] );
325309 } catch ( InvalidResponseException $e ) {
326 - $status->fatal( 'backend-fail-create', $params['dst'] );
327 - return $status;
 310+ $status->fatal( 'backend-fail-connect' );
 311+ } catch ( Exception $e ) { // some other exception?
 312+ $status->fatal( 'backend-fail-internal' );
328313 }
329314
330315 return $status;
331316 }
332317
333318 /**
 319+ * @see FileBackend::prepate()
 320+ */
 321+ function prepare( array $params ) {
 322+ $status = Status::newGood();
 323+ // @TODO: create containers as needed
 324+ return $status; // badgers? We don't need no steenking badgers!
 325+ }
 326+
 327+ /**
334328 * @see FileBackend::secure()
335329 */
336330 function secure( array $params ) {
@@ -342,18 +336,29 @@
343337 * @see FileBackend::fileExists()
344338 */
345339 function fileExists( array $params ) {
346 - list( $sourcec, $source ) = $this->resolveStoragePath( $params['src'] );
347 - if ( $source === null ) {
 340+ list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
 341+ if ( $srcRel === null ) {
348342 return false; // invalid storage path
349343 }
350 - $conn = $this->connect();
351 - $container = $this->get_container( $conn, $sourcec );
 344+
 345+ $conn = $this->getConnection();
 346+ if ( !$conn ) {
 347+ $status->fatal( 'backend-fail-connect' );
 348+ return $status;
 349+ }
 350+
352351 try {
353 - $obj = $container->get_object( $source );
 352+ $container = $this->get_container( $conn, $srcCont );
 353+ $container->get_object( $srcRel );
354354 $exists = true;
 355+ } catch ( NoSuchContainerException $e ) {
 356+ $exists = false;
355357 } catch ( NoSuchObjectException $e ) {
356358 $exists = false;
 359+ } catch ( Exception $e ) { // some other exception?
 360+ $exists = false; // fail vs not exists?
357361 }
 362+
358363 return $exists;
359364 }
360365
@@ -361,18 +366,28 @@
362367 * @see FileBackend::getFileTimestamp()
363368 */
364369 function getFileTimestamp( array $params ) {
365 - list( $sourcec, $source ) = $this->resolveStoragePath( $params['src'] );
366 - if ( $source === null ) {
 370+ list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
 371+ if ( $srcRel === null ) {
367372 return false; // invalid storage path
368373 }
369374
370 - $conn = $this->connect();
371 - $container = $this->get_container( $conn, $sourcec);
 375+ $conn = $this->getConnection();
 376+ if ( !$conn ) {
 377+ $status->fatal( 'backend-fail-connect' );
 378+ return $status;
 379+ }
 380+
372381 try {
373 - $obj = $container->get_object( $source );
 382+ $container = $this->get_container( $conn, $srcCont);
 383+ $obj = $container->get_object( $srcRel );
 384+ } catch ( NoSuchContainerException $e ) {
 385+ $obj = NULL;
374386 } catch ( NoSuchObjectException $e ) {
375387 $obj = NULL;
 388+ } catch ( Exception $e ) { // some other exception?
 389+ $obj = NULL; // fail vs not exists?
376390 }
 391+
377392 if ( $obj ) {
378393 $thumbTime = $obj->last_modified;
379394 // @FIXME: strptime() UNIX-only (http://php.net/manual/en/function.strptime.php)
@@ -394,10 +409,23 @@
395410 return array(); // empty result
396411 }
397412
398 - $conn = $this->connect();
 413+ $conn = $this->getConnection();
 414+ if ( !$conn ) {
 415+ return null;
 416+ }
 417+
399418 // @TODO: return an Iterator class that pages via list_objects()
400 - $container = $this->get_container( $conn, $dirc );
401 - $files = $container->list_objects( 0, NULL, $dir );
 419+ try {
 420+ $container = $this->get_container( $conn, $dirc );
 421+ $files = $container->list_objects( 0, NULL, $dir );
 422+ } catch ( NoSuchContainerException $e ) {
 423+ $files = array();
 424+ } catch ( NoSuchObjectException $e ) {
 425+ $files = array();
 426+ } catch ( Exception $e ) { // some other exception?
 427+ $files = null;
 428+ }
 429+
402430 // if there are no files matching the prefix, return empty array
403431 return $files;
404432 }
@@ -406,39 +434,111 @@
407435 * @see FileBackend::getLocalCopy()
408436 */
409437 function getLocalCopy( array $params ) {
410 - list( $sourcec, $source ) = $this->resolveStoragePath( $params['src'] );
411 - if ( $source === null ) {
 438+ list( $srcCont, $srcRel ) = $this->resolveStoragePath( $params['src'] );
 439+ if ( $srcRel === null ) {
412440 return null;
413441 }
414442
415443 // Get source file extension
416 - $i = strrpos( $source, '.' );
417 - $ext = strtolower( $i ? substr( $source, $i + 1 ) : '' );
 444+ $ext = FileBackend::extensionFromPath( $srcRel );
418445 // Create a new temporary file...
419 - $tmpFile = TempFSFile::factory( wfBaseName( $source ) . '_', $ext );
 446+ $tmpFile = TempFSFile::factory( wfBaseName( $srcRel ) . '_', $ext );
420447 if ( !$tmpFile ) {
421448 return null;
422449 }
423450 $tmpPath = $tmpFile->getPath();
424451
425 - $conn = $this->connect();
426 - $cont = $this->get_container( $conn, $sourcec );
427 -
428 - try {
429 - $obj = $cont->get_object( $source );
430 - } catch ( NoSuchObjectException $e ) {
431 - throw new MWException( "Unable to open original file at", $params['src'] );
 452+ $conn = $this->getConnection();
 453+ if ( !$conn ) {
 454+ return null;
432455 }
433456
434457 try {
 458+ $cont = $this->get_container( $conn, $srcCont );
 459+ $obj = $cont->get_object( $srcRel );
435460 $obj->save_to_filename( $tmpPath );
 461+ } catch ( NoSuchContainerException $e ) {
 462+ $tmpFile = null;
 463+ } catch ( NoSuchObjectException $e ) {
 464+ $tmpFile = null;
436465 } catch ( IOException $e ) {
437 - // throw new MWException( __METHOD__ . ": error opening '$e'" );
438 - return null;
439 - } catch ( InvalidResponseException $e ) {
440 - // throw new MWException( __METHOD__ . "unexpected response '$e'" );
441 - return null;
 466+ $tmpFile = null;
 467+ } catch ( Exception $e ) { // some other exception?
 468+ $tmpFile = null;
442469 }
 470+
443471 return $tmpFile;
444472 }
 473+
 474+ /**
 475+ * Get a connection to the swift proxy
 476+ *
 477+ * @return CF_Connection|null
 478+ */
 479+ protected function getConnection() {
 480+ if ( $this->conn === false ) {
 481+ return null; // failed last attempt
 482+ }
 483+ // Authenticate with proxy and get a session key.
 484+ // Session keys expire after a while, so we renew them periodically.
 485+ if ( $this->conn === null || ( time() - $this->connStarted ) > $this->connTTL ) {
 486+ try {
 487+ $this->auth->authenticate();
 488+ $this->conn = new CF_Connection( $this->auth );
 489+ $this->connStarted = time();
 490+ } catch ( AuthenticationException $e ) {
 491+ $this->conn = false; // don't keep re-trying
 492+ } catch ( InvalidResponseException $e ) {
 493+ $this->conn = false; // don't keep re-trying
 494+ }
 495+ }
 496+ return $this->conn;
 497+ }
 498+
 499+ /**
 500+ * Copy a file from one place to another place
 501+ *
 502+ * @param $srcContainer CF_Container
 503+ * @param $srcRel String: relative path to the source file.
 504+ * @param $dstContainer CF_Container
 505+ * @param $dstRel String: relative path to the destination.
 506+ */
 507+ protected function swiftcopy( $srcContainer, $srcRel, $dstContainer, $dstRel ) {
 508+ // The destination must exist already.
 509+ $obj = $dstContainer->create_object( $dstRel );
 510+ $obj->content_type = 'text/plain'; // overwritten by source object.
 511+
 512+ try {
 513+ $obj->write( '.' );
 514+ } catch ( SyntaxException $e ) {
 515+ throw new MWException( "Write failed: $e" );
 516+ } catch ( BadContentTypeException $e ) {
 517+ throw new MWException( "Missing Content-Type: $e" );
 518+ } catch ( MisMatchedChecksumException $e ) {
 519+ throw new MWException( __METHOD__ . "should not happen: '$e'" );
 520+ }
 521+
 522+ try {
 523+ $obj = $dstContainer->get_object( $dstRel );
 524+ } catch ( NoSuchObjectException $e ) {
 525+ throw new MWException( 'The object we just created does not exist: ' .
 526+ $dstContainer->name . "/$dstRel: $e" );
 527+ }
 528+
 529+ try {
 530+ $srcObj = $srcContainer->get_object( $srcRel );
 531+ } catch ( NoSuchObjectException $e ) {
 532+ throw new MWException( 'Source file does not exist: ' .
 533+ $srcContainer->name . "/$srcRel: $e" );
 534+ }
 535+
 536+ try {
 537+ $dstContainer->copy_object_from($srcObj,$srcContainer,$dstRel);
 538+ } catch ( SyntaxException $e ) {
 539+ throw new MWException( 'Source file does not exist: ' .
 540+ $srcContainer->name . "/$srcRel: $e" );
 541+ } catch ( MisMatchedChecksumException $e ) {
 542+ throw new MWException( "Checksums do not match: $e" );
 543+ }
 544+ }
445545 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r108256NULL -> null, ping r107199demon17:29, 6 January 2012

Status & tagging log