Completed
Pull Request — master (#8711)
by Robin
28:47 queued 11:07
created
lib/private/Files/ObjectStore/ObjectStoreStorage.php 2 patches
Indentation   +398 added lines, -398 removed lines patch added patch discarded remove patch
@@ -31,402 +31,402 @@
 block discarded – undo
31 31
 use OCP\Files\ObjectStore\IObjectStore;
32 32
 
33 33
 class ObjectStoreStorage extends \OC\Files\Storage\Common {
34
-	/**
35
-	 * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
36
-	 */
37
-	protected $objectStore;
38
-	/**
39
-	 * @var string $id
40
-	 */
41
-	protected $id;
42
-	/**
43
-	 * @var \OC\User\User $user
44
-	 */
45
-	protected $user;
46
-
47
-	private $objectPrefix = 'urn:oid:';
48
-
49
-	private $logger;
50
-
51
-	public function __construct($params) {
52
-		if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
53
-			$this->objectStore = $params['objectstore'];
54
-		} else {
55
-			throw new \Exception('missing IObjectStore instance');
56
-		}
57
-		if (isset($params['storageid'])) {
58
-			$this->id = 'object::store:' . $params['storageid'];
59
-		} else {
60
-			$this->id = 'object::store:' . $this->objectStore->getStorageId();
61
-		}
62
-		if (isset($params['objectPrefix'])) {
63
-			$this->objectPrefix = $params['objectPrefix'];
64
-		}
65
-		//initialize cache with root directory in cache
66
-		if (!$this->is_dir('/')) {
67
-			$this->mkdir('/');
68
-		}
69
-
70
-		$this->logger = \OC::$server->getLogger();
71
-	}
72
-
73
-	public function mkdir($path) {
74
-		$path = $this->normalizePath($path);
75
-
76
-		if ($this->file_exists($path)) {
77
-			return false;
78
-		}
79
-
80
-		$mTime = time();
81
-		$data = [
82
-			'mimetype' => 'httpd/unix-directory',
83
-			'size' => 0,
84
-			'mtime' => $mTime,
85
-			'storage_mtime' => $mTime,
86
-			'permissions' => \OCP\Constants::PERMISSION_ALL,
87
-		];
88
-		if ($path === '') {
89
-			//create root on the fly
90
-			$data['etag'] = $this->getETag('');
91
-			$this->getCache()->put('', $data);
92
-			return true;
93
-		} else {
94
-			// if parent does not exist, create it
95
-			$parent = $this->normalizePath(dirname($path));
96
-			$parentType = $this->filetype($parent);
97
-			if ($parentType === false) {
98
-				if (!$this->mkdir($parent)) {
99
-					// something went wrong
100
-					return false;
101
-				}
102
-			} else if ($parentType === 'file') {
103
-				// parent is a file
104
-				return false;
105
-			}
106
-			// finally create the new dir
107
-			$mTime = time(); // update mtime
108
-			$data['mtime'] = $mTime;
109
-			$data['storage_mtime'] = $mTime;
110
-			$data['etag'] = $this->getETag($path);
111
-			$this->getCache()->put($path, $data);
112
-			return true;
113
-		}
114
-	}
115
-
116
-	/**
117
-	 * @param string $path
118
-	 * @return string
119
-	 */
120
-	private function normalizePath($path) {
121
-		$path = trim($path, '/');
122
-		//FIXME why do we sometimes get a path like 'files//username'?
123
-		$path = str_replace('//', '/', $path);
124
-
125
-		// dirname('/folder') returns '.' but internally (in the cache) we store the root as ''
126
-		if (!$path || $path === '.') {
127
-			$path = '';
128
-		}
129
-
130
-		return $path;
131
-	}
132
-
133
-	/**
134
-	 * Object Stores use a NoopScanner because metadata is directly stored in
135
-	 * the file cache and cannot really scan the filesystem. The storage passed in is not used anywhere.
136
-	 *
137
-	 * @param string $path
138
-	 * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
139
-	 * @return \OC\Files\ObjectStore\NoopScanner
140
-	 */
141
-	public function getScanner($path = '', $storage = null) {
142
-		if (!$storage) {
143
-			$storage = $this;
144
-		}
145
-		if (!isset($this->scanner)) {
146
-			$this->scanner = new NoopScanner($storage);
147
-		}
148
-		return $this->scanner;
149
-	}
150
-
151
-	public function getId() {
152
-		return $this->id;
153
-	}
154
-
155
-	public function rmdir($path) {
156
-		$path = $this->normalizePath($path);
157
-
158
-		if (!$this->is_dir($path)) {
159
-			return false;
160
-		}
161
-
162
-		$this->rmObjects($path);
163
-
164
-		$this->getCache()->remove($path);
165
-
166
-		return true;
167
-	}
168
-
169
-	private function rmObjects($path) {
170
-		$children = $this->getCache()->getFolderContents($path);
171
-		foreach ($children as $child) {
172
-			if ($child['mimetype'] === 'httpd/unix-directory') {
173
-				$this->rmObjects($child['path']);
174
-			} else {
175
-				$this->unlink($child['path']);
176
-			}
177
-		}
178
-	}
179
-
180
-	public function unlink($path) {
181
-		$path = $this->normalizePath($path);
182
-		$stat = $this->stat($path);
183
-
184
-		if ($stat && isset($stat['fileid'])) {
185
-			if ($stat['mimetype'] === 'httpd/unix-directory') {
186
-				return $this->rmdir($path);
187
-			}
188
-			try {
189
-				$this->objectStore->deleteObject($this->getURN($stat['fileid']));
190
-			} catch (\Exception $ex) {
191
-				if ($ex->getCode() !== 404) {
192
-					$this->logger->logException($ex, [
193
-						'app' => 'objectstore',
194
-						'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
195
-					]);
196
-					return false;
197
-				}
198
-				//removing from cache is ok as it does not exist in the objectstore anyway
199
-			}
200
-			$this->getCache()->remove($path);
201
-			return true;
202
-		}
203
-		return false;
204
-	}
205
-
206
-	public function stat($path) {
207
-		$path = $this->normalizePath($path);
208
-		$cacheEntry = $this->getCache()->get($path);
209
-		if ($cacheEntry instanceof CacheEntry) {
210
-			return $cacheEntry->getData();
211
-		} else {
212
-			return false;
213
-		}
214
-	}
215
-
216
-	/**
217
-	 * Override this method if you need a different unique resource identifier for your object storage implementation.
218
-	 * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users.
219
-	 * You may need a mapping table to store your URN if it cannot be generated from the fileid.
220
-	 *
221
-	 * @param int $fileId the fileid
222
-	 * @return null|string the unified resource name used to identify the object
223
-	 */
224
-	protected function getURN($fileId) {
225
-		if (is_numeric($fileId)) {
226
-			return $this->objectPrefix . $fileId;
227
-		}
228
-		return null;
229
-	}
230
-
231
-	public function opendir($path) {
232
-		$path = $this->normalizePath($path);
233
-
234
-		try {
235
-			$files = array();
236
-			$folderContents = $this->getCache()->getFolderContents($path);
237
-			foreach ($folderContents as $file) {
238
-				$files[] = $file['name'];
239
-			}
240
-
241
-			return IteratorDirectory::wrap($files);
242
-		} catch (\Exception $e) {
243
-			$this->logger->logException($e);
244
-			return false;
245
-		}
246
-	}
247
-
248
-	public function filetype($path) {
249
-		$path = $this->normalizePath($path);
250
-		$stat = $this->stat($path);
251
-		if ($stat) {
252
-			if ($stat['mimetype'] === 'httpd/unix-directory') {
253
-				return 'dir';
254
-			}
255
-			return 'file';
256
-		} else {
257
-			return false;
258
-		}
259
-	}
260
-
261
-	public function fopen($path, $mode) {
262
-		$path = $this->normalizePath($path);
263
-
264
-		if (strrpos($path, '.') !== false) {
265
-			$ext = substr($path, strrpos($path, '.'));
266
-		} else {
267
-			$ext = '';
268
-		}
269
-
270
-		switch ($mode) {
271
-			case 'r':
272
-			case 'rb':
273
-				$stat = $this->stat($path);
274
-				if (is_array($stat)) {
275
-					try {
276
-						return $this->objectStore->readObject($this->getURN($stat['fileid']));
277
-					} catch (\Exception $ex) {
278
-						$this->logger->logException($ex, [
279
-							'app' => 'objectstore',
280
-							'message' => 'Count not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
281
-						]);
282
-						return false;
283
-					}
284
-				} else {
285
-					return false;
286
-				}
287
-			case 'w':
288
-			case 'wb':
289
-			case 'w+':
290
-			case 'wb+':
291
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
292
-				$handle = fopen($tmpFile, $mode);
293
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
294
-					$this->writeBack($tmpFile, $path);
295
-				});
296
-			case 'a':
297
-			case 'ab':
298
-			case 'r+':
299
-			case 'a+':
300
-			case 'x':
301
-			case 'x+':
302
-			case 'c':
303
-			case 'c+':
304
-				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
305
-				if ($this->file_exists($path)) {
306
-					$source = $this->fopen($path, 'r');
307
-					file_put_contents($tmpFile, $source);
308
-				}
309
-				$handle = fopen($tmpFile, $mode);
310
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
311
-					$this->writeBack($tmpFile, $path);
312
-				});
313
-		}
314
-		return false;
315
-	}
316
-
317
-	public function file_exists($path) {
318
-		$path = $this->normalizePath($path);
319
-		return (bool)$this->stat($path);
320
-	}
321
-
322
-	public function rename($source, $target) {
323
-		$source = $this->normalizePath($source);
324
-		$target = $this->normalizePath($target);
325
-		$this->remove($target);
326
-		$this->getCache()->move($source, $target);
327
-		$this->touch(dirname($target));
328
-		return true;
329
-	}
330
-
331
-	public function getMimeType($path) {
332
-		$path = $this->normalizePath($path);
333
-		$stat = $this->stat($path);
334
-		if (is_array($stat)) {
335
-			return $stat['mimetype'];
336
-		} else {
337
-			return false;
338
-		}
339
-	}
340
-
341
-	public function touch($path, $mtime = null) {
342
-		if (is_null($mtime)) {
343
-			$mtime = time();
344
-		}
345
-
346
-		$path = $this->normalizePath($path);
347
-		$dirName = dirname($path);
348
-		$parentExists = $this->is_dir($dirName);
349
-		if (!$parentExists) {
350
-			return false;
351
-		}
352
-
353
-		$stat = $this->stat($path);
354
-		if (is_array($stat)) {
355
-			// update existing mtime in db
356
-			$stat['mtime'] = $mtime;
357
-			$this->getCache()->update($stat['fileid'], $stat);
358
-		} else {
359
-			try {
360
-				//create a empty file, need to have at least on char to make it
361
-				// work with all object storage implementations
362
-				$this->file_put_contents($path, ' ');
363
-				$mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
364
-				$stat = array(
365
-					'etag' => $this->getETag($path),
366
-					'mimetype' => $mimeType,
367
-					'size' => 0,
368
-					'mtime' => $mtime,
369
-					'storage_mtime' => $mtime,
370
-					'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
371
-				);
372
-				$this->getCache()->put($path, $stat);
373
-			} catch (\Exception $ex) {
374
-				$this->logger->logException($ex, [
375
-					'app' => 'objectstore',
376
-					'message' => 'Could not create object for ' . $path,
377
-				]);
378
-				throw $ex;
379
-			}
380
-		}
381
-		return true;
382
-	}
383
-
384
-	public function writeBack($tmpFile, $path) {
385
-		$stat = $this->stat($path);
386
-		if (empty($stat)) {
387
-			// create new file
388
-			$stat = array(
389
-				'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
390
-			);
391
-		}
392
-		// update stat with new data
393
-		$mTime = time();
394
-		$stat['size'] = filesize($tmpFile);
395
-		$stat['mtime'] = $mTime;
396
-		$stat['storage_mtime'] = $mTime;
397
-
398
-		// run path based detection first, to use file extension because $tmpFile is only a random string
399
-		$mimetypeDetector = \OC::$server->getMimeTypeDetector();
400
-		$mimetype = $mimetypeDetector->detectPath($path);
401
-		if ($mimetype === 'application/octet-stream') {
402
-			$mimetype = $mimetypeDetector->detect($tmpFile);
403
-		}
404
-
405
-		$stat['mimetype'] = $mimetype;
406
-		$stat['etag'] = $this->getETag($path);
407
-
408
-		$fileId = $this->getCache()->put($path, $stat);
409
-		try {
410
-			//upload to object storage
411
-			$this->objectStore->writeObject($this->getURN($fileId), fopen($tmpFile, 'r'));
412
-		} catch (\Exception $ex) {
413
-			$this->getCache()->remove($path);
414
-			$this->logger->logException($ex, [
415
-				'app' => 'objectstore',
416
-				'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
417
-			]);
418
-			throw $ex; // make this bubble up
419
-		}
420
-	}
421
-
422
-	/**
423
-	 * external changes are not supported, exclusive access to the object storage is assumed
424
-	 *
425
-	 * @param string $path
426
-	 * @param int $time
427
-	 * @return false
428
-	 */
429
-	public function hasUpdated($path, $time) {
430
-		return false;
431
-	}
34
+    /**
35
+     * @var \OCP\Files\ObjectStore\IObjectStore $objectStore
36
+     */
37
+    protected $objectStore;
38
+    /**
39
+     * @var string $id
40
+     */
41
+    protected $id;
42
+    /**
43
+     * @var \OC\User\User $user
44
+     */
45
+    protected $user;
46
+
47
+    private $objectPrefix = 'urn:oid:';
48
+
49
+    private $logger;
50
+
51
+    public function __construct($params) {
52
+        if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) {
53
+            $this->objectStore = $params['objectstore'];
54
+        } else {
55
+            throw new \Exception('missing IObjectStore instance');
56
+        }
57
+        if (isset($params['storageid'])) {
58
+            $this->id = 'object::store:' . $params['storageid'];
59
+        } else {
60
+            $this->id = 'object::store:' . $this->objectStore->getStorageId();
61
+        }
62
+        if (isset($params['objectPrefix'])) {
63
+            $this->objectPrefix = $params['objectPrefix'];
64
+        }
65
+        //initialize cache with root directory in cache
66
+        if (!$this->is_dir('/')) {
67
+            $this->mkdir('/');
68
+        }
69
+
70
+        $this->logger = \OC::$server->getLogger();
71
+    }
72
+
73
+    public function mkdir($path) {
74
+        $path = $this->normalizePath($path);
75
+
76
+        if ($this->file_exists($path)) {
77
+            return false;
78
+        }
79
+
80
+        $mTime = time();
81
+        $data = [
82
+            'mimetype' => 'httpd/unix-directory',
83
+            'size' => 0,
84
+            'mtime' => $mTime,
85
+            'storage_mtime' => $mTime,
86
+            'permissions' => \OCP\Constants::PERMISSION_ALL,
87
+        ];
88
+        if ($path === '') {
89
+            //create root on the fly
90
+            $data['etag'] = $this->getETag('');
91
+            $this->getCache()->put('', $data);
92
+            return true;
93
+        } else {
94
+            // if parent does not exist, create it
95
+            $parent = $this->normalizePath(dirname($path));
96
+            $parentType = $this->filetype($parent);
97
+            if ($parentType === false) {
98
+                if (!$this->mkdir($parent)) {
99
+                    // something went wrong
100
+                    return false;
101
+                }
102
+            } else if ($parentType === 'file') {
103
+                // parent is a file
104
+                return false;
105
+            }
106
+            // finally create the new dir
107
+            $mTime = time(); // update mtime
108
+            $data['mtime'] = $mTime;
109
+            $data['storage_mtime'] = $mTime;
110
+            $data['etag'] = $this->getETag($path);
111
+            $this->getCache()->put($path, $data);
112
+            return true;
113
+        }
114
+    }
115
+
116
+    /**
117
+     * @param string $path
118
+     * @return string
119
+     */
120
+    private function normalizePath($path) {
121
+        $path = trim($path, '/');
122
+        //FIXME why do we sometimes get a path like 'files//username'?
123
+        $path = str_replace('//', '/', $path);
124
+
125
+        // dirname('/folder') returns '.' but internally (in the cache) we store the root as ''
126
+        if (!$path || $path === '.') {
127
+            $path = '';
128
+        }
129
+
130
+        return $path;
131
+    }
132
+
133
+    /**
134
+     * Object Stores use a NoopScanner because metadata is directly stored in
135
+     * the file cache and cannot really scan the filesystem. The storage passed in is not used anywhere.
136
+     *
137
+     * @param string $path
138
+     * @param \OC\Files\Storage\Storage (optional) the storage to pass to the scanner
139
+     * @return \OC\Files\ObjectStore\NoopScanner
140
+     */
141
+    public function getScanner($path = '', $storage = null) {
142
+        if (!$storage) {
143
+            $storage = $this;
144
+        }
145
+        if (!isset($this->scanner)) {
146
+            $this->scanner = new NoopScanner($storage);
147
+        }
148
+        return $this->scanner;
149
+    }
150
+
151
+    public function getId() {
152
+        return $this->id;
153
+    }
154
+
155
+    public function rmdir($path) {
156
+        $path = $this->normalizePath($path);
157
+
158
+        if (!$this->is_dir($path)) {
159
+            return false;
160
+        }
161
+
162
+        $this->rmObjects($path);
163
+
164
+        $this->getCache()->remove($path);
165
+
166
+        return true;
167
+    }
168
+
169
+    private function rmObjects($path) {
170
+        $children = $this->getCache()->getFolderContents($path);
171
+        foreach ($children as $child) {
172
+            if ($child['mimetype'] === 'httpd/unix-directory') {
173
+                $this->rmObjects($child['path']);
174
+            } else {
175
+                $this->unlink($child['path']);
176
+            }
177
+        }
178
+    }
179
+
180
+    public function unlink($path) {
181
+        $path = $this->normalizePath($path);
182
+        $stat = $this->stat($path);
183
+
184
+        if ($stat && isset($stat['fileid'])) {
185
+            if ($stat['mimetype'] === 'httpd/unix-directory') {
186
+                return $this->rmdir($path);
187
+            }
188
+            try {
189
+                $this->objectStore->deleteObject($this->getURN($stat['fileid']));
190
+            } catch (\Exception $ex) {
191
+                if ($ex->getCode() !== 404) {
192
+                    $this->logger->logException($ex, [
193
+                        'app' => 'objectstore',
194
+                        'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
195
+                    ]);
196
+                    return false;
197
+                }
198
+                //removing from cache is ok as it does not exist in the objectstore anyway
199
+            }
200
+            $this->getCache()->remove($path);
201
+            return true;
202
+        }
203
+        return false;
204
+    }
205
+
206
+    public function stat($path) {
207
+        $path = $this->normalizePath($path);
208
+        $cacheEntry = $this->getCache()->get($path);
209
+        if ($cacheEntry instanceof CacheEntry) {
210
+            return $cacheEntry->getData();
211
+        } else {
212
+            return false;
213
+        }
214
+    }
215
+
216
+    /**
217
+     * Override this method if you need a different unique resource identifier for your object storage implementation.
218
+     * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users.
219
+     * You may need a mapping table to store your URN if it cannot be generated from the fileid.
220
+     *
221
+     * @param int $fileId the fileid
222
+     * @return null|string the unified resource name used to identify the object
223
+     */
224
+    protected function getURN($fileId) {
225
+        if (is_numeric($fileId)) {
226
+            return $this->objectPrefix . $fileId;
227
+        }
228
+        return null;
229
+    }
230
+
231
+    public function opendir($path) {
232
+        $path = $this->normalizePath($path);
233
+
234
+        try {
235
+            $files = array();
236
+            $folderContents = $this->getCache()->getFolderContents($path);
237
+            foreach ($folderContents as $file) {
238
+                $files[] = $file['name'];
239
+            }
240
+
241
+            return IteratorDirectory::wrap($files);
242
+        } catch (\Exception $e) {
243
+            $this->logger->logException($e);
244
+            return false;
245
+        }
246
+    }
247
+
248
+    public function filetype($path) {
249
+        $path = $this->normalizePath($path);
250
+        $stat = $this->stat($path);
251
+        if ($stat) {
252
+            if ($stat['mimetype'] === 'httpd/unix-directory') {
253
+                return 'dir';
254
+            }
255
+            return 'file';
256
+        } else {
257
+            return false;
258
+        }
259
+    }
260
+
261
+    public function fopen($path, $mode) {
262
+        $path = $this->normalizePath($path);
263
+
264
+        if (strrpos($path, '.') !== false) {
265
+            $ext = substr($path, strrpos($path, '.'));
266
+        } else {
267
+            $ext = '';
268
+        }
269
+
270
+        switch ($mode) {
271
+            case 'r':
272
+            case 'rb':
273
+                $stat = $this->stat($path);
274
+                if (is_array($stat)) {
275
+                    try {
276
+                        return $this->objectStore->readObject($this->getURN($stat['fileid']));
277
+                    } catch (\Exception $ex) {
278
+                        $this->logger->logException($ex, [
279
+                            'app' => 'objectstore',
280
+                            'message' => 'Count not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
281
+                        ]);
282
+                        return false;
283
+                    }
284
+                } else {
285
+                    return false;
286
+                }
287
+            case 'w':
288
+            case 'wb':
289
+            case 'w+':
290
+            case 'wb+':
291
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
292
+                $handle = fopen($tmpFile, $mode);
293
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
294
+                    $this->writeBack($tmpFile, $path);
295
+                });
296
+            case 'a':
297
+            case 'ab':
298
+            case 'r+':
299
+            case 'a+':
300
+            case 'x':
301
+            case 'x+':
302
+            case 'c':
303
+            case 'c+':
304
+                $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
305
+                if ($this->file_exists($path)) {
306
+                    $source = $this->fopen($path, 'r');
307
+                    file_put_contents($tmpFile, $source);
308
+                }
309
+                $handle = fopen($tmpFile, $mode);
310
+                return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
311
+                    $this->writeBack($tmpFile, $path);
312
+                });
313
+        }
314
+        return false;
315
+    }
316
+
317
+    public function file_exists($path) {
318
+        $path = $this->normalizePath($path);
319
+        return (bool)$this->stat($path);
320
+    }
321
+
322
+    public function rename($source, $target) {
323
+        $source = $this->normalizePath($source);
324
+        $target = $this->normalizePath($target);
325
+        $this->remove($target);
326
+        $this->getCache()->move($source, $target);
327
+        $this->touch(dirname($target));
328
+        return true;
329
+    }
330
+
331
+    public function getMimeType($path) {
332
+        $path = $this->normalizePath($path);
333
+        $stat = $this->stat($path);
334
+        if (is_array($stat)) {
335
+            return $stat['mimetype'];
336
+        } else {
337
+            return false;
338
+        }
339
+    }
340
+
341
+    public function touch($path, $mtime = null) {
342
+        if (is_null($mtime)) {
343
+            $mtime = time();
344
+        }
345
+
346
+        $path = $this->normalizePath($path);
347
+        $dirName = dirname($path);
348
+        $parentExists = $this->is_dir($dirName);
349
+        if (!$parentExists) {
350
+            return false;
351
+        }
352
+
353
+        $stat = $this->stat($path);
354
+        if (is_array($stat)) {
355
+            // update existing mtime in db
356
+            $stat['mtime'] = $mtime;
357
+            $this->getCache()->update($stat['fileid'], $stat);
358
+        } else {
359
+            try {
360
+                //create a empty file, need to have at least on char to make it
361
+                // work with all object storage implementations
362
+                $this->file_put_contents($path, ' ');
363
+                $mimeType = \OC::$server->getMimeTypeDetector()->detectPath($path);
364
+                $stat = array(
365
+                    'etag' => $this->getETag($path),
366
+                    'mimetype' => $mimeType,
367
+                    'size' => 0,
368
+                    'mtime' => $mtime,
369
+                    'storage_mtime' => $mtime,
370
+                    'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
371
+                );
372
+                $this->getCache()->put($path, $stat);
373
+            } catch (\Exception $ex) {
374
+                $this->logger->logException($ex, [
375
+                    'app' => 'objectstore',
376
+                    'message' => 'Could not create object for ' . $path,
377
+                ]);
378
+                throw $ex;
379
+            }
380
+        }
381
+        return true;
382
+    }
383
+
384
+    public function writeBack($tmpFile, $path) {
385
+        $stat = $this->stat($path);
386
+        if (empty($stat)) {
387
+            // create new file
388
+            $stat = array(
389
+                'permissions' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_CREATE,
390
+            );
391
+        }
392
+        // update stat with new data
393
+        $mTime = time();
394
+        $stat['size'] = filesize($tmpFile);
395
+        $stat['mtime'] = $mTime;
396
+        $stat['storage_mtime'] = $mTime;
397
+
398
+        // run path based detection first, to use file extension because $tmpFile is only a random string
399
+        $mimetypeDetector = \OC::$server->getMimeTypeDetector();
400
+        $mimetype = $mimetypeDetector->detectPath($path);
401
+        if ($mimetype === 'application/octet-stream') {
402
+            $mimetype = $mimetypeDetector->detect($tmpFile);
403
+        }
404
+
405
+        $stat['mimetype'] = $mimetype;
406
+        $stat['etag'] = $this->getETag($path);
407
+
408
+        $fileId = $this->getCache()->put($path, $stat);
409
+        try {
410
+            //upload to object storage
411
+            $this->objectStore->writeObject($this->getURN($fileId), fopen($tmpFile, 'r'));
412
+        } catch (\Exception $ex) {
413
+            $this->getCache()->remove($path);
414
+            $this->logger->logException($ex, [
415
+                'app' => 'objectstore',
416
+                'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
417
+            ]);
418
+            throw $ex; // make this bubble up
419
+        }
420
+    }
421
+
422
+    /**
423
+     * external changes are not supported, exclusive access to the object storage is assumed
424
+     *
425
+     * @param string $path
426
+     * @param int $time
427
+     * @return false
428
+     */
429
+    public function hasUpdated($path, $time) {
430
+        return false;
431
+    }
432 432
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -55,9 +55,9 @@  discard block
 block discarded – undo
55 55
 			throw new \Exception('missing IObjectStore instance');
56 56
 		}
57 57
 		if (isset($params['storageid'])) {
58
-			$this->id = 'object::store:' . $params['storageid'];
58
+			$this->id = 'object::store:'.$params['storageid'];
59 59
 		} else {
60
-			$this->id = 'object::store:' . $this->objectStore->getStorageId();
60
+			$this->id = 'object::store:'.$this->objectStore->getStorageId();
61 61
 		}
62 62
 		if (isset($params['objectPrefix'])) {
63 63
 			$this->objectPrefix = $params['objectPrefix'];
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
 				if ($ex->getCode() !== 404) {
192 192
 					$this->logger->logException($ex, [
193 193
 						'app' => 'objectstore',
194
-						'message' => 'Could not delete object ' . $this->getURN($stat['fileid']) . ' for ' . $path,
194
+						'message' => 'Could not delete object '.$this->getURN($stat['fileid']).' for '.$path,
195 195
 					]);
196 196
 					return false;
197 197
 				}
@@ -223,7 +223,7 @@  discard block
 block discarded – undo
223 223
 	 */
224 224
 	protected function getURN($fileId) {
225 225
 		if (is_numeric($fileId)) {
226
-			return $this->objectPrefix . $fileId;
226
+			return $this->objectPrefix.$fileId;
227 227
 		}
228 228
 		return null;
229 229
 	}
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
 					} catch (\Exception $ex) {
278 278
 						$this->logger->logException($ex, [
279 279
 							'app' => 'objectstore',
280
-							'message' => 'Count not get object ' . $this->getURN($stat['fileid']) . ' for file ' . $path,
280
+							'message' => 'Count not get object '.$this->getURN($stat['fileid']).' for file '.$path,
281 281
 						]);
282 282
 						return false;
283 283
 					}
@@ -290,7 +290,7 @@  discard block
 block discarded – undo
290 290
 			case 'wb+':
291 291
 				$tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext);
292 292
 				$handle = fopen($tmpFile, $mode);
293
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
293
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
294 294
 					$this->writeBack($tmpFile, $path);
295 295
 				});
296 296
 			case 'a':
@@ -307,7 +307,7 @@  discard block
 block discarded – undo
307 307
 					file_put_contents($tmpFile, $source);
308 308
 				}
309 309
 				$handle = fopen($tmpFile, $mode);
310
-				return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) {
310
+				return CallbackWrapper::wrap($handle, null, null, function() use ($path, $tmpFile) {
311 311
 					$this->writeBack($tmpFile, $path);
312 312
 				});
313 313
 		}
@@ -316,7 +316,7 @@  discard block
 block discarded – undo
316 316
 
317 317
 	public function file_exists($path) {
318 318
 		$path = $this->normalizePath($path);
319
-		return (bool)$this->stat($path);
319
+		return (bool) $this->stat($path);
320 320
 	}
321 321
 
322 322
 	public function rename($source, $target) {
@@ -373,7 +373,7 @@  discard block
 block discarded – undo
373 373
 			} catch (\Exception $ex) {
374 374
 				$this->logger->logException($ex, [
375 375
 					'app' => 'objectstore',
376
-					'message' => 'Could not create object for ' . $path,
376
+					'message' => 'Could not create object for '.$path,
377 377
 				]);
378 378
 				throw $ex;
379 379
 			}
@@ -413,7 +413,7 @@  discard block
 block discarded – undo
413 413
 			$this->getCache()->remove($path);
414 414
 			$this->logger->logException($ex, [
415 415
 				'app' => 'objectstore',
416
-				'message' => 'Could not create object ' . $this->getURN($fileId) . ' for ' . $path,
416
+				'message' => 'Could not create object '.$this->getURN($fileId).' for '.$path,
417 417
 			]);
418 418
 			throw $ex; // make this bubble up
419 419
 		}
Please login to merge, or discard this patch.