@@ -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); |
@@ -0,0 +1,34 @@ | |||
<?php | |||
/** | |||
* @author Jörn Friedrich Dreyer | |||
* @copyright (c) 2014 Jörn Friedrich Dreyer <jfd@owncloud.com> | |||
* | |||
* 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 <http://www.gnu.org/licenses/>. | |||
* | |||
*/ | |||
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'); | |||
} | |||
} | |||
} |
@@ -20,32 +20,14 @@ | |||
namespace OC\Files\ObjectStore; | |||
abstract class AbstractObjectStore extends \OC\Files\Storage\Common { | |||
use OCP\Files\ObjectStore\IObjectStore; | |||
/** | |||
* @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); | |||
class ObjectStoreStorage 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 should be | |||
* used to store the object | |||
* @return void | |||
* @throws Exception when something goes wrong, message will be logged | |||
* @var \OCP\Files\ObjectStore\IObjectStore $objectStore | |||
*/ | |||
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); | |||
protected $objectStore; | |||
/** | |||
* @var \OC\User\User $user | |||
@@ -58,11 +40,16 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common { | |||
private static $tmpFiles = array(); | |||
public function __construct($params) { | |||
if (isset($params['user']) && is_object($params['user'])) { | |||
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('/'); | |||
@@ -243,7 +230,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common { | |||
return $this->rmdir($path); | |||
} | |||
try { | |||
$this->deleteObject($this->getURN($stat['fileid'])); | |||
$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); | |||
@@ -269,7 +256,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common { | |||
$tmpFile = \OC_Helper::tmpFile(); | |||
self::$tmpFiles[$tmpFile] = $path; | |||
try { | |||
$this->getObject($this->getURN($stat['fileid']), $tmpFile); | |||
$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; | |||
@@ -376,7 +363,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common { | |||
); | |||
$fileId = $this->getCache()->put($path, $stat); | |||
try { | |||
$this->createObject($this->getURN($fileId)); | |||
$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); | |||
@@ -424,7 +411,7 @@ abstract class AbstractObjectStore extends \OC\Files\Storage\Common { | |||
$fileId = $this->getCache()->put($path, $stat); | |||
try { | |||
//upload to object storage | |||
$this->createObject($this->getURN($fileId), $tmpFile); | |||
$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); |
@@ -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) { |
@@ -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(); |
@@ -0,0 +1,32 @@ | |||
<?php | |||
namespace OCP\Files\ObjectStore; | |||
interface IObjectStore { | |||
/** | |||
* @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 | |||
*/ | |||
function getObject($urn, $tmpFile); | |||
/** | |||
* @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 | |||
*/ | |||
function updateObject($urn, $tmpFile = null); | |||
/** | |||
* @param string $urn the unified resource name used to identify the object | |||
* @return void | |||
* @throws Exception when something goes wrong, message will be logged | |||
*/ | |||
function deleteObject($urn); | |||
} |
@@ -20,6 +20,7 @@ | |||
namespace OCA\ObjectStore\Tests\Unit; | |||
use OC\Files\ObjectStore\ObjectStoreStorage; | |||
use OC\Files\ObjectStore\Swift as ObjectStoreToTest; | |||
use PHPUnit_Framework_TestCase; | |||
@@ -30,6 +31,8 @@ class Swift extends PHPUnit_Framework_TestCase { | |||
* @var \OC\Files\ObjectStore\Swift $storage | |||
*/ | |||
private $storage; | |||
private $objectStorage; | |||
public function setUp() { | |||
@@ -67,14 +70,16 @@ class Swift extends PHPUnit_Framework_TestCase { | |||
'serviceName' => 'swift', //trystack uses swift by default, the lib defaults to 'cloudFiles' if omitted | |||
'user' => \OC_User::getManager()->get($userName) | |||
); | |||
$this->storage = new ObjectStoreToTest($params); | |||
$this->objectStorage = new ObjectStoreToTest($params); | |||
$params['objectstore'] = $this->objectStorage; | |||
$this->storage = new ObjectStoreStorage($params); | |||
} | |||
public function tearDown() { | |||
if (is_null($this->storage)) { | |||
return; | |||
} | |||
$this->storage->deleteContainer(true); | |||
$this->objectStorage->deleteContainer(true); | |||
$this->storage->getCache()->clear(); | |||
//TODO how do I clear hooks? | |||
} |