Passed
Push — master ( 86d0af...62675e )
by Blizzz
16:15 queued 11s
created
lib/private/Files/ObjectStore/ObjectStoreStorage.php 2 patches
Indentation   +556 added lines, -556 removed lines patch added patch discarded remove patch
@@ -42,563 +42,563 @@
 block discarded – undo
42 42
 use OCP\Files\Storage\IStorage;
43 43
 
44 44
 class ObjectStoreStorage extends \OC\Files\Storage\Common {
45
-	use CopyDirectory;
46
-
47
-	/**
48
-	 * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
49
-	 */
50
-	protected $objectStore;
51
-	/**
52
-	 * @var string $id
53
-	 */
54
-	protected $id;
55
-	/**
56
-	 * @var \OC\User\User $user
57
-	 */
58
-	protected $user;
59
-
60
-	private $objectPrefix = 'urn:oid:';
61
-
62
-	private $logger;
63
-
64
-	public function __construct($params) {
65
-		if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
66
-			$this->objectStore = $params['objectstore'];
67
-		} else {
68
-			throw new \Exception('missing IObjectStore instance');
69
-		}
70
-		if (isset($params['storageid'])) {
71
-			$this->id = 'object::store:' . $params['storageid'];
72
-		} else {
73
-			$this->id = 'object::store:' . $this->objectStore->getStorageId();
74
-		}
75
-		if (isset($params['objectPrefix'])) {
76
-			$this->objectPrefix = $params['objectPrefix'];
77
-		}
78
-		//initialize cache with root directory in cache
79
-		if (!$this->is_dir('/')) {
80
-			$this->mkdir('/');
81
-		}
82
-
83
-		$this->logger = \OC::$server->getLogger();
84
-	}
85
-
86
-	public function mkdir($path) {
87
-		$path = $this->normalizePath($path);
88
-
89
-		if ($this->file_exists($path)) {
90
-			return false;
91
-		}
92
-
93
-		$mTime = time();
94
-		$data = [
95
-			'mimetype' => 'httpd/unix-directory',
96
-			'size' => 0,
97
-			'mtime' => $mTime,
98
-			'storage_mtime' => $mTime,
99
-			'permissions' => \OCP\Constants::PERMISSION_ALL,
100
-		];
101
-		if ($path === '') {
102
-			//create root on the fly
103
-			$data['etag'] = $this->getETag('');
104
-			$this->getCache()->put('', $data);
105
-			return true;
106
-		} else {
107
-			// if parent does not exist, create it
108
-			$parent = $this->normalizePath(dirname($path));
109
-			$parentType = $this->filetype($parent);
110
-			if ($parentType === false) {
111
-				if (!$this->mkdir($parent)) {
112
-					// something went wrong
113
-					return false;
114
-				}
115
-			} elseif ($parentType === 'file') {
116
-				// parent is a file
117
-				return false;
118
-			}
119
-			// finally create the new dir
120
-			$mTime = time(); // update mtime
121
-			$data['mtime'] = $mTime;
122
-			$data['storage_mtime'] = $mTime;
123
-			$data['etag'] = $this->getETag($path);
124
-			$this->getCache()->put($path, $data);
125
-			return true;
126
-		}
127
-	}
128
-
129
-	/**
130
-	 * @param string $path
131
-	 * @return string
132
-	 */
133
-	private function normalizePath($path) {
134
-		$path = trim($path, '/');
135
-		//FIXME why do we sometimes get a path like 'files//username'?
136
-		$path = str_replace('//', '/', $path);
137
-
138
-		// dirname('/folder') returns '.' but internally (in the cache) we store the root as ''
139
-		if (!$path || $path === '.') {
140
-			$path = '';
141
-		}
142
-
143
-		return $path;
144
-	}
145
-
146
-	/**
147
-	 * Object Stores use a NoopScanner because metadata is directly stored in
148
-	 * the file cache and cannot really scan the filesystem. The storage passed in is not used anywhere.
149
-	 *
150
-	 * @param string $path
151
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
152
-	 * @return \OC\Files\ObjectStore\NoopScanner
153
-	 */
154
-	public function getScanner($path = '', $storage = null) {
155
-		if (!$storage) {
156
-			$storage = $this;
157
-		}
158
-		if (!isset($this->scanner)) {
159
-			$this->scanner = new NoopScanner($storage);
160
-		}
161
-		return $this->scanner;
162
-	}
163
-
164
-	public function getId() {
165
-		return $this->id;
166
-	}
167
-
168
-	public function rmdir($path) {
169
-		$path = $this->normalizePath($path);
170
-
171
-		if (!$this->is_dir($path)) {
172
-			return false;
173
-		}
174
-
175
-		if (!$this->rmObjects($path)) {
176
-			return false;
177
-		}
178
-
179
-		$this->getCache()->remove($path);
180
-
181
-		return true;
182
-	}
183
-
184
-	private function rmObjects($path) {
185
-		$children = $this->getCache()->getFolderContents($path);
186
-		foreach ($children as $child) {
187
-			if ($child['mimetype'] === 'httpd/unix-directory') {
188
-				if (!$this->rmObjects($child['path'])) {
189
-					return false;
190
-				}
191
-			} else {
192
-				if (!$this->unlink($child['path'])) {
193
-					return false;
194
-				}
195
-			}
196
-		}
197
-
198
-		return true;
199
-	}
200
-
201
-	public function unlink($path) {
202
-		$path = $this->normalizePath($path);
203
-		$stat = $this->stat($path);
204
-
205
-		if ($stat && isset($stat['fileid'])) {
206
-			if ($stat['mimetype'] === 'httpd/unix-directory') {
207
-				return $this->rmdir($path);
208
-			}
209
-			try {
210
-				$this->objectStore->deleteObject($this->getURN($stat['fileid']));
211
-			} catch (\Exception $ex) {
212
-				if ($ex->getCode() !== 404) {
213
-					$this->logger->logException($ex, [
214
-						'app' => 'objectstore',
215
-						'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
216
-					]);
217
-					return false;
218
-				}
219
-				//removing from cache is ok as it does not exist in the objectstore anyway
220
-			}
221
-			$this->getCache()->remove($path);
222
-			return true;
223
-		}
224
-		return false;
225
-	}
226
-
227
-	public function stat($path) {
228
-		$path = $this->normalizePath($path);
229
-		$cacheEntry = $this->getCache()->get($path);
230
-		if ($cacheEntry instanceof CacheEntry) {
231
-			return $cacheEntry->getData();
232
-		} else {
233
-			return false;
234
-		}
235
-	}
236
-
237
-	public function getPermissions($path) {
238
-		$stat = $this->stat($path);
239
-
240
-		if (is_array($stat) && isset($stat['permissions'])) {
241
-			return $stat['permissions'];
242
-		}
243
-
244
-		return parent::getPermissions($path);
245
-	}
246
-
247
-	/**
248
-	 * Override this method if you need a different unique resource identifier for your object storage implementation.
249
-	 * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users.
250
-	 * You may need a mapping table to store your URN if it cannot be generated from the fileid.
251
-	 *
252
-	 * @param int $fileId the fileid
253
-	 * @return null|string the unified resource name used to identify the object
254
-	 */
255
-	public function getURN($fileId) {
256
-		if (is_numeric($fileId)) {
257
-			return $this->objectPrefix . $fileId;
258
-		}
259
-		return null;
260
-	}
261
-
262
-	public function opendir($path) {
263
-		$path = $this->normalizePath($path);
264
-
265
-		try {
266
-			$files = [];
267
-			$folderContents = $this->getCache()->getFolderContents($path);
268
-			foreach ($folderContents as $file) {
269
-				$files[] = $file['name'];
270
-			}
271
-
272
-			return IteratorDirectory::wrap($files);
273
-		} catch (\Exception $e) {
274
-			$this->logger->logException($e);
275
-			return false;
276
-		}
277
-	}
278
-
279
-	public function filetype($path) {
280
-		$path = $this->normalizePath($path);
281
-		$stat = $this->stat($path);
282
-		if ($stat) {
283
-			if ($stat['mimetype'] === 'httpd/unix-directory') {
284
-				return 'dir';
285
-			}
286
-			return 'file';
287
-		} else {
288
-			return false;
289
-		}
290
-	}
291
-
292
-	public function fopen($path, $mode) {
293
-		$path = $this->normalizePath($path);
294
-
295
-		if (strrpos($path, '.') !== false) {
296
-			$ext = substr($path, strrpos($path, '.'));
297
-		} else {
298
-			$ext = '';
299
-		}
300
-
301
-		switch ($mode) {
302
-			case 'r':
303
-			case 'rb':
304
-				$stat = $this->stat($path);
305
-				if (is_array($stat)) {
306
-					// Reading 0 sized files is a waste of time
307
-					if (isset($stat['size']) && $stat['size'] === 0) {
308
-						return fopen('php://memory', $mode);
309
-					}
310
-
311
-					try {
312
-						return $this->objectStore->readObject($this->getURN($stat['fileid']));
313
-					} catch (NotFoundException $e) {
314
-						$this->logger->logException($e, [
315
-							'app' => 'objectstore',
316
-							'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
317
-						]);
318
-						throw $e;
319
-					} catch (\Exception $ex) {
320
-						$this->logger->logException($ex, [
321
-							'app' => 'objectstore',
322
-							'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
323
-						]);
324
-						return false;
325
-					}
326
-				} else {
327
-					return false;
328
-				}
329
-			// no break
330
-			case 'w':
331
-			case 'wb':
332
-			case 'w+':
333
-			case 'wb+':
334
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
335
-				$handle = fopen($tmpFile, $mode);
336
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
337
-					$this->writeBack($tmpFile, $path);
338
-				});
339
-			case 'a':
340
-			case 'ab':
341
-			case 'r+':
342
-			case 'a+':
343
-			case 'x':
344
-			case 'x+':
345
-			case 'c':
346
-			case 'c+':
347
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
348
-				if ($this->file_exists($path)) {
349
-					$source = $this->fopen($path, 'r');
350
-					file_put_contents($tmpFile, $source);
351
-				}
352
-				$handle = fopen($tmpFile, $mode);
353
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
354
-					$this->writeBack($tmpFile, $path);
355
-				});
356
-		}
357
-		return false;
358
-	}
359
-
360
-	public function file_exists($path) {
361
-		$path = $this->normalizePath($path);
362
-		return (bool)$this->stat($path);
363
-	}
364
-
365
-	public function rename($source, $target) {
366
-		$source = $this->normalizePath($source);
367
-		$target = $this->normalizePath($target);
368
-		$this->remove($target);
369
-		$this->getCache()->move($source, $target);
370
-		$this->touch(dirname($target));
371
-		return true;
372
-	}
373
-
374
-	public function getMimeType($path) {
375
-		$path = $this->normalizePath($path);
376
-		return parent::getMimeType($path);
377
-	}
378
-
379
-	public function touch($path, $mtime = null) {
380
-		if (is_null($mtime)) {
381
-			$mtime = time();
382
-		}
383
-
384
-		$path = $this->normalizePath($path);
385
-		$dirName = dirname($path);
386
-		$parentExists = $this->is_dir($dirName);
387
-		if (!$parentExists) {
388
-			return false;
389
-		}
390
-
391
-		$stat = $this->stat($path);
392
-		if (is_array($stat)) {
393
-			// update existing mtime in db
394
-			$stat['mtime'] = $mtime;
395
-			$this->getCache()->update($stat['fileid'], $stat);
396
-		} else {
397
-			try {
398
-				//create a empty file, need to have at least on char to make it
399
-				// work with all object storage implementations
400
-				$this->file_put_contents($path, ' ');
401
-				$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
402
-				$stat = [
403
-					'etag' => $this->getETag($path),
404
-					'mimetype' => $mimeType,
405
-					'size' => 0,
406
-					'mtime' => $mtime,
407
-					'storage_mtime' => $mtime,
408
-					'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
409
-				];
410
-				$this->getCache()->put($path, $stat);
411
-			} catch (\Exception $ex) {
412
-				$this->logger->logException($ex, [
413
-					'app' => 'objectstore',
414
-					'message' => 'Could not create object for ' . $path,
415
-				]);
416
-				throw $ex;
417
-			}
418
-		}
419
-		return true;
420
-	}
421
-
422
-	public function writeBack($tmpFile, $path) {
423
-		$size = filesize($tmpFile);
424
-		$this->writeStream($path, fopen($tmpFile, 'r'), $size);
425
-	}
426
-
427
-	/**
428
-	 * external changes are not supported, exclusive access to the object storage is assumed
429
-	 *
430
-	 * @param string $path
431
-	 * @param int $time
432
-	 * @return false
433
-	 */
434
-	public function hasUpdated($path, $time) {
435
-		return false;
436
-	}
437
-
438
-	public function needsPartFile() {
439
-		return false;
440
-	}
441
-
442
-	public function file_put_contents($path, $data) {
443
-		$handle = $this->fopen($path, 'w+');
444
-		$result = fwrite($handle, $data);
445
-		fclose($handle);
446
-		return $result;
447
-	}
448
-
449
-	public function writeStream(string $path, $stream, int $size = null): int {
450
-		$stat = $this->stat($path);
451
-		if (empty($stat)) {
452
-			// create new file
453
-			$stat = [
454
-				'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
455
-			];
456
-		}
457
-		// update stat with new data
458
-		$mTime = time();
459
-		$stat['size'] = (int)$size;
460
-		$stat['mtime'] = $mTime;
461
-		$stat['storage_mtime'] = $mTime;
462
-
463
-		$mimetypeDetector = \OC::$server->getMimeTypeDetector();
464
-		$mimetype = $mimetypeDetector->detectPath($path);
465
-
466
-		$stat['mimetype'] = $mimetype;
467
-		$stat['etag'] = $this->getETag($path);
468
-		$stat['checksum'] = '';
469
-
470
-		$exists = $this->getCache()->inCache($path);
471
-		$uploadPath = $exists ? $path : $path . '.part';
472
-
473
-		if ($exists) {
474
-			$fileId = $stat['fileid'];
475
-		} else {
476
-			$fileId = $this->getCache()->put($uploadPath, $stat);
477
-		}
478
-
479
-		$urn = $this->getURN($fileId);
480
-		try {
481
-			//upload to object storage
482
-			if ($size === null) {
483
-				$countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) {
484
-					$this->getCache()->update($fileId, [
485
-						'size' => $writtenSize,
486
-					]);
487
-					$size = $writtenSize;
488
-				});
489
-				$this->objectStore->writeObject($urn, $countStream, $mimetype);
490
-				if (is_resource($countStream)) {
491
-					fclose($countStream);
492
-				}
493
-				$stat['size'] = $size;
494
-			} else {
495
-				$this->objectStore->writeObject($urn, $stream, $mimetype);
496
-				if (is_resource($stream)) {
497
-					fclose($stream);
498
-				}
499
-			}
500
-		} catch (\Exception $ex) {
501
-			if (!$exists) {
502
-				/*
45
+    use CopyDirectory;
46
+
47
+    /**
48
+     * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
49
+     */
50
+    protected $objectStore;
51
+    /**
52
+     * @var string $id
53
+     */
54
+    protected $id;
55
+    /**
56
+     * @var \OC\User\User $user
57
+     */
58
+    protected $user;
59
+
60
+    private $objectPrefix = 'urn:oid:';
61
+
62
+    private $logger;
63
+
64
+    public function __construct($params) {
65
+        if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
66
+            $this->objectStore = $params['objectstore'];
67
+        } else {
68
+            throw new \Exception('missing IObjectStore instance');
69
+        }
70
+        if (isset($params['storageid'])) {
71
+            $this->id = 'object::store:' . $params['storageid'];
72
+        } else {
73
+            $this->id = 'object::store:' . $this->objectStore->getStorageId();
74
+        }
75
+        if (isset($params['objectPrefix'])) {
76
+            $this->objectPrefix = $params['objectPrefix'];
77
+        }
78
+        //initialize cache with root directory in cache
79
+        if (!$this->is_dir('/')) {
80
+            $this->mkdir('/');
81
+        }
82
+
83
+        $this->logger = \OC::$server->getLogger();
84
+    }
85
+
86
+    public function mkdir($path) {
87
+        $path = $this->normalizePath($path);
88
+
89
+        if ($this->file_exists($path)) {
90
+            return false;
91
+        }
92
+
93
+        $mTime = time();
94
+        $data = [
95
+            'mimetype' => 'httpd/unix-directory',
96
+            'size' => 0,
97
+            'mtime' => $mTime,
98
+            'storage_mtime' => $mTime,
99
+            'permissions' => \OCP\Constants::PERMISSION_ALL,
100
+        ];
101
+        if ($path === '') {
102
+            //create root on the fly
103
+            $data['etag'] = $this->getETag('');
104
+            $this->getCache()->put('', $data);
105
+            return true;
106
+        } else {
107
+            // if parent does not exist, create it
108
+            $parent = $this->normalizePath(dirname($path));
109
+            $parentType = $this->filetype($parent);
110
+            if ($parentType === false) {
111
+                if (!$this->mkdir($parent)) {
112
+                    // something went wrong
113
+                    return false;
114
+                }
115
+            } elseif ($parentType === 'file') {
116
+                // parent is a file
117
+                return false;
118
+            }
119
+            // finally create the new dir
120
+            $mTime = time(); // update mtime
121
+            $data['mtime'] = $mTime;
122
+            $data['storage_mtime'] = $mTime;
123
+            $data['etag'] = $this->getETag($path);
124
+            $this->getCache()->put($path, $data);
125
+            return true;
126
+        }
127
+    }
128
+
129
+    /**
130
+     * @param string $path
131
+     * @return string
132
+     */
133
+    private function normalizePath($path) {
134
+        $path = trim($path, '/');
135
+        //FIXME why do we sometimes get a path like 'files//username'?
136
+        $path = str_replace('//', '/', $path);
137
+
138
+        // dirname('/folder') returns '.' but internally (in the cache) we store the root as ''
139
+        if (!$path || $path === '.') {
140
+            $path = '';
141
+        }
142
+
143
+        return $path;
144
+    }
145
+
146
+    /**
147
+     * Object Stores use a NoopScanner because metadata is directly stored in
148
+     * the file cache and cannot really scan the filesystem. The storage passed in is not used anywhere.
149
+     *
150
+     * @param string $path
151
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
152
+     * @return \OC\Files\ObjectStore\NoopScanner
153
+     */
154
+    public function getScanner($path = '', $storage = null) {
155
+        if (!$storage) {
156
+            $storage = $this;
157
+        }
158
+        if (!isset($this->scanner)) {
159
+            $this->scanner = new NoopScanner($storage);
160
+        }
161
+        return $this->scanner;
162
+    }
163
+
164
+    public function getId() {
165
+        return $this->id;
166
+    }
167
+
168
+    public function rmdir($path) {
169
+        $path = $this->normalizePath($path);
170
+
171
+        if (!$this->is_dir($path)) {
172
+            return false;
173
+        }
174
+
175
+        if (!$this->rmObjects($path)) {
176
+            return false;
177
+        }
178
+
179
+        $this->getCache()->remove($path);
180
+
181
+        return true;
182
+    }
183
+
184
+    private function rmObjects($path) {
185
+        $children = $this->getCache()->getFolderContents($path);
186
+        foreach ($children as $child) {
187
+            if ($child['mimetype'] === 'httpd/unix-directory') {
188
+                if (!$this->rmObjects($child['path'])) {
189
+                    return false;
190
+                }
191
+            } else {
192
+                if (!$this->unlink($child['path'])) {
193
+                    return false;
194
+                }
195
+            }
196
+        }
197
+
198
+        return true;
199
+    }
200
+
201
+    public function unlink($path) {
202
+        $path = $this->normalizePath($path);
203
+        $stat = $this->stat($path);
204
+
205
+        if ($stat && isset($stat['fileid'])) {
206
+            if ($stat['mimetype'] === 'httpd/unix-directory') {
207
+                return $this->rmdir($path);
208
+            }
209
+            try {
210
+                $this->objectStore->deleteObject($this->getURN($stat['fileid']));
211
+            } catch (\Exception $ex) {
212
+                if ($ex->getCode() !== 404) {
213
+                    $this->logger->logException($ex, [
214
+                        'app' => 'objectstore',
215
+                        'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
216
+                    ]);
217
+                    return false;
218
+                }
219
+                //removing from cache is ok as it does not exist in the objectstore anyway
220
+            }
221
+            $this->getCache()->remove($path);
222
+            return true;
223
+        }
224
+        return false;
225
+    }
226
+
227
+    public function stat($path) {
228
+        $path = $this->normalizePath($path);
229
+        $cacheEntry = $this->getCache()->get($path);
230
+        if ($cacheEntry instanceof CacheEntry) {
231
+            return $cacheEntry->getData();
232
+        } else {
233
+            return false;
234
+        }
235
+    }
236
+
237
+    public function getPermissions($path) {
238
+        $stat = $this->stat($path);
239
+
240
+        if (is_array($stat) && isset($stat['permissions'])) {
241
+            return $stat['permissions'];
242
+        }
243
+
244
+        return parent::getPermissions($path);
245
+    }
246
+
247
+    /**
248
+     * Override this method if you need a different unique resource identifier for your object storage implementation.
249
+     * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users.
250
+     * You may need a mapping table to store your URN if it cannot be generated from the fileid.
251
+     *
252
+     * @param int $fileId the fileid
253
+     * @return null|string the unified resource name used to identify the object
254
+     */
255
+    public function getURN($fileId) {
256
+        if (is_numeric($fileId)) {
257
+            return $this->objectPrefix . $fileId;
258
+        }
259
+        return null;
260
+    }
261
+
262
+    public function opendir($path) {
263
+        $path = $this->normalizePath($path);
264
+
265
+        try {
266
+            $files = [];
267
+            $folderContents = $this->getCache()->getFolderContents($path);
268
+            foreach ($folderContents as $file) {
269
+                $files[] = $file['name'];
270
+            }
271
+
272
+            return IteratorDirectory::wrap($files);
273
+        } catch (\Exception $e) {
274
+            $this->logger->logException($e);
275
+            return false;
276
+        }
277
+    }
278
+
279
+    public function filetype($path) {
280
+        $path = $this->normalizePath($path);
281
+        $stat = $this->stat($path);
282
+        if ($stat) {
283
+            if ($stat['mimetype'] === 'httpd/unix-directory') {
284
+                return 'dir';
285
+            }
286
+            return 'file';
287
+        } else {
288
+            return false;
289
+        }
290
+    }
291
+
292
+    public function fopen($path, $mode) {
293
+        $path = $this->normalizePath($path);
294
+
295
+        if (strrpos($path, '.') !== false) {
296
+            $ext = substr($path, strrpos($path, '.'));
297
+        } else {
298
+            $ext = '';
299
+        }
300
+
301
+        switch ($mode) {
302
+            case 'r':
303
+            case 'rb':
304
+                $stat = $this->stat($path);
305
+                if (is_array($stat)) {
306
+                    // Reading 0 sized files is a waste of time
307
+                    if (isset($stat['size']) && $stat['size'] === 0) {
308
+                        return fopen('php://memory', $mode);
309
+                    }
310
+
311
+                    try {
312
+                        return $this->objectStore->readObject($this->getURN($stat['fileid']));
313
+                    } catch (NotFoundException $e) {
314
+                        $this->logger->logException($e, [
315
+                            'app' => 'objectstore',
316
+                            'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
317
+                        ]);
318
+                        throw $e;
319
+                    } catch (\Exception $ex) {
320
+                        $this->logger->logException($ex, [
321
+                            'app' => 'objectstore',
322
+                            'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
323
+                        ]);
324
+                        return false;
325
+                    }
326
+                } else {
327
+                    return false;
328
+                }
329
+            // no break
330
+            case 'w':
331
+            case 'wb':
332
+            case 'w+':
333
+            case 'wb+':
334
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
335
+                $handle = fopen($tmpFile, $mode);
336
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
337
+                    $this->writeBack($tmpFile, $path);
338
+                });
339
+            case 'a':
340
+            case 'ab':
341
+            case 'r+':
342
+            case 'a+':
343
+            case 'x':
344
+            case 'x+':
345
+            case 'c':
346
+            case 'c+':
347
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
348
+                if ($this->file_exists($path)) {
349
+                    $source = $this->fopen($path, 'r');
350
+                    file_put_contents($tmpFile, $source);
351
+                }
352
+                $handle = fopen($tmpFile, $mode);
353
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
354
+                    $this->writeBack($tmpFile, $path);
355
+                });
356
+        }
357
+        return false;
358
+    }
359
+
360
+    public function file_exists($path) {
361
+        $path = $this->normalizePath($path);
362
+        return (bool)$this->stat($path);
363
+    }
364
+
365
+    public function rename($source, $target) {
366
+        $source = $this->normalizePath($source);
367
+        $target = $this->normalizePath($target);
368
+        $this->remove($target);
369
+        $this->getCache()->move($source, $target);
370
+        $this->touch(dirname($target));
371
+        return true;
372
+    }
373
+
374
+    public function getMimeType($path) {
375
+        $path = $this->normalizePath($path);
376
+        return parent::getMimeType($path);
377
+    }
378
+
379
+    public function touch($path, $mtime = null) {
380
+        if (is_null($mtime)) {
381
+            $mtime = time();
382
+        }
383
+
384
+        $path = $this->normalizePath($path);
385
+        $dirName = dirname($path);
386
+        $parentExists = $this->is_dir($dirName);
387
+        if (!$parentExists) {
388
+            return false;
389
+        }
390
+
391
+        $stat = $this->stat($path);
392
+        if (is_array($stat)) {
393
+            // update existing mtime in db
394
+            $stat['mtime'] = $mtime;
395
+            $this->getCache()->update($stat['fileid'], $stat);
396
+        } else {
397
+            try {
398
+                //create a empty file, need to have at least on char to make it
399
+                // work with all object storage implementations
400
+                $this->file_put_contents($path, ' ');
401
+                $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
402
+                $stat = [
403
+                    'etag' => $this->getETag($path),
404
+                    'mimetype' => $mimeType,
405
+                    'size' => 0,
406
+                    'mtime' => $mtime,
407
+                    'storage_mtime' => $mtime,
408
+                    'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
409
+                ];
410
+                $this->getCache()->put($path, $stat);
411
+            } catch (\Exception $ex) {
412
+                $this->logger->logException($ex, [
413
+                    'app' => 'objectstore',
414
+                    'message' => 'Could not create object for ' . $path,
415
+                ]);
416
+                throw $ex;
417
+            }
418
+        }
419
+        return true;
420
+    }
421
+
422
+    public function writeBack($tmpFile, $path) {
423
+        $size = filesize($tmpFile);
424
+        $this->writeStream($path, fopen($tmpFile, 'r'), $size);
425
+    }
426
+
427
+    /**
428
+     * external changes are not supported, exclusive access to the object storage is assumed
429
+     *
430
+     * @param string $path
431
+     * @param int $time
432
+     * @return false
433
+     */
434
+    public function hasUpdated($path, $time) {
435
+        return false;
436
+    }
437
+
438
+    public function needsPartFile() {
439
+        return false;
440
+    }
441
+
442
+    public function file_put_contents($path, $data) {
443
+        $handle = $this->fopen($path, 'w+');
444
+        $result = fwrite($handle, $data);
445
+        fclose($handle);
446
+        return $result;
447
+    }
448
+
449
+    public function writeStream(string $path, $stream, int $size = null): int {
450
+        $stat = $this->stat($path);
451
+        if (empty($stat)) {
452
+            // create new file
453
+            $stat = [
454
+                'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
455
+            ];
456
+        }
457
+        // update stat with new data
458
+        $mTime = time();
459
+        $stat['size'] = (int)$size;
460
+        $stat['mtime'] = $mTime;
461
+        $stat['storage_mtime'] = $mTime;
462
+
463
+        $mimetypeDetector = \OC::$server->getMimeTypeDetector();
464
+        $mimetype = $mimetypeDetector->detectPath($path);
465
+
466
+        $stat['mimetype'] = $mimetype;
467
+        $stat['etag'] = $this->getETag($path);
468
+        $stat['checksum'] = '';
469
+
470
+        $exists = $this->getCache()->inCache($path);
471
+        $uploadPath = $exists ? $path : $path . '.part';
472
+
473
+        if ($exists) {
474
+            $fileId = $stat['fileid'];
475
+        } else {
476
+            $fileId = $this->getCache()->put($uploadPath, $stat);
477
+        }
478
+
479
+        $urn = $this->getURN($fileId);
480
+        try {
481
+            //upload to object storage
482
+            if ($size === null) {
483
+                $countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) {
484
+                    $this->getCache()->update($fileId, [
485
+                        'size' => $writtenSize,
486
+                    ]);
487
+                    $size = $writtenSize;
488
+                });
489
+                $this->objectStore->writeObject($urn, $countStream, $mimetype);
490
+                if (is_resource($countStream)) {
491
+                    fclose($countStream);
492
+                }
493
+                $stat['size'] = $size;
494
+            } else {
495
+                $this->objectStore->writeObject($urn, $stream, $mimetype);
496
+                if (is_resource($stream)) {
497
+                    fclose($stream);
498
+                }
499
+            }
500
+        } catch (\Exception $ex) {
501
+            if (!$exists) {
502
+                /*
503 503
 				 * Only remove the entry if we are dealing with a new file.
504 504
 				 * Else people lose access to existing files
505 505
 				 */
506
-				$this->getCache()->remove($uploadPath);
507
-				$this->logger->logException($ex, [
508
-					'app' => 'objectstore',
509
-					'message' => 'Could not create object ' . $urn . ' for ' . $path,
510
-				]);
511
-			} else {
512
-				$this->logger->logException($ex, [
513
-					'app' => 'objectstore',
514
-					'message' => 'Could not update object ' . $urn . ' for ' . $path,
515
-				]);
516
-			}
517
-			throw $ex; // make this bubble up
518
-		}
519
-
520
-		if ($exists) {
521
-			$this->getCache()->update($fileId, $stat);
522
-		} else {
523
-			if ($this->objectStore->objectExists($urn)) {
524
-				$this->getCache()->move($uploadPath, $path);
525
-			} else {
526
-				$this->getCache()->remove($uploadPath);
527
-				throw new \Exception("Object not found after writing (urn: $urn, path: $path)", 404);
528
-			}
529
-		}
530
-
531
-		return $size;
532
-	}
533
-
534
-	public function getObjectStore(): IObjectStore {
535
-		return $this->objectStore;
536
-	}
537
-
538
-	public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) {
539
-		if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class)) {
540
-			/** @var ObjectStoreStorage $sourceStorage */
541
-			if ($sourceStorage->getObjectStore()->getStorageId() === $this->getObjectStore()->getStorageId()) {
542
-				$sourceEntry = $sourceStorage->getCache()->get($sourceInternalPath);
543
-				$this->copyInner($sourceEntry, $targetInternalPath);
544
-				return true;
545
-			}
546
-		}
547
-
548
-		return parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
549
-	}
550
-
551
-	public function copy($path1, $path2) {
552
-		$path1 = $this->normalizePath($path1);
553
-		$path2 = $this->normalizePath($path2);
554
-
555
-		$cache = $this->getCache();
556
-		$sourceEntry = $cache->get($path1);
557
-		if (!$sourceEntry) {
558
-			throw new NotFoundException('Source object not found');
559
-		}
560
-
561
-		$this->copyInner($sourceEntry, $path2);
562
-
563
-		return true;
564
-	}
565
-
566
-	private function copyInner(ICacheEntry $sourceEntry, string $to) {
567
-		$cache = $this->getCache();
568
-
569
-		if ($sourceEntry->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
570
-			if ($cache->inCache($to)) {
571
-				$cache->remove($to);
572
-			}
573
-			$this->mkdir($to);
574
-
575
-			foreach ($cache->getFolderContentsById($sourceEntry->getId()) as $child) {
576
-				$this->copyInner($child, $to . '/' . $child->getName());
577
-			}
578
-		} else {
579
-			$this->copyFile($sourceEntry, $to);
580
-		}
581
-	}
582
-
583
-	private function copyFile(ICacheEntry $sourceEntry, string $to) {
584
-		$cache = $this->getCache();
585
-
586
-		$sourceUrn = $this->getURN($sourceEntry->getId());
587
-
588
-		if (!$cache instanceof Cache) {
589
-			throw new \Exception("Invalid source cache for object store copy");
590
-		}
591
-
592
-		$targetId = $cache->copyFromCache($cache, $sourceEntry, $to);
593
-
594
-		$targetUrn = $this->getURN($targetId);
595
-
596
-		try {
597
-			$this->objectStore->copyObject($sourceUrn, $targetUrn);
598
-		} catch (\Exception $e) {
599
-			$cache->remove($to);
600
-
601
-			throw $e;
602
-		}
603
-	}
506
+                $this->getCache()->remove($uploadPath);
507
+                $this->logger->logException($ex, [
508
+                    'app' => 'objectstore',
509
+                    'message' => 'Could not create object ' . $urn . ' for ' . $path,
510
+                ]);
511
+            } else {
512
+                $this->logger->logException($ex, [
513
+                    'app' => 'objectstore',
514
+                    'message' => 'Could not update object ' . $urn . ' for ' . $path,
515
+                ]);
516
+            }
517
+            throw $ex; // make this bubble up
518
+        }
519
+
520
+        if ($exists) {
521
+            $this->getCache()->update($fileId, $stat);
522
+        } else {
523
+            if ($this->objectStore->objectExists($urn)) {
524
+                $this->getCache()->move($uploadPath, $path);
525
+            } else {
526
+                $this->getCache()->remove($uploadPath);
527
+                throw new \Exception("Object not found after writing (urn: $urn, path: $path)", 404);
528
+            }
529
+        }
530
+
531
+        return $size;
532
+    }
533
+
534
+    public function getObjectStore(): IObjectStore {
535
+        return $this->objectStore;
536
+    }
537
+
538
+    public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime = false) {
539
+        if ($sourceStorage->instanceOfStorage(ObjectStoreStorage::class)) {
540
+            /** @var ObjectStoreStorage $sourceStorage */
541
+            if ($sourceStorage->getObjectStore()->getStorageId() === $this->getObjectStore()->getStorageId()) {
542
+                $sourceEntry = $sourceStorage->getCache()->get($sourceInternalPath);
543
+                $this->copyInner($sourceEntry, $targetInternalPath);
544
+                return true;
545
+            }
546
+        }
547
+
548
+        return parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
549
+    }
550
+
551
+    public function copy($path1, $path2) {
552
+        $path1 = $this->normalizePath($path1);
553
+        $path2 = $this->normalizePath($path2);
554
+
555
+        $cache = $this->getCache();
556
+        $sourceEntry = $cache->get($path1);
557
+        if (!$sourceEntry) {
558
+            throw new NotFoundException('Source object not found');
559
+        }
560
+
561
+        $this->copyInner($sourceEntry, $path2);
562
+
563
+        return true;
564
+    }
565
+
566
+    private function copyInner(ICacheEntry $sourceEntry, string $to) {
567
+        $cache = $this->getCache();
568
+
569
+        if ($sourceEntry->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
570
+            if ($cache->inCache($to)) {
571
+                $cache->remove($to);
572
+            }
573
+            $this->mkdir($to);
574
+
575
+            foreach ($cache->getFolderContentsById($sourceEntry->getId()) as $child) {
576
+                $this->copyInner($child, $to . '/' . $child->getName());
577
+            }
578
+        } else {
579
+            $this->copyFile($sourceEntry, $to);
580
+        }
581
+    }
582
+
583
+    private function copyFile(ICacheEntry $sourceEntry, string $to) {
584
+        $cache = $this->getCache();
585
+
586
+        $sourceUrn = $this->getURN($sourceEntry->getId());
587
+
588
+        if (!$cache instanceof Cache) {
589
+            throw new \Exception("Invalid source cache for object store copy");
590
+        }
591
+
592
+        $targetId = $cache->copyFromCache($cache, $sourceEntry, $to);
593
+
594
+        $targetUrn = $this->getURN($targetId);
595
+
596
+        try {
597
+            $this->objectStore->copyObject($sourceUrn, $targetUrn);
598
+        } catch (\Exception $e) {
599
+            $cache->remove($to);
600
+
601
+            throw $e;
602
+        }
603
+    }
604 604
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -68,9 +68,9 @@  discard block
 block discarded – undo
68 68
 			throw new \Exception('missing IObjectStore instance');
69 69
 		}
70 70
 		if (isset($params['storageid'])) {
71
-			$this->id = 'object::store:' . $params['storageid'];
71
+			$this->id = 'object::store:'.$params['storageid'];
72 72
 		} else {
73
-			$this->id = 'object::store:' . $this->objectStore->getStorageId();
73
+			$this->id = 'object::store:'.$this->objectStore->getStorageId();
74 74
 		}
75 75
 		if (isset($params['objectPrefix'])) {
76 76
 			$this->objectPrefix = $params['objectPrefix'];
@@ -212,7 +212,7 @@  discard block
 block discarded – undo
212 212
 				if ($ex->getCode() !== 404) {
213 213
 					$this->logger->logException($ex, [
214 214
 						'app' => 'objectstore',
215
-						'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
215
+						'message' => 'Could not delete object '.$this->getURN($stat['fileid']).' for '.$path,
216 216
 					]);
217 217
 					return false;
218 218
 				}
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
 	 */
255 255
 	public function getURN($fileId) {
256 256
 		if (is_numeric($fileId)) {
257
-			return $this->objectPrefix . $fileId;
257
+			return $this->objectPrefix.$fileId;
258 258
 		}
259 259
 		return null;
260 260
 	}
@@ -313,13 +313,13 @@  discard block
 block discarded – undo
313 313
 					} catch (NotFoundException $e) {
314 314
 						$this->logger->logException($e, [
315 315
 							'app' => 'objectstore',
316
-							'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
316
+							'message' => 'Could not get object '.$this->getURN($stat['fileid']).' for file '.$path,
317 317
 						]);
318 318
 						throw $e;
319 319
 					} catch (\Exception $ex) {
320 320
 						$this->logger->logException($ex, [
321 321
 							'app' => 'objectstore',
322
-							'message' => 'Could not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
322
+							'message' => 'Could not get object '.$this->getURN($stat['fileid']).' for file '.$path,
323 323
 						]);
324 324
 						return false;
325 325
 					}
@@ -333,7 +333,7 @@  discard block
 block discarded – undo
333 333
 			case 'wb+':
334 334
 				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
335 335
 				$handle = fopen($tmpFile, $mode);
336
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
336
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
337 337
 					$this->writeBack($tmpFile, $path);
338 338
 				});
339 339
 			case 'a':
@@ -350,7 +350,7 @@  discard block
 block discarded – undo
350 350
 					file_put_contents($tmpFile, $source);
351 351
 				}
352 352
 				$handle = fopen($tmpFile, $mode);
353
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
353
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
354 354
 					$this->writeBack($tmpFile, $path);
355 355
 				});
356 356
 		}
@@ -359,7 +359,7 @@  discard block
 block discarded – undo
359 359
 
360 360
 	public function file_exists($path) {
361 361
 		$path = $this->normalizePath($path);
362
-		return (bool)$this->stat($path);
362
+		return (bool) $this->stat($path);
363 363
 	}
364 364
 
365 365
 	public function rename($source, $target) {
@@ -411,7 +411,7 @@  discard block
 block discarded – undo
411 411
 			} catch (\Exception $ex) {
412 412
 				$this->logger->logException($ex, [
413 413
 					'app' => 'objectstore',
414
-					'message' => 'Could not create object for ' . $path,
414
+					'message' => 'Could not create object for '.$path,
415 415
 				]);
416 416
 				throw $ex;
417 417
 			}
@@ -456,7 +456,7 @@  discard block
 block discarded – undo
456 456
 		}
457 457
 		// update stat with new data
458 458
 		$mTime = time();
459
-		$stat['size'] = (int)$size;
459
+		$stat['size'] = (int) $size;
460 460
 		$stat['mtime'] = $mTime;
461 461
 		$stat['storage_mtime'] = $mTime;
462 462
 
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
 		$stat['checksum'] = '';
469 469
 
470 470
 		$exists = $this->getCache()->inCache($path);
471
-		$uploadPath = $exists ? $path : $path . '.part';
471
+		$uploadPath = $exists ? $path : $path.'.part';
472 472
 
473 473
 		if ($exists) {
474 474
 			$fileId = $stat['fileid'];
@@ -480,7 +480,7 @@  discard block
 block discarded – undo
480 480
 		try {
481 481
 			//upload to object storage
482 482
 			if ($size === null) {
483
-				$countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) {
483
+				$countStream = CountWrapper::wrap($stream, function($writtenSize) use ($fileId, &$size) {
484 484
 					$this->getCache()->update($fileId, [
485 485
 						'size' => $writtenSize,
486 486
 					]);
@@ -506,12 +506,12 @@  discard block
 block discarded – undo
506 506
 				$this->getCache()->remove($uploadPath);
507 507
 				$this->logger->logException($ex, [
508 508
 					'app' => 'objectstore',
509
-					'message' => 'Could not create object ' . $urn . ' for ' . $path,
509
+					'message' => 'Could not create object '.$urn.' for '.$path,
510 510
 				]);
511 511
 			} else {
512 512
 				$this->logger->logException($ex, [
513 513
 					'app' => 'objectstore',
514
-					'message' => 'Could not update object ' . $urn . ' for ' . $path,
514
+					'message' => 'Could not update object '.$urn.' for '.$path,
515 515
 				]);
516 516
 			}
517 517
 			throw $ex; // make this bubble up
@@ -573,7 +573,7 @@  discard block
 block discarded – undo
573 573
 			$this->mkdir($to);
574 574
 
575 575
 			foreach ($cache->getFolderContentsById($sourceEntry->getId()) as $child) {
576
-				$this->copyInner($child, $to . '/' . $child->getName());
576
+				$this->copyInner($child, $to.'/'.$child->getName());
577 577
 			}
578 578
 		} else {
579 579
 			$this->copyFile($sourceEntry, $to);
Please login to merge, or discard this patch.