From 5cae863408630aee768adf70fdb5c11f72b713fa Mon Sep 17 00:00:00 2001 From: Jörn Friedrich Dreyer Date: Tue, 17 Jun 2014 22:06:56 +0200 Subject: change architecture from inheritance to composition --- lib/private/files/filesystem.php | 38 +- .../files/objectstore/abstractobjectstore.php | 436 --------------------- .../files/objectstore/homeobjectstorestorage.php | 34 ++ .../files/objectstore/objectstorestorage.php | 423 ++++++++++++++++++++ lib/private/files/objectstore/swift.php | 30 +- lib/private/util.php | 10 +- lib/public/files/objectstore/iobjectstore.php | 32 ++ 7 files changed, 532 insertions(+), 471 deletions(-) delete mode 100644 lib/private/files/objectstore/abstractobjectstore.php create mode 100644 lib/private/files/objectstore/homeobjectstorestorage.php create mode 100644 lib/private/files/objectstore/objectstorestorage.php create mode 100644 lib/public/files/objectstore/iobjectstore.php (limited to 'lib') diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index 71d70bbf2a5..4774d25ad9e 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -325,32 +325,36 @@ class Filesystem { $userObject = \OC_User::getManager()->get($user); if (!is_null($userObject)) { - $homeStorage = \OC_Config::getValue( 'objectstore', array( - //default home storage configuration: - 'class' => '\OC\Files\Storage\Home', - 'arguments' => array() - )); - // sanity checks - if (empty($homeStorage['class'])) { - \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR); - } - if (!isset($homeStorage['arguments'])) { - $homeStorage['arguments'] = array(); + $homeStorage = \OC_Config::getValue( 'objectstore' ); + if (!empty($homeStorage)) { + // sanity checks + if (empty($homeStorage['class'])) { + \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR); + } + if (!isset($homeStorage['arguments'])) { + $homeStorage['arguments'] = array(); + } + // instantiate object store implementation + $homeStorage['arguments']['objectstore'] = new $homeStorage['class']($homeStorage['arguments']); + // mount with home object store implementation + $homeStorage['class'] = '\OC\Files\ObjectStore\HomeObjectStoreStorage'; + } else { + $homeStorage = array( + //default home storage configuration: + 'class' => '\OC\Files\Storage\Home', + 'arguments' => array() + ); } $homeStorage['arguments']['user'] = $userObject; + // check for legacy home id (<= 5.0.12) if (\OC\Files\Cache\Storage::exists('local::' . $root . '/')) { $homeStorage['arguments']['legacy'] = true; } + self::mount($homeStorage['class'], $homeStorage['arguments'], $user); $home = \OC\Files\Filesystem::getStorage($user); - if ( $home->instanceOfStorage('\OC\Files\ObjectStore\AbstractObjectStore') ) { - //create the files folder in the cache when mounting the objectstore for a user - if ( ! $home->is_dir('files') ) { - $home->mkdir('files'); - } - } } else { self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); diff --git a/lib/private/files/objectstore/abstractobjectstore.php b/lib/private/files/objectstore/abstractobjectstore.php deleted file mode 100644 index de82003f0e8..00000000000 --- a/lib/private/files/objectstore/abstractobjectstore.php +++ /dev/null @@ -1,436 +0,0 @@ - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU AFFERO GENERAL PUBLIC LICENSE for more details. - * - * You should have received a copy of the GNU Affero General Public - * License along with this library. If not, see . - * - */ - -namespace OC\Files\ObjectStore; - -abstract class AbstractObjectStore extends \OC\Files\Storage\Common { - - /** - * @param string $urn the unified resource name used to identify the object - * @param string $tmpFile path to the local temporary file that the object - * should be loaded from - * @return void - * @throws Exception when something goes wrong, message will be logged - */ - abstract protected function createObject($urn, $tmpFile = null); - - /** - * @param string $urn the unified resource name used to identify the object - * @param string $tmpFile path to the local temporary file that should be - * used to store the object - * @return void - * @throws Exception when something goes wrong, message will be logged - */ - abstract protected function getObject($urn, $tmpFile); - - /** - * @param string $urn the unified resource name used to identify the object - * @return void - * @throws Exception when something goes wrong, message will be logged - */ - abstract protected function deleteObject($urn); - - /** - * @var \OC\User\User $user - */ - protected $user; - - /** - * @var array - */ - private static $tmpFiles = array(); - - public function __construct($params) { - if (isset($params['user']) && is_object($params['user'])) { - $this->user = $params['user']; - } else { - $this->user = null; - } - //initialize cache with root directory in cache - if ( ! $this->is_dir('/') ) { - $this->mkdir('/'); - } - } - - /** - * Object Stores use a NoopScanner because metadata is directly stored in - * the file cache and cannot really scan the filesystem - * @param string $path - * @return \OC\Files\ObjectStore\NoopScanner - */ - public function getScanner($path = '') { - if (!isset($this->scanner)) { - $this->scanner = new NoopScanner($this); - } - return $this->scanner; - } - - /** - * get the owner of a path - * - * @param string $path The path to get the owner - * @return false|string uid - */ - public function getOwner($path) { - if (is_object($this->user)) { - return $this->user->getUID(); - } - return false; - } - - /** - * @param string $path, optional - * @return \OC\User\User - */ - public function getUser($path = null) { - return $this->user; - } - - /** - * @param string $path - * @return string - */ - private function normalizePath($path) { - $path = trim($path, '/'); - //FIXME why do we sometimes get a path like 'files//username'? - $path = str_replace('//', '/', $path); - - if (!$path) { - $path = '.'; - } - - return $path; - } - - public function getId () { - if (is_object($this->user)) { - return 'objstore::user:' . $this->user->getUID(); - } - return 'objstore::root'; - } - - public function mkdir($path) { - $path = $this->normalizePath($path); - - if($this->is_dir($path)) { - return false; - } - - $dirName = dirname($path); - $parentExists = $this->is_dir($dirName); - - $mTime = time(); - - $data = array( - 'mimetype' => 'httpd/unix-directory', - 'size' => 0, - 'mtime' => $mTime, - 'storage_mtime' => $mTime, - 'permissions' => \OCP\PERMISSION_ALL, - ); - - if ($dirName === '.' && ! $parentExists ) { - //create root on the fly - $data['etag'] = $this->getETag($dirName); - $this->getCache()->put('', $data); - $parentExists = true; - } - - if ($parentExists) { - $data['etag'] = $this->getETag($path); - $this->getCache()->put($path, $data); - return true; - } - return false; - } - - public function file_exists($path) { - $path = $this->normalizePath($path); - return (bool)$this->stat($path); - } - - private function rmObjects($path) { - $children = $this->getCache()->getFolderContents($path); - foreach ($children as $child) { - if ($child['mimetype'] === 'httpd/unix-directory') { - $this->rmObjects($child['path']); - } else { - $this->unlink($child['path']); - } - } - } - - public function rmdir($path) { - $path = $this->normalizePath($path); - - if (!$this->is_dir($path)) { - return false; - } - - $this->rmObjects($path); - - $this->getCache()->remove($path); - - return true; - } - - public function opendir($path) { - $path = $this->normalizePath($path); - - if ($path === '.') { - $path = ''; - } else if ($path) { - $path .= '/'; - } - - try { - $files = array(); - $folderContents = $this->getCache()->getFolderContents($path); - foreach ($folderContents as $file) { - $files[] = $file['name']; - } - - \OC\Files\Stream\Dir::register('objstore' . $path, $files); - - return opendir('fakedir://objstore' . $path); - } catch (Exception $e) { - \OCP\Util::writeLog('objectstore', $e->getMessage(), \OCP\Util::ERROR); - return false; - } - } - - public function stat($path) { - return $this->getCache()->get($path); - } - - public function filetype($path) { - $path = $this->normalizePath($path); - $stat = $this->stat($path); - if ($stat) { - if ($stat['mimetype'] === 'httpd/unix-directory') { - return 'dir'; - } - return 'file'; - } else { - return false; - } - } - - - public function unlink($path) { - $path = $this->normalizePath($path); - $stat = $this->stat($path); - - if ($stat && isset($stat['fileid'])) { - if ($stat['mimetype'] === 'httpd/unix-directory') { - return $this->rmdir($path); - } - try { - $this->deleteObject($this->getURN($stat['fileid'])); - } catch (\Exception $ex) { - if ($ex->getCode() !== 404) { - \OCP\Util::writeLog('objectstore', 'Could not delete object: '.$ex->getMessage(), \OCP\Util::ERROR); - return false; - } else { - //removing from cache is ok as it does not exist in the objectstore anyway - } - } - $this->getCache()->remove($path); - return true; - } - return false; - } - - public function fopen($path, $mode) { - $path = $this->normalizePath($path); - - switch ($mode) { - case 'r': - case 'rb': - $stat = $this->stat($path); - if (is_array($stat)) { - $tmpFile = \OC_Helper::tmpFile(); - self::$tmpFiles[$tmpFile] = $path; - try { - $this->getObject($this->getURN($stat['fileid']), $tmpFile); - } catch (\Exception $ex) { - \OCP\Util::writeLog('objectstore', 'Could not get object: '.$ex->getMessage(), \OCP\Util::ERROR); - return false; - } - return fopen($tmpFile, 'r'); - } else { - return false; - } - case 'w': - case 'wb': - case 'a': - case 'ab': - case 'r+': - case 'w+': - case 'wb+': - case 'a+': - case 'x': - case 'x+': - case 'c': - case 'c+': - if (strrpos($path, '.') !== false) { - $ext = substr($path, strrpos($path, '.')); - } else { - $ext = ''; - } - $tmpFile = \OC_Helper::tmpFile($ext); - \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); - if ($this->file_exists($path)) { - $source = $this->fopen($path, 'r'); - file_put_contents($tmpFile, $source); - } - self::$tmpFiles[$tmpFile] = $path; - - return fopen('close://' . $tmpFile, $mode); - } - return false; - } - - public function rename($path1, $path2) { - $path1 = $this->normalizePath($path1); - $path2 = $this->normalizePath($path2); - $stat1 = $this->stat($path1); - if (is_array($stat1)) { - $parent = $this->stat(dirname($path2)); - if (is_array($parent)) { - $stat2 = $this->stat($path2); - if (is_array($stat2)) { - $this->unlink($path2); - } - $stat1['parent'] = $parent['fileid']; - $stat1['path'] = $path2; - $stat1['path_hash'] = md5($path2); - $stat1['name'] = \OC_Util::basename($path2); - $stat1['mtime'] = time(); - $stat1['etag'] = $this->getETag($path2); - $this->getCache()->update($stat1['fileid'], $stat1); - return true; - } else { - return false; - } - - } else { - return false; - } - } - - public function getMimeType($path) { - $path = $this->normalizePath($path); - $stat = $this->stat($path); - if (is_array($stat)) { - return $stat['mimetype']; - } else { - return false; - } - } - - public function touch($path, $mtime = null) { - if (is_null($mtime)) { - $mtime = time(); - } - - $path = $this->normalizePath($path); - $dirName = dirname($path); - $parentExists = $this->is_dir($dirName); - if (!$parentExists) { - return false; - } - - $stat = $this->stat($path); - if (is_array($stat)) { - // update existing mtime in db - $stat['mtime'] = $mtime; - $this->getCache()->update($stat['fileid'], $stat); - } else { - $mimeType = \OC_Helper::getFileNameMimeType($path); - // create new file - $stat = array( - 'etag' => $this->getETag($path), - 'mimetype' => $mimeType, - 'size' => 0, - 'mtime' => $mtime, - 'storage_mtime' => $mtime, - 'permissions' => \OCP\PERMISSION_ALL, - ); - $fileId = $this->getCache()->put($path, $stat); - try { - $this->createObject($this->getURN($fileId)); - } catch (\Exception $ex) { - $this->getCache()->remove($path); - \OCP\Util::writeLog('objectstore', 'Could not create object: '.$ex->getMessage(), \OCP\Util::ERROR); - return false; - } - } - return true; - } - - /** - * Override this method if you need a different unique resource identifier for your object storage implementation. - * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users. - * You may need a mapping table to store your URN if it cannot be generated from the fileid. - * @param int $fileId the fileid - * @return null|string the unified resource name used to identify the object - */ - protected function getURN($fileId) { - if (is_numeric($fileId)) { - return 'urn:oid:'.$fileId; - } - return null; - } - - public function writeBack($tmpFile) { - if (!isset(self::$tmpFiles[$tmpFile])) { - return false; - } - - $path = self::$tmpFiles[$tmpFile]; - $stat = $this->stat($path); - if (empty($stat)) { - // create new file - $stat = array( - 'etag' => $this->getETag($path), - 'permissions' => \OCP\PERMISSION_ALL, - ); - } - // update stat with new data - $mTime = time(); - $stat['size'] = filesize($tmpFile); - $stat['mtime'] = $mTime; - $stat['storage_mtime'] = $mTime; - $stat['mimetype'] = \OC_Helper::getMimeType($tmpFile); - - $fileId = $this->getCache()->put($path, $stat); - try { - //upload to object storage - $this->createObject($this->getURN($fileId), $tmpFile); - } catch (\Exception $ex) { - $this->getCache()->remove($path); - \OCP\Util::writeLog('objectstore', 'Could not create object: '.$ex->getMessage(), \OCP\Util::ERROR); - return false; - } - return true; - } - -} \ No newline at end of file diff --git a/lib/private/files/objectstore/homeobjectstorestorage.php b/lib/private/files/objectstore/homeobjectstorestorage.php new file mode 100644 index 00000000000..0c889725828 --- /dev/null +++ b/lib/private/files/objectstore/homeobjectstorestorage.php @@ -0,0 +1,34 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ + +namespace OC\Files\ObjectStore; + +class HomeObjectStoreStorage extends ObjectStoreStorage { + + public function __construct($params) { + parent::__construct($params); + + //initialize cache with root directory in cache + if ( ! $this->is_dir('files') ) { + $this->mkdir('files'); + } + } + +} \ No newline at end of file diff --git a/lib/private/files/objectstore/objectstorestorage.php b/lib/private/files/objectstore/objectstorestorage.php new file mode 100644 index 00000000000..6b48e2d78dd --- /dev/null +++ b/lib/private/files/objectstore/objectstorestorage.php @@ -0,0 +1,423 @@ + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ + +namespace OC\Files\ObjectStore; + +use OCP\Files\ObjectStore\IObjectStore; + +class ObjectStoreStorage extends \OC\Files\Storage\Common { + + /** + * @var \OCP\Files\ObjectStore\IObjectStore $objectStore + */ + protected $objectStore; + + /** + * @var \OC\User\User $user + */ + protected $user; + + /** + * @var array + */ + private static $tmpFiles = array(); + + public function __construct($params) { + if (isset($params['user']) && $params['user'] instanceof \OC\User\User) { + $this->user = $params['user']; + } else { + $this->user = null; + } + if (isset($params['objectstore']) && $params['objectstore'] instanceof IObjectStore) { + $this->objectStore = $params['objectstore']; + } else { + throw new \Exception('missing IObjectStore instance'); + } + //initialize cache with root directory in cache + if ( ! $this->is_dir('/') ) { + $this->mkdir('/'); + } + } + + /** + * Object Stores use a NoopScanner because metadata is directly stored in + * the file cache and cannot really scan the filesystem + * @param string $path + * @return \OC\Files\ObjectStore\NoopScanner + */ + public function getScanner($path = '') { + if (!isset($this->scanner)) { + $this->scanner = new NoopScanner($this); + } + return $this->scanner; + } + + /** + * get the owner of a path + * + * @param string $path The path to get the owner + * @return false|string uid + */ + public function getOwner($path) { + if (is_object($this->user)) { + return $this->user->getUID(); + } + return false; + } + + /** + * @param string $path, optional + * @return \OC\User\User + */ + public function getUser($path = null) { + return $this->user; + } + + /** + * @param string $path + * @return string + */ + private function normalizePath($path) { + $path = trim($path, '/'); + //FIXME why do we sometimes get a path like 'files//username'? + $path = str_replace('//', '/', $path); + + if (!$path) { + $path = '.'; + } + + return $path; + } + + public function getId () { + if (is_object($this->user)) { + return 'objstore::user:' . $this->user->getUID(); + } + return 'objstore::root'; + } + + public function mkdir($path) { + $path = $this->normalizePath($path); + + if($this->is_dir($path)) { + return false; + } + + $dirName = dirname($path); + $parentExists = $this->is_dir($dirName); + + $mTime = time(); + + $data = array( + 'mimetype' => 'httpd/unix-directory', + 'size' => 0, + 'mtime' => $mTime, + 'storage_mtime' => $mTime, + 'permissions' => \OCP\PERMISSION_ALL, + ); + + if ($dirName === '.' && ! $parentExists ) { + //create root on the fly + $data['etag'] = $this->getETag($dirName); + $this->getCache()->put('', $data); + $parentExists = true; + } + + if ($parentExists) { + $data['etag'] = $this->getETag($path); + $this->getCache()->put($path, $data); + return true; + } + return false; + } + + public function file_exists($path) { + $path = $this->normalizePath($path); + return (bool)$this->stat($path); + } + + private function rmObjects($path) { + $children = $this->getCache()->getFolderContents($path); + foreach ($children as $child) { + if ($child['mimetype'] === 'httpd/unix-directory') { + $this->rmObjects($child['path']); + } else { + $this->unlink($child['path']); + } + } + } + + public function rmdir($path) { + $path = $this->normalizePath($path); + + if (!$this->is_dir($path)) { + return false; + } + + $this->rmObjects($path); + + $this->getCache()->remove($path); + + return true; + } + + public function opendir($path) { + $path = $this->normalizePath($path); + + if ($path === '.') { + $path = ''; + } else if ($path) { + $path .= '/'; + } + + try { + $files = array(); + $folderContents = $this->getCache()->getFolderContents($path); + foreach ($folderContents as $file) { + $files[] = $file['name']; + } + + \OC\Files\Stream\Dir::register('objstore' . $path, $files); + + return opendir('fakedir://objstore' . $path); + } catch (Exception $e) { + \OCP\Util::writeLog('objectstore', $e->getMessage(), \OCP\Util::ERROR); + return false; + } + } + + public function stat($path) { + return $this->getCache()->get($path); + } + + public function filetype($path) { + $path = $this->normalizePath($path); + $stat = $this->stat($path); + if ($stat) { + if ($stat['mimetype'] === 'httpd/unix-directory') { + return 'dir'; + } + return 'file'; + } else { + return false; + } + } + + + public function unlink($path) { + $path = $this->normalizePath($path); + $stat = $this->stat($path); + + if ($stat && isset($stat['fileid'])) { + if ($stat['mimetype'] === 'httpd/unix-directory') { + return $this->rmdir($path); + } + try { + $this->objectStore->deleteObject($this->getURN($stat['fileid'])); + } catch (\Exception $ex) { + if ($ex->getCode() !== 404) { + \OCP\Util::writeLog('objectstore', 'Could not delete object: '.$ex->getMessage(), \OCP\Util::ERROR); + return false; + } else { + //removing from cache is ok as it does not exist in the objectstore anyway + } + } + $this->getCache()->remove($path); + return true; + } + return false; + } + + public function fopen($path, $mode) { + $path = $this->normalizePath($path); + + switch ($mode) { + case 'r': + case 'rb': + $stat = $this->stat($path); + if (is_array($stat)) { + $tmpFile = \OC_Helper::tmpFile(); + self::$tmpFiles[$tmpFile] = $path; + try { + $this->objectStore->getObject($this->getURN($stat['fileid']), $tmpFile); + } catch (\Exception $ex) { + \OCP\Util::writeLog('objectstore', 'Could not get object: '.$ex->getMessage(), \OCP\Util::ERROR); + return false; + } + return fopen($tmpFile, 'r'); + } else { + return false; + } + case 'w': + case 'wb': + case 'a': + case 'ab': + case 'r+': + case 'w+': + case 'wb+': + case 'a+': + case 'x': + case 'x+': + case 'c': + case 'c+': + if (strrpos($path, '.') !== false) { + $ext = substr($path, strrpos($path, '.')); + } else { + $ext = ''; + } + $tmpFile = \OC_Helper::tmpFile($ext); + \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); + if ($this->file_exists($path)) { + $source = $this->fopen($path, 'r'); + file_put_contents($tmpFile, $source); + } + self::$tmpFiles[$tmpFile] = $path; + + return fopen('close://' . $tmpFile, $mode); + } + return false; + } + + public function rename($path1, $path2) { + $path1 = $this->normalizePath($path1); + $path2 = $this->normalizePath($path2); + $stat1 = $this->stat($path1); + if (is_array($stat1)) { + $parent = $this->stat(dirname($path2)); + if (is_array($parent)) { + $stat2 = $this->stat($path2); + if (is_array($stat2)) { + $this->unlink($path2); + } + $stat1['parent'] = $parent['fileid']; + $stat1['path'] = $path2; + $stat1['path_hash'] = md5($path2); + $stat1['name'] = \OC_Util::basename($path2); + $stat1['mtime'] = time(); + $stat1['etag'] = $this->getETag($path2); + $this->getCache()->update($stat1['fileid'], $stat1); + return true; + } else { + return false; + } + + } else { + return false; + } + } + + public function getMimeType($path) { + $path = $this->normalizePath($path); + $stat = $this->stat($path); + if (is_array($stat)) { + return $stat['mimetype']; + } else { + return false; + } + } + + public function touch($path, $mtime = null) { + if (is_null($mtime)) { + $mtime = time(); + } + + $path = $this->normalizePath($path); + $dirName = dirname($path); + $parentExists = $this->is_dir($dirName); + if (!$parentExists) { + return false; + } + + $stat = $this->stat($path); + if (is_array($stat)) { + // update existing mtime in db + $stat['mtime'] = $mtime; + $this->getCache()->update($stat['fileid'], $stat); + } else { + $mimeType = \OC_Helper::getFileNameMimeType($path); + // create new file + $stat = array( + 'etag' => $this->getETag($path), + 'mimetype' => $mimeType, + 'size' => 0, + 'mtime' => $mtime, + 'storage_mtime' => $mtime, + 'permissions' => \OCP\PERMISSION_ALL, + ); + $fileId = $this->getCache()->put($path, $stat); + try { + $this->objectStore->updateObject($this->getURN($fileId)); + } catch (\Exception $ex) { + $this->getCache()->remove($path); + \OCP\Util::writeLog('objectstore', 'Could not create object: '.$ex->getMessage(), \OCP\Util::ERROR); + return false; + } + } + return true; + } + + /** + * Override this method if you need a different unique resource identifier for your object storage implementation. + * The default implementations just appends the fileId to 'urn:oid:'. Make sure the URN is unique over all users. + * You may need a mapping table to store your URN if it cannot be generated from the fileid. + * @param int $fileId the fileid + * @return null|string the unified resource name used to identify the object + */ + protected function getURN($fileId) { + if (is_numeric($fileId)) { + return 'urn:oid:'.$fileId; + } + return null; + } + + public function writeBack($tmpFile) { + if (!isset(self::$tmpFiles[$tmpFile])) { + return false; + } + + $path = self::$tmpFiles[$tmpFile]; + $stat = $this->stat($path); + if (empty($stat)) { + // create new file + $stat = array( + 'etag' => $this->getETag($path), + 'permissions' => \OCP\PERMISSION_ALL, + ); + } + // update stat with new data + $mTime = time(); + $stat['size'] = filesize($tmpFile); + $stat['mtime'] = $mTime; + $stat['storage_mtime'] = $mTime; + $stat['mimetype'] = \OC_Helper::getMimeType($tmpFile); + + $fileId = $this->getCache()->put($path, $stat); + try { + //upload to object storage + $this->objectStore->updateObject($this->getURN($fileId), $tmpFile); + } catch (\Exception $ex) { + $this->getCache()->remove($path); + \OCP\Util::writeLog('objectstore', 'Could not create object: '.$ex->getMessage(), \OCP\Util::ERROR); + return false; + } + return true; + } + +} \ No newline at end of file diff --git a/lib/private/files/objectstore/swift.php b/lib/private/files/objectstore/swift.php index 53367367af0..f66b03889d2 100644 --- a/lib/private/files/objectstore/swift.php +++ b/lib/private/files/objectstore/swift.php @@ -23,7 +23,7 @@ namespace OC\Files\ObjectStore; use Guzzle\Http\Exception\ClientErrorResponseException; use OpenCloud\OpenStack; -class Swift extends AbstractObjectStore { +class Swift implements \OCP\Files\ObjectStore\IObjectStore { /** * @var \OpenCloud\ObjectStore\Service @@ -78,19 +78,22 @@ class Swift extends AbstractObjectStore { throw $ex; } } - - //set the user via parent constructor, also initializes the root of the filecache - parent::__construct($params); } + /** * @param string $urn Unified Resource Name + * @param string $tmpFile * @return void * @throws Exception from openstack lib when something goes wrong */ - protected function deleteObject($urn) { - $object = $this->container->getObject($urn); - $object->delete(); + public function updateObject($urn, $tmpFile = null) { + $fileData = ''; + if ($tmpFile) { + $fileData = fopen($tmpFile, 'r'); + } + + $this->container->uploadObject($urn, $fileData); } /** @@ -99,7 +102,7 @@ class Swift extends AbstractObjectStore { * @return void * @throws Exception from openstack lib when something goes wrong */ - protected function getObject($urn, $tmpFile) { + public function getObject($urn, $tmpFile) { $object = $this->container->getObject($urn); /** @var $objectContent \Guzzle\Http\EntityBody **/ @@ -112,17 +115,12 @@ class Swift extends AbstractObjectStore { /** * @param string $urn Unified Resource Name - * @param string $tmpFile * @return void * @throws Exception from openstack lib when something goes wrong */ - protected function createObject($urn, $tmpFile = null) { - $fileData = ''; - if ($tmpFile) { - $fileData = fopen($tmpFile, 'r'); - } - - $this->container->uploadObject($urn, $fileData); + public function deleteObject($urn) { + $object = $this->container->getObject($urn); + $object->delete(); } public function deleteContainer($recursive = false) { diff --git a/lib/private/util.php b/lib/private/util.php index f2ecdcbded6..d384eda5f7f 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -32,11 +32,17 @@ class OC_Util { private static function initObjectStoreRootFS($config) { // check misconfiguration if (empty($config['class'])) { - //FIXME log error? + \OCP\Util::writeLog('files', 'No class given for objectstore', \OCP\Util::ERROR); } if (!isset($config['arguments'])) { $config['arguments'] = array(); } + + // instantiate object store implementation + $config['arguments']['objectstore'] = new $config['class']($config['arguments']); + // mount with plain / root object store implementation + $config['class'] = '\OC\Files\ObjectStore\ObjectStoreStorage'; + // mount object storage as root \OC\Files\Filesystem::initMounts(); if(!self::$rootMounted) { @@ -94,7 +100,7 @@ class OC_Util { * @var \OC\Files\Storage\Storage $storage */ if ($storage->instanceOfStorage('\OC\Files\Storage\Home') - || $storage->instanceOfStorage('\OC\Files\ObjectStore\AbstractObjectStore') + || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage') ) { if (is_object($storage->getUser())) { $user = $storage->getUser()->getUID(); diff --git a/lib/public/files/objectstore/iobjectstore.php b/lib/public/files/objectstore/iobjectstore.php new file mode 100644 index 00000000000..ecc35faf34a --- /dev/null +++ b/lib/public/files/objectstore/iobjectstore.php @@ -0,0 +1,32 @@ +