summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/lib/connector/sabre/objecttree.php3
-rw-r--r--apps/files_sharing/lib/cache.php13
-rw-r--r--apps/files_sharing/lib/scanner.php2
-rw-r--r--apps/files_sharing/lib/watcher.php3
-rw-r--r--apps/files_sharing/tests/backend.php6
-rw-r--r--apps/files_sharing/tests/external/cache.php4
-rw-r--r--apps/files_sharing/tests/sharedmount.php6
-rw-r--r--apps/files_sharing/tests/updater.php6
-rw-r--r--apps/files_sharing/tests/watcher.php12
-rw-r--r--apps/files_versions/tests/versions.php10
-rw-r--r--lib/private/files/cache/cache.php67
-rw-r--r--lib/private/files/cache/cacheentry.php114
-rw-r--r--lib/private/files/cache/homecache.php4
-rw-r--r--lib/private/files/cache/propagator.php6
-rw-r--r--lib/private/files/cache/scanner.php31
-rw-r--r--lib/private/files/cache/updater.php16
-rw-r--r--lib/private/files/cache/watcher.php13
-rw-r--r--lib/private/files/cache/wrapper/cachewrapper.php15
-rw-r--r--lib/private/files/fileinfo.php3
-rw-r--r--lib/private/files/objectstore/objectstorestorage.php8
-rw-r--r--lib/private/files/storage/common.php3
-rw-r--r--lib/private/files/storage/wrapper/encryption.php4
-rw-r--r--lib/private/files/storage/wrapper/quota.php4
-rw-r--r--lib/private/files/storage/wrapper/wrapper.php15
-rw-r--r--lib/private/files/view.php48
-rw-r--r--lib/public/files/cache/icache.php249
-rw-r--r--lib/public/files/cache/icacheentry.php132
-rw-r--r--lib/public/files/cache/ipropagator.php37
-rw-r--r--lib/public/files/cache/iscanner.php81
-rw-r--r--lib/public/files/cache/iupdater.php75
-rw-r--r--lib/public/files/cache/iwatcher.php82
-rw-r--r--lib/public/files/storage.php13
-rw-r--r--lib/public/files/storage/ilockingstorage.php60
-rw-r--r--lib/public/files/storage/istorage.php482
-rw-r--r--tests/lib/files/cache/cache.php2
-rw-r--r--tests/lib/files/cache/scanner.php4
-rw-r--r--tests/lib/files/storage/wrapper/quota.php4
37 files changed, 1495 insertions, 142 deletions
diff --git a/apps/dav/lib/connector/sabre/objecttree.php b/apps/dav/lib/connector/sabre/objecttree.php
index ba4c855f58a..55b310a4405 100644
--- a/apps/dav/lib/connector/sabre/objecttree.php
+++ b/apps/dav/lib/connector/sabre/objecttree.php
@@ -135,9 +135,8 @@ class ObjectTree extends \Sabre\DAV\Tree {
/**
* @var \OC\Files\Storage\Storage $storage
*/
- $scanner = $storage->getScanner($internalPath);
// get data directly
- $data = $scanner->getData($internalPath);
+ $data = $storage->getMetaData($internalPath);
$info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
} else {
$info = null;
diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php
index 714cc144c0b..10d1e787922 100644
--- a/apps/files_sharing/lib/cache.php
+++ b/apps/files_sharing/lib/cache.php
@@ -33,6 +33,7 @@
namespace OC\Files\Cache;
use OC\User\NoUserException;
+use OCP\Files\Cache\ICacheEntry;
use OCP\Share_Backend_Collection;
/**
@@ -98,8 +99,8 @@ class Shared_Cache extends Cache {
/**
* get the stored metadata of a file or folder
*
- * @param string $file
- * @return array|false
+ * @param string|int $file
+ * @return ICacheEntry|false
*/
public function get($file) {
$mimetypeLoader = \OC::$server->getMimeTypeLoader();
@@ -161,7 +162,7 @@ class Shared_Cache extends Cache {
* get the metadata of all files stored in $folder
*
* @param string $folderId
- * @return array|false
+ * @return ICacheEntry[]|false
*/
public function getFolderContentsById($folderId) {
$cache = $this->getSourceCache('');
@@ -281,7 +282,7 @@ class Shared_Cache extends Cache {
* search for files matching $pattern
*
* @param string $pattern
- * @return array of file data
+ * @return ICacheEntry[] of file data
*/
public function search($pattern) {
@@ -320,7 +321,7 @@ class Shared_Cache extends Cache {
* search for files by mimetype
*
* @param string $mimetype
- * @return array
+ * @return ICacheEntry[]
*/
public function searchByMime($mimetype) {
$mimepart = null;
@@ -373,7 +374,7 @@ class Shared_Cache extends Cache {
*
* @param string|int $tag tag to search for
* @param string $userId owner of the tags
- * @return array file data
+ * @return ICacheEntry[] file data
*/
public function searchByTag($tag, $userId) {
// TODO: inject this
diff --git a/apps/files_sharing/lib/scanner.php b/apps/files_sharing/lib/scanner.php
index 1152c49755a..bd6a28a4934 100644
--- a/apps/files_sharing/lib/scanner.php
+++ b/apps/files_sharing/lib/scanner.php
@@ -35,7 +35,7 @@ class SharedScanner extends Scanner {
*
* @return array an array of metadata of the file
*/
- public function getData($path){
+ protected function getData($path){
$data = parent::getData($path);
$sourcePath = $this->storage->getSourcePath($path);
list($sourceStorage, $internalPath) = \OC\Files\Filesystem::resolvePath($sourcePath);
diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php
index 9a8968f2265..5b4736c21e1 100644
--- a/apps/files_sharing/lib/watcher.php
+++ b/apps/files_sharing/lib/watcher.php
@@ -24,6 +24,7 @@
*/
namespace OC\Files\Cache;
+use OCP\Files\Cache\ICacheEntry;
/**
* check the storage backends for updates and change the cache accordingly
@@ -38,7 +39,7 @@ class Shared_Watcher extends Watcher {
* Update the cache for changes to $path
*
* @param string $path
- * @param array $cachedData
+ * @param ICacheEntry $cachedData
*/
public function update($path, $cachedData) {
parent::update($path, $cachedData);
diff --git a/apps/files_sharing/tests/backend.php b/apps/files_sharing/tests/backend.php
index 0e151d9e76a..acb59855394 100644
--- a/apps/files_sharing/tests/backend.php
+++ b/apps/files_sharing/tests/backend.php
@@ -58,8 +58,10 @@ class Test_Files_Sharing_Backend extends TestCase {
}
protected function tearDown() {
- $this->view->unlink($this->filename);
- $this->view->deleteAll($this->folder);
+ if ($this->view) {
+ $this->view->unlink($this->filename);
+ $this->view->deleteAll($this->folder);
+ }
parent::tearDown();
}
diff --git a/apps/files_sharing/tests/external/cache.php b/apps/files_sharing/tests/external/cache.php
index 52e01677fa3..3e078bf3722 100644
--- a/apps/files_sharing/tests/external/cache.php
+++ b/apps/files_sharing/tests/external/cache.php
@@ -75,7 +75,9 @@ class Cache extends TestCase {
}
protected function tearDown() {
- $this->cache->clear();
+ if ($this->cache) {
+ $this->cache->clear();
+ }
parent::tearDown();
}
diff --git a/apps/files_sharing/tests/sharedmount.php b/apps/files_sharing/tests/sharedmount.php
index 347ec0d2a7b..e01deeb60f4 100644
--- a/apps/files_sharing/tests/sharedmount.php
+++ b/apps/files_sharing/tests/sharedmount.php
@@ -48,8 +48,10 @@ class Test_Files_Sharing_Mount extends OCA\Files_sharing\Tests\TestCase {
}
protected function tearDown() {
- $this->view->unlink($this->folder);
- $this->view->unlink($this->filename);
+ if ($this->view) {
+ $this->view->unlink($this->folder);
+ $this->view->unlink($this->filename);
+ }
parent::tearDown();
}
diff --git a/apps/files_sharing/tests/updater.php b/apps/files_sharing/tests/updater.php
index 02c5f487e0a..dd1f83c99a8 100644
--- a/apps/files_sharing/tests/updater.php
+++ b/apps/files_sharing/tests/updater.php
@@ -52,8 +52,10 @@ class Test_Files_Sharing_Updater extends OCA\Files_Sharing\Tests\TestCase {
}
protected function tearDown() {
- $this->view->unlink($this->filename);
- $this->view->deleteAll($this->folder);
+ if ($this->view) {
+ $this->view->unlink($this->filename);
+ $this->view->deleteAll($this->folder);
+ }
parent::tearDown();
}
diff --git a/apps/files_sharing/tests/watcher.php b/apps/files_sharing/tests/watcher.php
index 021f10bacca..247fb59f351 100644
--- a/apps/files_sharing/tests/watcher.php
+++ b/apps/files_sharing/tests/watcher.php
@@ -88,13 +88,15 @@ class Test_Files_Sharing_Watcher extends OCA\Files_sharing\Tests\TestCase {
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
- $fileinfo = $this->view->getFileInfo('container/shareddir');
- \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
- self::TEST_FILES_SHARING_API_USER2);
+ if ($this->view) {
+ $fileinfo = $this->view->getFileInfo('container/shareddir');
+ \OCP\Share::unshare('folder', $fileinfo['fileid'], \OCP\Share::SHARE_TYPE_USER,
+ self::TEST_FILES_SHARING_API_USER2);
- $this->view->deleteAll('container');
+ $this->view->deleteAll('container');
- $this->ownerCache->clear();
+ $this->ownerCache->clear();
+ }
parent::tearDown();
}
diff --git a/apps/files_versions/tests/versions.php b/apps/files_versions/tests/versions.php
index 74d6006cfd9..ac922b74b9f 100644
--- a/apps/files_versions/tests/versions.php
+++ b/apps/files_versions/tests/versions.php
@@ -86,10 +86,12 @@ class Test_Files_Versioning extends \Test\TestCase {
}
protected function tearDown() {
- $this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files/');
- $this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files/');
- $this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files_versions/');
- $this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files_versions/');
+ if ($this->rootView) {
+ $this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files/');
+ $this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files/');
+ $this->rootView->deleteAll(self::TEST_VERSIONS_USER . '/files_versions/');
+ $this->rootView->deleteAll(self::TEST_VERSIONS_USER2 . '/files_versions/');
+ }
\OC_Hook::clear();
diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php
index 7a976e18888..527c8b76e52 100644
--- a/lib/private/files/cache/cache.php
+++ b/lib/private/files/cache/cache.php
@@ -33,6 +33,8 @@
namespace OC\Files\Cache;
+use OCP\Files\Cache\ICache;
+use OCP\Files\Cache\ICacheEntry;
use \OCP\Files\IMimeTypeLoader;
use OCP\IDBConnection;
@@ -46,12 +48,7 @@ use OCP\IDBConnection;
* - Updater: listens to changes made to the filesystem inside of the ownCloud instance and updates the cache where needed
* - ChangePropagator: updates the mtime and etags of parent folders whenever a change to the cache is made to the cache by the updater
*/
-class Cache {
- const NOT_FOUND = 0;
- const PARTIAL = 1; //only partial data available, file not cached in the database
- const SHALLOW = 2; //folder in cache, but not all child files are completely scanned
- const COMPLETE = 3;
-
+class Cache implements ICache {
/**
* @var array partial data for the cache
*/
@@ -105,28 +102,8 @@ class Cache {
/**
* get the stored metadata of a file or folder
*
- * the returned cache entry contains at least the following values:
- * [
- * 'fileid' => int, the numeric id of a file (see getId)
- * 'storage' => int, the numeric id of the storage the file is stored on
- * 'path' => string, the path of the file within the storage ('foo/bar.txt')
- * 'name' => string, the basename of a file ('bar.txt)
- * 'mimetype' => string, the full mimetype of the file ('text/plain')
- * 'mimepart' => string, the first half of the mimetype ('text')
- * 'size' => int, the size of the file or folder in bytes
- * 'mtime' => int, the last modified date of the file as unix timestamp as shown in the ui
- * 'storage_mtime' => int, the last modified date of the file as unix timestamp as stored on the storage
- * Note that when a file is updated we also update the mtime of all parent folders to make it visible to the user which folder has had updates most recently
- * This can differ from the mtime on the underlying storage which usually only changes when a direct child is added, removed or renamed
- * 'etag' => string, the etag for the file
- * An etag is used for change detection of files and folders, an etag of a file changes whenever the content of the file changes
- * Etag for folders change whenever a file in the folder has changed
- * 'permissions' int, the permissions for the file stored as bitwise combination of \OCP\PERMISSION_READ, \OCP\PERMISSION_CREATE
- * \OCP\PERMISSION_UPDATE, \OCP\PERMISSION_DELETE and \OCP\PERMISSION_SHARE
- * ]
- *
* @param string | int $file either the path of a file or folder or the file id for a file or folder
- * @return array|false the cache entry as array of false if the file is not found in the cache
+ * @return ICacheEntry|false the cache entry as array of false if the file is not found in the cache
*/
public function get($file) {
if (is_string($file) or $file == '') {
@@ -156,6 +133,7 @@ class Cache {
if (isset($this->partial[$file])) {
$data = $this->partial[$file];
}
+ return $data;
} else {
//fix types
$data['fileid'] = (int)$data['fileid'];
@@ -171,16 +149,15 @@ class Cache {
$data['storage_mtime'] = $data['mtime'];
}
$data['permissions'] = (int)$data['permissions'];
+ return new CacheEntry($data);
}
-
- return $data;
}
/**
* get the metadata of all files stored in $folder
*
* @param string $folder
- * @return array
+ * @return ICacheEntry[]
*/
public function getFolderContents($folder) {
$fileId = $this->getId($folder);
@@ -191,7 +168,7 @@ class Cache {
* get the metadata of all files stored in $folder
*
* @param int $fileId the file id of the folder
- * @return array
+ * @return ICacheEntry[]
*/
public function getFolderContentsById($fileId) {
if ($fileId > -1) {
@@ -211,7 +188,9 @@ class Cache {
$file['storage_mtime'] = (int)$file['storage_mtime'];
$file['size'] = 0 + $file['size'];
}
- return $files;
+ return array_map(function (array $data) {
+ return new CacheEntry($data);
+ }, $files);
} else {
return array();
}
@@ -392,7 +371,7 @@ class Cache {
return -1;
} else {
$parent = $this->getParentPath($file);
- return (int) $this->getId($parent);
+ return (int)$this->getId($parent);
}
}
@@ -481,12 +460,12 @@ class Cache {
/**
* Move a file or folder in the cache
*
- * @param \OC\Files\Cache\Cache $sourceCache
+ * @param \OCP\Files\Cache\ICache $sourceCache
* @param string $sourcePath
* @param string $targetPath
* @throws \OC\DatabaseException
*/
- public function moveFromCache(Cache $sourceCache, $sourcePath, $targetPath) {
+ public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
// normalize source and target
$sourcePath = $this->normalize($sourcePath);
$targetPath = $this->normalize($targetPath);
@@ -571,7 +550,7 @@ class Cache {
* search for files matching $pattern
*
* @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
- * @return array an array of cache entries where the name matches the search pattern
+ * @return ICacheEntry[] an array of cache entries where the name matches the search pattern
*/
public function search($pattern) {
// normalize pattern
@@ -594,7 +573,9 @@ class Cache {
$row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']);
$files[] = $row;
}
- return $files;
+ return array_map(function(array $data) {
+ return new CacheEntry($data);
+ }, $files);
}
/**
@@ -602,7 +583,7 @@ class Cache {
*
* @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image')
* where it will search for all mimetypes in the group ('image/*')
- * @return array an array of cache entries where the mimetype matches the search
+ * @return ICacheEntry[] an array of cache entries where the mimetype matches the search
*/
public function searchByMime($mimetype) {
if (strpos($mimetype, '/')) {
@@ -620,7 +601,9 @@ class Cache {
$row['mimepart'] = $this->mimetypeLoader->getMimetypeById($row['mimepart']);
$files[] = $row;
}
- return $files;
+ return array_map(function (array $data) {
+ return new CacheEntry($data);
+ }, $files);
}
/**
@@ -630,7 +613,7 @@ class Cache {
*
* @param string|int $tag name or tag id
* @param string $userId owner of the tags
- * @return array file data
+ * @return ICacheEntry[] file data
*/
public function searchByTag($tag, $userId) {
$sql = 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, ' .
@@ -665,7 +648,9 @@ class Cache {
while ($row = $result->fetch()) {
$files[] = $row;
}
- return $files;
+ return array_map(function (array $data) {
+ return new CacheEntry($data);
+ }, $files);
}
/**
diff --git a/lib/private/files/cache/cacheentry.php b/lib/private/files/cache/cacheentry.php
new file mode 100644
index 00000000000..3db3b3f8aa0
--- /dev/null
+++ b/lib/private/files/cache/cacheentry.php
@@ -0,0 +1,114 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Files\Cache;
+
+use OCP\Files\Cache\ICacheEntry;
+
+/**
+ * meta data for a file or folder
+ */
+class CacheEntry implements ICacheEntry, \ArrayAccess {
+ /**
+ * @var array
+ */
+ private $data;
+
+ public function __construct(array $data) {
+ $this->data = $data;
+ }
+
+ public function offsetSet($offset, $value) {
+ $this->data[$offset] = $value;
+ }
+
+ public function offsetExists($offset) {
+ return isset($this->data[$offset]);
+ }
+
+ public function offsetUnset($offset) {
+ unset($this->data[$offset]);
+ }
+
+ public function offsetGet($offset) {
+ if (isset($this->data[$offset])) {
+ return $this->data[$offset];
+ } else {
+ return null;
+ }
+ }
+
+ public function getId() {
+ return (int)$this->data['fileid'];
+ }
+
+ public function getStorageId() {
+ return $this->data['storage'];
+ }
+
+
+ public function getPath() {
+ return $this->data['path'];
+ }
+
+
+ public function getName() {
+ return $this->data['name'];
+ }
+
+
+ public function getMimeType() {
+ return $this->data['mimetype'];
+ }
+
+
+ public function getMimePart() {
+ return $this->data['mimepart'];
+ }
+
+ public function getSize() {
+ return $this->data['size'];
+ }
+
+ public function getMTime() {
+ return $this->data['mtime'];
+ }
+
+ public function getStorageMTime() {
+ return $this->data['storage_mtime'];
+ }
+
+ public function getEtag() {
+ return $this->data['etag'];
+ }
+
+ public function getPermissions() {
+ return $this->data['permissions'];
+ }
+
+ public function isEncrypted() {
+ return isset($this->data['encrypted']) && $this->data['encrypted'];
+ }
+
+ public function getData() {
+ return $this->data;
+ }
+}
diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php
index 693896fccfb..ae92504ddd6 100644
--- a/lib/private/files/cache/homecache.php
+++ b/lib/private/files/cache/homecache.php
@@ -26,6 +26,8 @@
namespace OC\Files\Cache;
+use OCP\Files\Cache\ICacheEntry;
+
class HomeCache extends Cache {
/**
* get the size of a folder and set it in the cache
@@ -67,7 +69,7 @@ class HomeCache extends Cache {
/**
* @param string $path
- * @return array
+ * @return ICacheEntry
*/
public function get($path) {
$data = parent::get($path);
diff --git a/lib/private/files/cache/propagator.php b/lib/private/files/cache/propagator.php
index 56abcdadee2..1e85a2ecc8b 100644
--- a/lib/private/files/cache/propagator.php
+++ b/lib/private/files/cache/propagator.php
@@ -21,10 +21,12 @@
namespace OC\Files\Cache;
+use OCP\Files\Cache\IPropagator;
+
/**
* Propagate etags and mtimes within the storage
*/
-class Propagator {
+class Propagator implements IPropagator {
/**
* @var \OC\Files\Storage\Storage
*/
@@ -41,7 +43,7 @@ class Propagator {
/**
* @param string $internalPath
* @param int $time
- * @return array[] all propagated entries
+ * @return array[] all propagated cache entries
*/
public function propagateChange($internalPath, $time) {
$cache = $this->storage->getCache($internalPath);
diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php
index 79f749394f1..743b50f54a9 100644
--- a/lib/private/files/cache/scanner.php
+++ b/lib/private/files/cache/scanner.php
@@ -37,6 +37,8 @@ namespace OC\Files\Cache;
use OC\Files\Filesystem;
use OC\Hooks\BasicEmitter;
use OCP\Config;
+use OCP\Files\Cache\IScanner;
+use OCP\Files\Storage\ILockingStorage;
use OCP\Lock\ILockingProvider;
/**
@@ -50,7 +52,7 @@ use OCP\Lock\ILockingProvider;
*
* @package OC\Files\Cache
*/
-class Scanner extends BasicEmitter {
+class Scanner extends BasicEmitter implements IScanner {
/**
* @var \OC\Files\Storage\Storage $storage
*/
@@ -81,12 +83,6 @@ class Scanner extends BasicEmitter {
*/
protected $lockingProvider;
- const SCAN_RECURSIVE = true;
- const SCAN_SHALLOW = false;
-
- const REUSE_ETAG = 1;
- const REUSE_SIZE = 2;
-
public function __construct(\OC\Files\Storage\Storage $storage) {
$this->storage = $storage;
$this->storageId = $this->storage->getId();
@@ -112,7 +108,7 @@ class Scanner extends BasicEmitter {
* @param string $path
* @return array an array of metadata of the file
*/
- public function getData($path) {
+ protected function getData($path) {
$data = $this->storage->getMetaData($path);
if (is_null($data)) {
\OCP\Util::writeLog('OC\Files\Cache\Scanner', "!!! Path '$path' is not accessible or present !!!", \OCP\Util::DEBUG);
@@ -137,7 +133,9 @@ class Scanner extends BasicEmitter {
and !Filesystem::isFileBlacklisted($file)
) {
if ($lock) {
- $this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->acquireLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ }
}
$this->emit('\OC\Files\Cache\Scanner', 'scanFile', array($file, $this->storageId));
\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
@@ -160,6 +158,7 @@ class Scanner extends BasicEmitter {
$data['parent'] = $parentId;
}
if (is_null($cacheData)) {
+ /** @var CacheEntry $cacheData */
$cacheData = $this->cache->get($file);
}
if ($cacheData and $reuseExisting and isset($cacheData['fileid'])) {
@@ -182,7 +181,7 @@ class Scanner extends BasicEmitter {
}
}
// Only update metadata that has changed
- $newData = array_diff_assoc($data, $cacheData);
+ $newData = array_diff_assoc($data, $cacheData->getData());
} else {
$newData = $data;
$fileId = -1;
@@ -196,7 +195,9 @@ class Scanner extends BasicEmitter {
$this->removeFromCache($file);
}
if ($lock) {
- $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->releaseLock($file, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ }
}
return $data;
}
@@ -263,7 +264,9 @@ class Scanner extends BasicEmitter {
$reuse = ($recursive === self::SCAN_SHALLOW) ? self::REUSE_ETAG | self::REUSE_SIZE : self::REUSE_ETAG;
}
if ($lock) {
- $this->storage->acquireLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->acquireLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ }
}
$data = $this->scanFile($path, $reuse, -1, null, $lock);
if ($data and $data['mimetype'] === 'httpd/unix-directory') {
@@ -271,7 +274,9 @@ class Scanner extends BasicEmitter {
$data['size'] = $size;
}
if ($lock) {
- $this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->releaseLock($path, ILockingProvider::LOCK_SHARED, $this->lockingProvider);
+ }
}
return $data;
}
diff --git a/lib/private/files/cache/updater.php b/lib/private/files/cache/updater.php
index c5b1e7de32e..58d8e53cfd1 100644
--- a/lib/private/files/cache/updater.php
+++ b/lib/private/files/cache/updater.php
@@ -24,12 +24,14 @@
*/
namespace OC\Files\Cache;
+use OCP\Files\Cache\IUpdater;
+use OCP\Files\Storage\IStorage;
/**
* Update the cache and propagate changes
*
*/
-class Updater {
+class Updater implements IUpdater {
/**
* @var bool
*/
@@ -145,18 +147,18 @@ class Updater {
/**
* Rename a file or folder in the cache and update the size, etag and mtime of the parent folders
*
- * @param \OC\Files\Storage\Storage $sourceStorage
+ * @param IStorage $sourceStorage
* @param string $source
* @param string $target
*/
- public function renameFromStorage(\OC\Files\Storage\Storage $sourceStorage, $source, $target) {
+ public function renameFromStorage(IStorage $sourceStorage, $source, $target) {
if (!$this->enabled or Scanner::isPartialFile($source) or Scanner::isPartialFile($target)) {
return;
}
$time = time();
- $sourceCache = $sourceStorage->getCache($source);
+ $sourceCache = $sourceStorage->getCache();
$sourceUpdater = $sourceStorage->getUpdater();
$sourcePropagator = $sourceStorage->getPropagator();
@@ -181,7 +183,9 @@ class Updater {
$sourceCache->correctFolderSize($source);
$this->cache->correctFolderSize($target);
- $sourceUpdater->correctParentStorageMtime($source);
+ if ($sourceUpdater instanceof Updater) {
+ $sourceUpdater->correctParentStorageMtime($source);
+ }
$this->correctParentStorageMtime($target);
$this->updateStorageMTimeOnly($target);
$sourcePropagator->propagateChange($source, $time);
@@ -205,7 +209,7 @@ class Updater {
*
* @param string $internalPath
*/
- public function correctParentStorageMtime($internalPath) {
+ private function correctParentStorageMtime($internalPath) {
$parentId = $this->cache->getParentId($internalPath);
$parent = dirname($internalPath);
if ($parentId != -1) {
diff --git a/lib/private/files/cache/watcher.php b/lib/private/files/cache/watcher.php
index bb80dcbd80c..a00e875a2d4 100644
--- a/lib/private/files/cache/watcher.php
+++ b/lib/private/files/cache/watcher.php
@@ -22,14 +22,13 @@
*/
namespace OC\Files\Cache;
+use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\Cache\IWatcher;
/**
* check the storage backends for updates and change the cache accordingly
*/
-class Watcher {
- const CHECK_NEVER = 0; // never check the underlying filesystem for updates
- const CHECK_ONCE = 1; // check the underlying filesystem for updates once every request for each file
- const CHECK_ALWAYS = 2; // always check the underlying filesystem for updates
+class Watcher implements IWatcher {
protected $watchPolicy = self::CHECK_ONCE;
@@ -77,7 +76,7 @@ class Watcher {
* check $path for updates and update if needed
*
* @param string $path
- * @param array $cachedEntry
+ * @param ICacheEntry|null $cachedEntry
* @return boolean true if path was updated
*/
public function checkUpdate($path, $cachedEntry = null) {
@@ -96,7 +95,7 @@ class Watcher {
* Update the cache for changes to $path
*
* @param string $path
- * @param array $cachedData
+ * @param ICacheEntry $cachedData
*/
public function update($path, $cachedData) {
if ($this->storage->is_dir($path)) {
@@ -114,7 +113,7 @@ class Watcher {
* Check if the cache for $path needs to be updated
*
* @param string $path
- * @param array $cachedData
+ * @param ICacheEntry $cachedData
* @return bool
*/
public function needsUpdate($path, $cachedData) {
diff --git a/lib/private/files/cache/wrapper/cachewrapper.php b/lib/private/files/cache/wrapper/cachewrapper.php
index f401b7482eb..39a6b63205b 100644
--- a/lib/private/files/cache/wrapper/cachewrapper.php
+++ b/lib/private/files/cache/wrapper/cachewrapper.php
@@ -25,6 +25,7 @@
namespace OC\Files\Cache\Wrapper;
use OC\Files\Cache\Cache;
+use OCP\Files\Cache\ICacheEntry;
class CacheWrapper extends Cache {
/**
@@ -42,8 +43,8 @@ class CacheWrapper extends Cache {
/**
* Make it easy for wrappers to modify every returned cache entry
*
- * @param array $entry
- * @return array
+ * @param ICacheEntry $entry
+ * @return ICacheEntry
*/
protected function formatCacheEntry($entry) {
return $entry;
@@ -53,7 +54,7 @@ class CacheWrapper extends Cache {
* get the stored metadata of a file or folder
*
* @param string /int $file
- * @return array|false
+ * @return ICacheEntry|false
*/
public function get($file) {
$result = $this->cache->get($file);
@@ -67,7 +68,7 @@ class CacheWrapper extends Cache {
* get the metadata of all files stored in $folder
*
* @param string $folder
- * @return array
+ * @return ICacheEntry[]
*/
public function getFolderContents($folder) {
// cant do a simple $this->cache->.... call here since getFolderContentsById needs to be called on this
@@ -178,7 +179,7 @@ class CacheWrapper extends Cache {
* search for files matching $pattern
*
* @param string $pattern
- * @return array an array of file data
+ * @return ICacheEntry[] an array of file data
*/
public function search($pattern) {
$results = $this->cache->search($pattern);
@@ -189,7 +190,7 @@ class CacheWrapper extends Cache {
* search for files by mimetype
*
* @param string $mimetype
- * @return array
+ * @return ICacheEntry[]
*/
public function searchByMime($mimetype) {
$results = $this->cache->searchByMime($mimetype);
@@ -201,7 +202,7 @@ class CacheWrapper extends Cache {
*
* @param string|int $tag name or tag id
* @param string $userId owner of the tags
- * @return array file data
+ * @return ICacheEntry[] file data
*/
public function searchByTag($tag, $userId) {
$results = $this->cache->searchByTag($tag, $userId);
diff --git a/lib/private/files/fileinfo.php b/lib/private/files/fileinfo.php
index 3e5e894eed4..1e6fe474f7b 100644
--- a/lib/private/files/fileinfo.php
+++ b/lib/private/files/fileinfo.php
@@ -29,6 +29,7 @@
namespace OC\Files;
+use OCP\Files\Cache\ICacheEntry;
use OCP\IUser;
class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
@@ -71,7 +72,7 @@ class FileInfo implements \OCP\Files\FileInfo, \ArrayAccess {
* @param string|boolean $path
* @param Storage\Storage $storage
* @param string $internalPath
- * @param array $data
+ * @param array|ICacheEntry $data
* @param \OCP\Files\Mount\IMountPoint $mount
* @param \OCP\IUser|null $owner
*/
diff --git a/lib/private/files/objectstore/objectstorestorage.php b/lib/private/files/objectstore/objectstorestorage.php
index 9cea07b7f69..35c2c19c75b 100644
--- a/lib/private/files/objectstore/objectstorestorage.php
+++ b/lib/private/files/objectstore/objectstorestorage.php
@@ -25,6 +25,7 @@
namespace OC\Files\ObjectStore;
use Icewind\Streams\IteratorDirectory;
+use OC\Files\Cache\CacheEntry;
use OCP\Files\ObjectStore\IObjectStore;
class ObjectStoreStorage extends \OC\Files\Storage\Common {
@@ -192,7 +193,12 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common {
public function stat($path) {
$path = $this->normalizePath($path);
- return $this->getCache()->get($path);
+ $cacheEntry = $this->getCache()->get($path);
+ if ($cacheEntry instanceof CacheEntry) {
+ return $cacheEntry->getData();
+ } else {
+ return false;
+ }
}
/**
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index c27f9d759f1..95bb3f74ba7 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -46,6 +46,7 @@ use OCP\Files\FileNameTooLongException;
use OCP\Files\InvalidCharacterInPathException;
use OCP\Files\InvalidPathException;
use OCP\Files\ReservedWordException;
+use OCP\Files\Storage\ILockingStorage;
use OCP\Lock\ILockingProvider;
/**
@@ -59,7 +60,7 @@ use OCP\Lock\ILockingProvider;
* Some \OC\Files\Storage\Common methods call functions which are first defined
* in classes which extend it, e.g. $this->stat() .
*/
-abstract class Common implements Storage {
+abstract class Common implements Storage, ILockingStorage {
use LocalTempFileTrait;
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index fda28079d0f..69438ef0c7c 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -28,6 +28,7 @@ namespace OC\Files\Storage\Wrapper;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
use OC\Encryption\Update;
use OC\Encryption\Util;
+use OC\Files\Cache\CacheEntry;
use OC\Files\Filesystem;
use OC\Files\Mount\Manager;
use OC\Files\Storage\LocalTempFileTrait;
@@ -123,13 +124,14 @@ class Encryption extends Wrapper {
public function filesize($path) {
$fullPath = $this->getFullPath($path);
+ /** @var CacheEntry $info */
$info = $this->getCache()->get($path);
if (isset($this->unencryptedSize[$fullPath])) {
$size = $this->unencryptedSize[$fullPath];
// update file cache
$info['encrypted'] = true;
$info['size'] = $size;
- $this->getCache()->put($path, $info);
+ $this->getCache()->put($path, $info->getData());
return $size;
}
diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php
index 55c826092c1..844505679df 100644
--- a/lib/private/files/storage/wrapper/quota.php
+++ b/lib/private/files/storage/wrapper/quota.php
@@ -25,6 +25,8 @@
namespace OC\Files\Storage\Wrapper;
+use OCP\Files\Cache\ICacheEntry;
+
class Quota extends Wrapper {
/**
@@ -64,7 +66,7 @@ class Quota extends Wrapper {
$cache = $storage->getCache();
}
$data = $cache->get($path);
- if (is_array($data) and isset($data['size'])) {
+ if ($data instanceof ICacheEntry and isset($data['size'])) {
return $data['size'];
} else {
return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED;
diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php
index 472c60b5faa..c632aa399e1 100644
--- a/lib/private/files/storage/wrapper/wrapper.php
+++ b/lib/private/files/storage/wrapper/wrapper.php
@@ -26,9 +26,10 @@
namespace OC\Files\Storage\Wrapper;
use OCP\Files\InvalidPathException;
+use OCP\Files\Storage\ILockingStorage;
use OCP\Lock\ILockingProvider;
-class Wrapper implements \OC\Files\Storage\Storage {
+class Wrapper implements \OC\Files\Storage\Storage, ILockingStorage {
/**
* @var \OC\Files\Storage\Storage $storage
*/
@@ -583,7 +584,9 @@ class Wrapper implements \OC\Files\Storage\Storage {
* @throws \OCP\Lock\LockedException
*/
public function acquireLock($path, $type, ILockingProvider $provider) {
- $this->storage->acquireLock($path, $type, $provider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->acquireLock($path, $type, $provider);
+ }
}
/**
@@ -592,7 +595,9 @@ class Wrapper implements \OC\Files\Storage\Storage {
* @param \OCP\Lock\ILockingProvider $provider
*/
public function releaseLock($path, $type, ILockingProvider $provider) {
- $this->storage->releaseLock($path, $type, $provider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->releaseLock($path, $type, $provider);
+ }
}
/**
@@ -601,6 +606,8 @@ class Wrapper implements \OC\Files\Storage\Storage {
* @param \OCP\Lock\ILockingProvider $provider
*/
public function changeLock($path, $type, ILockingProvider $provider) {
- $this->storage->changeLock($path, $type, $provider);
+ if ($this->storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $this->storage->changeLock($path, $type, $provider);
+ }
}
}
diff --git a/lib/private/files/view.php b/lib/private/files/view.php
index 7b0f1d37255..55b8da165e1 100644
--- a/lib/private/files/view.php
+++ b/lib/private/files/view.php
@@ -43,15 +43,16 @@
namespace OC\Files;
use Icewind\Streams\CallbackWrapper;
-use OC\Files\Cache\Updater;
use OC\Files\Mount\MoveableMount;
use OC\Files\Storage\Storage;
use OC\User\User;
+use OCP\Files\Cache\ICacheEntry;
use OCP\Files\FileNameTooLongException;
use OCP\Files\InvalidCharacterInPathException;
use OCP\Files\InvalidPathException;
use OCP\Files\NotFoundException;
use OCP\Files\ReservedWordException;
+use OCP\Files\Storage\ILockingStorage;
use OCP\IUser;
use OCP\Lock\ILockingProvider;
use OCP\Lock\LockedException;
@@ -1274,7 +1275,7 @@ class View {
if ($storage) {
$data = $this->getCacheEntry($storage, $internalPath, $relativePath);
- if (!is_array($data)) {
+ if (!$data instanceof ICacheEntry) {
return false;
}
@@ -1334,7 +1335,7 @@ class View {
$data = $this->getCacheEntry($storage, $internalPath, $directory);
- if (!is_array($data) || !isset($data['fileid'])) {
+ if (!$data instanceof ICacheEntry || !isset($data['fileid'])) {
return [];
}
@@ -1345,7 +1346,7 @@ class View {
/**
* @var \OC\Files\FileInfo[] $files
*/
- $files = array_map(function (array $content) use ($path, $storage, $mount, $sharingDisabled) {
+ $files = array_map(function (ICacheEntry $content) use ($path, $storage, $mount, $sharingDisabled) {
if ($sharingDisabled) {
$content['permissions'] = $content['permissions'] & ~\OCP\Constants::PERMISSION_SHARE;
}
@@ -1834,11 +1835,14 @@ class View {
$mount = $this->getMountForLock($absolutePath, $lockMountPoint);
if ($mount) {
try {
- $mount->getStorage()->acquireLock(
- $mount->getInternalPath($absolutePath),
- $type,
- $this->lockingProvider
- );
+ $storage = $mount->getStorage();
+ if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $storage->acquireLock(
+ $mount->getInternalPath($absolutePath),
+ $type,
+ $this->lockingProvider
+ );
+ }
} catch (\OCP\Lock\LockedException $e) {
// rethrow with the a human-readable path
throw new \OCP\Lock\LockedException(
@@ -1872,11 +1876,14 @@ class View {
$mount = $this->getMountForLock($absolutePath, $lockMountPoint);
if ($mount) {
try {
- $mount->getStorage()->changeLock(
- $mount->getInternalPath($absolutePath),
- $type,
- $this->lockingProvider
- );
+ $storage = $mount->getStorage();
+ if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $storage->changeLock(
+ $mount->getInternalPath($absolutePath),
+ $type,
+ $this->lockingProvider
+ );
+ }
} catch (\OCP\Lock\LockedException $e) {
// rethrow with the a human-readable path
throw new \OCP\Lock\LockedException(
@@ -1907,11 +1914,14 @@ class View {
$mount = $this->getMountForLock($absolutePath, $lockMountPoint);
if ($mount) {
- $mount->getStorage()->releaseLock(
- $mount->getInternalPath($absolutePath),
- $type,
- $this->lockingProvider
- );
+ $storage = $mount->getStorage();
+ if ($storage->instanceOfStorage('\OCP\Files\Storage\ILockingStorage')) {
+ $storage->releaseLock(
+ $mount->getInternalPath($absolutePath),
+ $type,
+ $this->lockingProvider
+ );
+ }
}
return true;
diff --git a/lib/public/files/cache/icache.php b/lib/public/files/cache/icache.php
new file mode 100644
index 00000000000..07396db4588
--- /dev/null
+++ b/lib/public/files/cache/icache.php
@@ -0,0 +1,249 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Cache;
+
+/**
+ * Metadata cache for a storage
+ *
+ * The cache stores the metadata for all files and folders in a storage and is kept up to date trough the following mechanisms:
+ *
+ * - Scanner: scans the storage and updates the cache where needed
+ * - Watcher: checks for changes made to the filesystem outside of the ownCloud instance and rescans files and folder when a change is detected
+ * - Updater: listens to changes made to the filesystem inside of the ownCloud instance and updates the cache where needed
+ * - ChangePropagator: updates the mtime and etags of parent folders whenever a change to the cache is made to the cache by the updater
+ *
+ * @since 9.0.0
+ */
+interface ICache {
+ const NOT_FOUND = 0;
+ const PARTIAL = 1; //only partial data available, file not cached in the database
+ const SHALLOW = 2; //folder in cache, but not all child files are completely scanned
+ const COMPLETE = 3;
+
+ /**
+ * Get the numeric storage id for this cache's storage
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getNumericStorageId();
+
+ /**
+ * get the stored metadata of a file or folder
+ *
+ * @param string | int $file either the path of a file or folder or the file id for a file or folder
+ * @return ICacheEntry[]|false the cache entry or false if the file is not found in the cache
+ * @since 9.0.0
+ */
+ public function get($file);
+
+ /**
+ * get the metadata of all files stored in $folder
+ *
+ * @param string $folder
+ * @return ICacheEntry[]
+ * @since 9.0.0
+ */
+ public function getFolderContents($folder);
+
+ /**
+ * get the metadata of all files stored in $folder
+ *
+ * @param int $fileId the file id of the folder
+ * @return ICacheEntry[]
+ * @since 9.0.0
+ */
+ public function getFolderContentsById($fileId);
+
+ /**
+ * store meta data for a file or folder
+ *
+ * @param string $file
+ * @param array $data
+ *
+ * @return int file id
+ * @throws \RuntimeException
+ * @since 9.0.0
+ */
+ public function put($file, array $data);
+
+ /**
+ * update the metadata of an existing file or folder in the cache
+ *
+ * @param int $id the fileid of the existing file or folder
+ * @param array $data [$key => $value] the metadata to update, only the fields provided in the array will be updated, non-provided values will remain unchanged
+ * @since 9.0.0
+ */
+ public function update($id, array $data);
+
+ /**
+ * get the file id for a file
+ *
+ * A file id is a numeric id for a file or folder that's unique within an owncloud instance which stays the same for the lifetime of a file
+ *
+ * File ids are easiest way for apps to store references to a file since unlike paths they are not affected by renames or sharing
+ *
+ * @param string $file
+ * @return int
+ * @since 9.0.0
+ */
+ public function getId($file);
+
+ /**
+ * get the id of the parent folder of a file
+ *
+ * @param string $file
+ * @return int
+ * @since 9.0.0
+ */
+ public function getParentId($file);
+
+ /**
+ * check if a file is available in the cache
+ *
+ * @param string $file
+ * @return bool
+ * @since 9.0.0
+ */
+ public function inCache($file);
+
+ /**
+ * remove a file or folder from the cache
+ *
+ * when removing a folder from the cache all files and folders inside the folder will be removed as well
+ *
+ * @param string $file
+ * @since 9.0.0
+ */
+ public function remove($file);
+
+ /**
+ * Move a file or folder in the cache
+ *
+ * @param string $source
+ * @param string $target
+ * @since 9.0.0
+ */
+ public function move($source, $target);
+
+ /**
+ * Move a file or folder in the cache
+ *
+ * @param \OCP\Files\Cache\ICache $sourceCache
+ * @param string $sourcePath
+ * @param string $targetPath
+ * @throws \OC\DatabaseException
+ * @since 9.0.0
+ */
+ public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath);
+
+ /**
+ * remove all entries for files that are stored on the storage from the cache
+ *
+ * @since 9.0.0
+ */
+ public function clear();
+
+ /**
+ * Get the scan status of a file
+ *
+ * - ICache::NOT_FOUND: File is not in the cache
+ * - ICache::PARTIAL: File is not stored in the cache but some incomplete data is known
+ * - ICache::SHALLOW: The folder and it's direct children are in the cache but not all sub folders are fully scanned
+ * - ICache::COMPLETE: The file or folder, with all it's children) are fully scanned
+ *
+ * @param string $file
+ *
+ * @return int ICache::NOT_FOUND, ICache::PARTIAL, ICache::SHALLOW or ICache::COMPLETE
+ * @since 9.0.0
+ */
+ public function getStatus($file);
+
+ /**
+ * search for files matching $pattern
+ *
+ * @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%')
+ * @return ICacheEntry[] an array of cache entries where the name matches the search pattern
+ * @since 9.0.0
+ */
+ public function search($pattern);
+
+ /**
+ * search for files by mimetype
+ *
+ * @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image')
+ * where it will search for all mimetypes in the group ('image/*')
+ * @return ICacheEntry[] an array of cache entries where the mimetype matches the search
+ * @since 9.0.0
+ */
+ public function searchByMime($mimetype);
+
+ /**
+ * Search for files by tag of a given users.
+ *
+ * Note that every user can tag files differently.
+ *
+ * @param string|int $tag name or tag id
+ * @param string $userId owner of the tags
+ * @return ICacheEntry[] file data
+ * @since 9.0.0
+ */
+ public function searchByTag($tag, $userId);
+
+ /**
+ * get all file ids on the files on the storage
+ *
+ * @return int[]
+ * @since 9.0.0
+ */
+ public function getAll();
+
+ /**
+ * find a folder in the cache which has not been fully scanned
+ *
+ * If multiple incomplete folders are in the cache, the one with the highest id will be returned,
+ * use the one with the highest id gives the best result with the background scanner, since that is most
+ * likely the folder where we stopped scanning previously
+ *
+ * @return string|bool the path of the folder or false when no folder matched
+ * @since 9.0.0
+ */
+ public function getIncomplete();
+
+ /**
+ * get the path of a file on this storage by it's file id
+ *
+ * @param int $id the file id of the file or folder to search
+ * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache
+ * @since 9.0.0
+ */
+ public function getPathById($id);
+
+ /**
+ * normalize the given path for usage in the cache
+ *
+ * @param string $path
+ * @return string
+ * @since 9.0.0
+ */
+ public function normalize($path);
+}
diff --git a/lib/public/files/cache/icacheentry.php b/lib/public/files/cache/icacheentry.php
new file mode 100644
index 00000000000..8d14bd2c555
--- /dev/null
+++ b/lib/public/files/cache/icacheentry.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Cache;
+
+/**
+ * meta data for a file or folder
+ *
+ * @since 9.0.0
+ */
+interface ICacheEntry {
+ /**
+ * Get the numeric id of a file
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getId();
+
+ /**
+ * Get the numeric id for the storage
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getStorageId();
+
+ /**
+ * Get the path of the file relative to the storage root
+ *
+ * @return string
+ * @since 9.0.0
+ */
+ public function getPath();
+
+ /**
+ * Get the file name
+ *
+ * @return string
+ * @since 9.0.0
+ */
+ public function getName();
+
+ /**
+ * Get the full mimetype
+ *
+ * @return string
+ * @since 9.0.0
+ */
+ public function getMimeType();
+
+ /**
+ * Get the first part of the mimetype
+ *
+ * @return string
+ * @since 9.0.0
+ */
+ public function getMimePart();
+
+ /**
+ * Get the file size in bytes
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getSize();
+
+ /**
+ * Get the last modified date as unix timestamp
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getMTime();
+
+ /**
+ * Get the last modified date on the storage as unix timestamp
+ *
+ * Note that when a file is updated we also update the mtime of all parent folders to make it visible to the user which folder has had updates most recently
+ * This can differ from the mtime on the underlying storage which usually only changes when a direct child is added, removed or renamed
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getStorageMTime();
+
+ /**
+ * Get the etag for the file
+ *
+ * An etag is used for change detection of files and folders, an etag of a file changes whenever the content of the file changes
+ * Etag for folders change whenever a file in the folder has changed
+ *
+ * @return string
+ * @since 9.0.0
+ */
+ public function getEtag();
+
+ /**
+ * Get the permissions for the file stored as bitwise combination of \OCP\PERMISSION_READ, \OCP\PERMISSION_CREATE
+ * \OCP\PERMISSION_UPDATE, \OCP\PERMISSION_DELETE and \OCP\PERMISSION_SHARE
+ *
+ * @return int
+ * @since 9.0.0
+ */
+ public function getPermissions();
+
+ /**
+ * Check if the file is encrypted
+ *
+ * @return bool
+ * @since 9.0.0
+ */
+ public function isEncrypted();
+}
diff --git a/lib/public/files/cache/ipropagator.php b/lib/public/files/cache/ipropagator.php
new file mode 100644
index 00000000000..7f7dbada532
--- /dev/null
+++ b/lib/public/files/cache/ipropagator.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Cache;
+
+/**
+ * Propagate etags and mtimes within the storage
+ *
+ * @since 9.0.0
+ */
+interface IPropagator {
+ /**
+ * @param string $internalPath
+ * @param int $time
+ * @return array[] all propagated cache entries
+ * @since 9.0.0
+ */
+ public function propagateChange($internalPath, $time);
+}
diff --git a/lib/public/files/cache/iscanner.php b/lib/public/files/cache/iscanner.php
new file mode 100644
index 00000000000..47e33a98bae
--- /dev/null
+++ b/lib/public/files/cache/iscanner.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Cache;
+
+/**
+ * Scan files from the storage and save to the cache
+ *
+ * @since 9.0.0
+ */
+interface IScanner {
+ const SCAN_RECURSIVE = true;
+ const SCAN_SHALLOW = false;
+
+ const REUSE_ETAG = 1;
+ const REUSE_SIZE = 2;
+
+ /**
+ * scan a single file and store it in the cache
+ *
+ * @param string $file
+ * @param int $reuseExisting
+ * @param int $parentId
+ * @param array | null $cacheData existing data in the cache for the file to be scanned
+ * @param bool $lock set to false to disable getting an additional read lock during scanning
+ * @return array an array of metadata of the scanned file
+ * @throws \OC\ServerNotAvailableException
+ * @throws \OCP\Lock\LockedException
+ * @since 9.0.0
+ */
+ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData = null, $lock = true);
+
+ /**
+ * scan a folder and all its children
+ *
+ * @param string $path
+ * @param bool $recursive
+ * @param int $reuse
+ * @param bool $lock set to false to disable getting an additional read lock during scanning
+ * @return array an array of the meta data of the scanned file or folder
+ * @since 9.0.0
+ */
+ public function scan($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1, $lock = true);
+
+ /**
+ * check if the file should be ignored when scanning
+ * NOTE: files with a '.part' extension are ignored as well!
+ * prevents unfinished put requests to be scanned
+ *
+ * @param string $file
+ * @return boolean
+ * @since 9.0.0
+ */
+ public static function isPartialFile($file);
+
+ /**
+ * walk over any folders that are not fully scanned yet and scan them
+ *
+ * @since 9.0.0
+ */
+ public function backgroundScan();
+}
+
diff --git a/lib/public/files/cache/iupdater.php b/lib/public/files/cache/iupdater.php
new file mode 100644
index 00000000000..241cd8636a1
--- /dev/null
+++ b/lib/public/files/cache/iupdater.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Cache;
+
+use OCP\Files\Storage\IStorage;
+
+/**
+ * Update the cache and propagate changes
+ *
+ * @since 9.0.0
+ */
+interface IUpdater {
+ /**
+ * Get the propagator for etags and mtime for the view the updater works on
+ *
+ * @return IPropagator
+ * @since 9.0.0
+ */
+ public function getPropagator();
+
+ /**
+ * Propagate etag and mtime changes for the parent folders of $path up to the root of the filesystem
+ *
+ * @param string $path the path of the file to propagate the changes for
+ * @param int|null $time the timestamp to set as mtime for the parent folders, if left out the current time is used
+ * @since 9.0.0
+ */
+ public function propagate($path, $time = null);
+
+ /**
+ * Update the cache for $path and update the size, etag and mtime of the parent folders
+ *
+ * @param string $path
+ * @param int $time
+ * @since 9.0.0
+ */
+ public function update($path, $time = null);
+
+ /**
+ * Remove $path from the cache and update the size, etag and mtime of the parent folders
+ *
+ * @param string $path
+ * @since 9.0.0
+ */
+ public function remove($path);
+
+ /**
+ * Rename a file or folder in the cache and update the size, etag and mtime of the parent folders
+ *
+ * @param IStorage $sourceStorage
+ * @param string $source
+ * @param string $target
+ * @since 9.0.0
+ */
+ public function renameFromStorage(IStorage $sourceStorage, $source, $target);
+}
diff --git a/lib/public/files/cache/iwatcher.php b/lib/public/files/cache/iwatcher.php
new file mode 100644
index 00000000000..a61975036f8
--- /dev/null
+++ b/lib/public/files/cache/iwatcher.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Cache;
+
+/**
+ * check the storage backends for updates and change the cache accordingly
+ *
+ * @since 9.0.0
+ */
+interface IWatcher {
+ const CHECK_NEVER = 0; // never check the underlying filesystem for updates
+ const CHECK_ONCE = 1; // check the underlying filesystem for updates once every request for each file
+ const CHECK_ALWAYS = 2; // always check the underlying filesystem for updates
+
+ /**
+ * @param int $policy either IWatcher::CHECK_NEVER, IWatcher::CHECK_ONCE, IWatcher::CHECK_ALWAYS
+ * @since 9.0.0
+ */
+ public function setPolicy($policy);
+
+ /**
+ * @return int either IWatcher::CHECK_NEVER, IWatcher::CHECK_ONCE, IWatcher::CHECK_ALWAYS
+ * @since 9.0.0
+ */
+ public function getPolicy();
+
+ /**
+ * check $path for updates and update if needed
+ *
+ * @param string $path
+ * @param ICacheEntry|null $cachedEntry
+ * @return boolean true if path was updated
+ * @since 9.0.0
+ */
+ public function checkUpdate($path, $cachedEntry = null);
+
+ /**
+ * Update the cache for changes to $path
+ *
+ * @param string $path
+ * @param ICacheEntry $cachedData
+ * @since 9.0.0
+ */
+ public function update($path, $cachedData);
+
+ /**
+ * Check if the cache for $path needs to be updated
+ *
+ * @param string $path
+ * @param ICacheEntry $cachedData
+ * @return bool
+ * @since 9.0.0
+ */
+ public function needsUpdate($path, $cachedData);
+
+ /**
+ * remove deleted files in $path from the cache
+ *
+ * @param string $path
+ * @since 9.0.0
+ */
+ public function cleanFolder($path);
+}
diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php
index f6f5081abaa..1c125221449 100644
--- a/lib/public/files/storage.php
+++ b/lib/public/files/storage.php
@@ -33,16 +33,19 @@
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP\Files;
-use OCP\Files\InvalidPathException;
+
+use OCP\Files\Storage\IStorage;
use OCP\Lock\ILockingProvider;
/**
* Provide a common interface to all different storage options
*
* All paths passed to the storage are relative to the storage and should NOT have a leading slash.
+ *
* @since 6.0.0
+ * @deprecated 9.0.0 use \OCP\Files\Storage\IStorage instead
*/
-interface Storage {
+interface Storage extends IStorage {
/**
* $parameters is a free form array with the configuration options needed to construct the storage
*
@@ -462,10 +465,4 @@ interface Storage {
* @param bool $isAvailable
*/
public function setAvailability($isAvailable);
-
- /**
- * @param $path path for which to retrieve the owner
- * @since 9.0.0
- */
- public function getOwner($path);
}
diff --git a/lib/public/files/storage/ilockingstorage.php b/lib/public/files/storage/ilockingstorage.php
new file mode 100644
index 00000000000..32cc32ffb05
--- /dev/null
+++ b/lib/public/files/storage/ilockingstorage.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @author Robin Appelman <icewind@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Files\Storage;
+
+use OCP\Lock\ILockingProvider;
+
+/**
+ * Storage backends that require explicit locking
+ *
+ * Storage backends implementing this interface do not need to implement their own locking implementation but should use the provided lockingprovider instead
+ * The implementation of the locking methods only need to map internal storage paths to "lock keys"
+ *
+ * @since 9.0.0
+ */
+interface ILockingStorage {
+ /**
+ * @param string $path The path of the file to acquire the lock for
+ * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
+ * @param \OCP\Lock\ILockingProvider $provider
+ * @throws \OCP\Lock\LockedException
+ * @since 9.0.0
+ */
+ public function acquireLock($path, $type, ILockingProvider $provider);
+
+ /**
+ * @param string $path The path of the file to acquire the lock for
+ * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
+ * @param \OCP\Lock\ILockingProvider $provider
+ * @since 9.0.0
+ */
+ public function releaseLock($path, $type, ILockingProvider $provider);
+
+ /**
+ * @param string $path The path of the file to change the lock for
+ * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
+ * @param \OCP\Lock\ILockingProvider $provider
+ * @throws \OCP\Lock\LockedException
+ * @since 9.0.0
+ */
+ public function changeLock($path, $type, ILockingProvider $provider);
+}
diff --git a/lib/public/files/storage/istorage.php b/lib/public/files/storage/istorage.php
new file mode 100644
index 00000000000..4bc5e3536dc
--- /dev/null
+++ b/lib/public/files/storage/istorage.php
@@ -0,0 +1,482 @@
+<?php
+/**
+ * @author Jörn Friedrich Dreyer <jfd@butonic.de>
+ * @author Michael Roth <michael.roth@rz.uni-augsburg.de>
+ * @author Morris Jobke <hey@morrisjobke.de>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Robin McCorkell <rmccorkell@karoshi.org.uk>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Vincent Petry <pvince81@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program 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, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/**
+ * Public interface of ownCloud for apps to use.
+ * Files/Storage interface
+ */
+
+// use OCP namespace for all classes that are considered public.
+// This means that they should be used by apps instead of the internal ownCloud classes
+namespace OCP\Files\Storage;
+
+use OCP\Files\Cache\ICache;
+use OCP\Files\Cache\IPropagator;
+use OCP\Files\Cache\IScanner;
+use OCP\Files\Cache\IUpdater;
+use OCP\Files\Cache\IWatcher;
+use OCP\Files\InvalidPathException;
+
+/**
+ * Provide a common interface to all different storage options
+ *
+ * All paths passed to the storage are relative to the storage and should NOT have a leading slash.
+ *
+ * @since 9.0.0
+ */
+interface IStorage {
+ /**
+ * $parameters is a free form array with the configuration options needed to construct the storage
+ *
+ * @param array $parameters
+ * @since 9.0.0
+ */
+ public function __construct($parameters);
+
+ /**
+ * Get the identifier for the storage,
+ * the returned id should be the same for every storage object that is created with the same parameters
+ * and two storage objects with the same id should refer to two storages that display the same files.
+ *
+ * @return string
+ * @since 9.0.0
+ */
+ public function getId();
+
+ /**
+ * see http://php.net/manual/en/function.mkdir.php
+ * implementations need to implement a recursive mkdir
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function mkdir($path);
+
+ /**
+ * see http://php.net/manual/en/function.rmdir.php
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function rmdir($path);
+
+ /**
+ * see http://php.net/manual/en/function.opendir.php
+ *
+ * @param string $path
+ * @return resource|false
+ * @since 9.0.0
+ */
+ public function opendir($path);
+
+ /**
+ * see http://php.net/manual/en/function.is-dir.php
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function is_dir($path);
+
+ /**
+ * see http://php.net/manual/en/function.is-file.php
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function is_file($path);
+
+ /**
+ * see http://php.net/manual/en/function.stat.php
+ * only the following keys are required in the result: size and mtime
+ *
+ * @param string $path
+ * @return array|false
+ * @since 9.0.0
+ */
+ public function stat($path);
+
+ /**
+ * see http://php.net/manual/en/function.filetype.php
+ *
+ * @param string $path
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function filetype($path);
+
+ /**
+ * see http://php.net/manual/en/function.filesize.php
+ * The result for filesize when called on a folder is required to be 0
+ *
+ * @param string $path
+ * @return int|false
+ * @since 9.0.0
+ */
+ public function filesize($path);
+
+ /**
+ * check if a file can be created in $path
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function isCreatable($path);
+
+ /**
+ * check if a file can be read
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function isReadable($path);
+
+ /**
+ * check if a file can be written to
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function isUpdatable($path);
+
+ /**
+ * check if a file can be deleted
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function isDeletable($path);
+
+ /**
+ * check if a file can be shared
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function isSharable($path);
+
+ /**
+ * get the full permissions of a path.
+ * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php
+ *
+ * @param string $path
+ * @return int
+ * @since 9.0.0
+ */
+ public function getPermissions($path);
+
+ /**
+ * see http://php.net/manual/en/function.file_exists.php
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function file_exists($path);
+
+ /**
+ * see http://php.net/manual/en/function.filemtime.php
+ *
+ * @param string $path
+ * @return int|false
+ * @since 9.0.0
+ */
+ public function filemtime($path);
+
+ /**
+ * see http://php.net/manual/en/function.file_get_contents.php
+ *
+ * @param string $path
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function file_get_contents($path);
+
+ /**
+ * see http://php.net/manual/en/function.file_put_contents.php
+ *
+ * @param string $path
+ * @param string $data
+ * @return bool
+ * @since 9.0.0
+ */
+ public function file_put_contents($path, $data);
+
+ /**
+ * see http://php.net/manual/en/function.unlink.php
+ *
+ * @param string $path
+ * @return bool
+ * @since 9.0.0
+ */
+ public function unlink($path);
+
+ /**
+ * see http://php.net/manual/en/function.rename.php
+ *
+ * @param string $path1
+ * @param string $path2
+ * @return bool
+ * @since 9.0.0
+ */
+ public function rename($path1, $path2);
+
+ /**
+ * see http://php.net/manual/en/function.copy.php
+ *
+ * @param string $path1
+ * @param string $path2
+ * @return bool
+ * @since 9.0.0
+ */
+ public function copy($path1, $path2);
+
+ /**
+ * see http://php.net/manual/en/function.fopen.php
+ *
+ * @param string $path
+ * @param string $mode
+ * @return resource|false
+ * @since 9.0.0
+ */
+ public function fopen($path, $mode);
+
+ /**
+ * get the mimetype for a file or folder
+ * The mimetype for a folder is required to be "httpd/unix-directory"
+ *
+ * @param string $path
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function getMimeType($path);
+
+ /**
+ * see http://php.net/manual/en/function.hash-file.php
+ *
+ * @param string $type
+ * @param string $path
+ * @param bool $raw
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function hash($type, $path, $raw = false);
+
+ /**
+ * see http://php.net/manual/en/function.free_space.php
+ *
+ * @param string $path
+ * @return int|false
+ * @since 9.0.0
+ */
+ public function free_space($path);
+
+ /**
+ * search for occurrences of $query in file names
+ *
+ * @param string $query
+ * @return array|false
+ * @since 9.0.0
+ */
+ public function search($query);
+
+ /**
+ * see http://php.net/manual/en/function.touch.php
+ * If the backend does not support the operation, false should be returned
+ *
+ * @param string $path
+ * @param int $mtime
+ * @return bool
+ * @since 9.0.0
+ */
+ public function touch($path, $mtime = null);
+
+ /**
+ * get the path to a local version of the file.
+ * The local version of the file can be temporary and doesn't have to be persistent across requests
+ *
+ * @param string $path
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function getLocalFile($path);
+
+ /**
+ * get the path to a local version of the folder.
+ * The local version of the folder can be temporary and doesn't have to be persistent across requests
+ *
+ * @param string $path
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function getLocalFolder($path);
+
+ /**
+ * check if a file or folder has been updated since $time
+ *
+ * @param string $path
+ * @param int $time
+ * @return bool
+ * @since 9.0.0
+ *
+ * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed.
+ * returning true for other changes in the folder is optional
+ */
+ public function hasUpdated($path, $time);
+
+ /**
+ * get the ETag for a file or folder
+ *
+ * @param string $path
+ * @return string|false
+ * @since 9.0.0
+ */
+ public function getETag($path);
+
+ /**
+ * Returns whether the storage is local, which means that files
+ * are stored on the local filesystem instead of remotely.
+ * Calling getLocalFile() for local storages should always
+ * return the local files, whereas for non-local storages
+ * it might return a temporary file.
+ *
+ * @return bool true if the files are stored locally, false otherwise
+ * @since 9.0.0
+ */
+ public function isLocal();
+
+ /**
+ * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class
+ *
+ * @param string $class
+ * @return bool
+ * @since 9.0.0
+ */
+ public function instanceOfStorage($class);
+
+ /**
+ * A custom storage implementation can return an url for direct download of a give file.
+ *
+ * For now the returned array can hold the parameter url - in future more attributes might follow.
+ *
+ * @param string $path
+ * @return array|false
+ * @since 9.0.0
+ */
+ public function getDirectDownload($path);
+
+ /**
+ * @param string $path the path of the target folder
+ * @param string $fileName the name of the file itself
+ * @return void
+ * @throws InvalidPathException
+ * @since 9.0.0
+ */
+ public function verifyPath($path, $fileName);
+
+ /**
+ * @param \OCP\Files\Storage $sourceStorage
+ * @param string $sourceInternalPath
+ * @param string $targetInternalPath
+ * @return bool
+ * @since 9.0.0
+ */
+ public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath);
+
+ /**
+ * @param \OCP\Files\Storage $sourceStorage
+ * @param string $sourceInternalPath
+ * @param string $targetInternalPath
+ * @return bool
+ * @since 9.0.0
+ */
+ public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath);
+
+ /**
+ * Test a storage for availability
+ *
+ * @since 9.0.0
+ * @return bool
+ */
+ public function test();
+
+ /**
+ * @since 9.0.0
+ * @return array [ available, last_checked ]
+ */
+ public function getAvailability();
+
+ /**
+ * @since 9.0.0
+ * @param bool $isAvailable
+ */
+ public function setAvailability($isAvailable);
+
+ /**
+ * @param string $path path for which to retrieve the owner
+ * @since 9.0.0
+ */
+ public function getOwner($path);
+
+ /**
+ * @return ICache
+ * @since 9.0.0
+ */
+ public function getCache();
+
+ /**
+ * @return IPropagator
+ * @since 9.0.0
+ */
+ public function getPropagator();
+
+ /**
+ * @return IScanner
+ * @since 9.0.0
+ */
+ public function getScanner();
+
+ /**
+ * @return IUpdater
+ * @since 9.0.0
+ */
+ public function getUpdater();
+
+ /**
+ * @return IWatcher
+ * @since 9.0.0
+ */
+ public function getWatcher();
+}
diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php
index d674ac27fa1..de4ae9cd8e9 100644
--- a/tests/lib/files/cache/cache.php
+++ b/tests/lib/files/cache/cache.php
@@ -556,7 +556,7 @@ class Cache extends \Test\TestCase {
$this->assertEquals($folderWith00F6, $unNormalizedFolderName['name']);
// put normalized folder
- $this->assertTrue(is_array($this->cache->get('folder/' . $folderWith00F6)));
+ $this->assertInstanceOf('\OCP\Files\Cache\ICacheEntry', $this->cache->get('folder/' . $folderWith00F6));
$this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith00F6, $data));
// at this point we should have only one folder named "Schön"
diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php
index 8186fe29493..b1eb3f589e8 100644
--- a/tests/lib/files/cache/scanner.php
+++ b/tests/lib/files/cache/scanner.php
@@ -7,6 +7,7 @@
*/
namespace Test\Files\Cache;
+use OC\Files\Cache\CacheEntry;
/**
* Class Scanner
@@ -226,6 +227,7 @@ class Scanner extends \Test\TestCase {
// manipulate etag to simulate an empty etag
$this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_ETAG);
+ /** @var CacheEntry $data0 */
$data0 = $this->cache->get('folder/bar.txt');
$this->assertInternalType('string', $data0['etag']);
$data1 = $this->cache->get('folder');
@@ -233,7 +235,7 @@ class Scanner extends \Test\TestCase {
$data2 = $this->cache->get('');
$this->assertInternalType('string', $data2['etag']);
$data0['etag'] = '';
- $this->cache->put('folder/bar.txt', $data0);
+ $this->cache->put('folder/bar.txt', $data0->getData());
// rescan
$this->scanner->scan('folder/bar.txt', \OC\Files\Cache\Scanner::SCAN_SHALLOW, \OC\Files\Cache\Scanner::REUSE_ETAG);
diff --git a/tests/lib/files/storage/wrapper/quota.php b/tests/lib/files/storage/wrapper/quota.php
index 95bc2ff7a1a..d087a3eef33 100644
--- a/tests/lib/files/storage/wrapper/quota.php
+++ b/tests/lib/files/storage/wrapper/quota.php
@@ -9,6 +9,8 @@
namespace Test\Files\Storage\Wrapper;
//ensure the constants are loaded
+use OC\Files\Cache\CacheEntry;
+
\OC::$loader->load('\OC\Files\Filesystem');
/**
@@ -194,7 +196,7 @@ class Quota extends \Test\Files\Storage\Storage {
$cache->expects($this->once())
->method('get')
->with('files')
- ->will($this->returnValue(array('size' => 50)));
+ ->will($this->returnValue(new CacheEntry(['size' => 50])));
$instance = new \OC\Files\Storage\Wrapper\Quota(array('storage' => $storage, 'quota' => 1024, 'root' => 'files'));