summaryrefslogtreecommitdiffstats
path: root/lib/files/cache
diff options
context:
space:
mode:
authorFlorin Peter <github@florin-peter.de>2013-05-15 03:22:06 +0200
committerFlorin Peter <github@florin-peter.de>2013-05-15 03:22:06 +0200
commit226aec8d5602e112c413f8c0548b18c737a65a02 (patch)
treeaa745db7ea720bfd25ab8d890167885d1c505db4 /lib/files/cache
parentd017bbb065245212e8aa4091f4bee0a4e8ea9055 (diff)
parent6a788d1a545d5e0dcd6df6ec3c144fa593cf40c8 (diff)
downloadnextcloud-server-226aec8d5602e112c413f8c0548b18c737a65a02.tar.gz
nextcloud-server-226aec8d5602e112c413f8c0548b18c737a65a02.zip
Merge branch 'master' into files_encryption
Diffstat (limited to 'lib/files/cache')
-rw-r--r--lib/files/cache/backgroundwatcher.php104
-rw-r--r--lib/files/cache/cache.php74
-rw-r--r--lib/files/cache/permissions.php15
-rw-r--r--lib/files/cache/scanner.php12
-rw-r--r--lib/files/cache/storage.php59
-rw-r--r--lib/files/cache/updater.php9
6 files changed, 225 insertions, 48 deletions
diff --git a/lib/files/cache/backgroundwatcher.php b/lib/files/cache/backgroundwatcher.php
new file mode 100644
index 00000000000..7549745e7d7
--- /dev/null
+++ b/lib/files/cache/backgroundwatcher.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Cache;
+
+use \OC\Files\Mount;
+use \OC\Files\Filesystem;
+
+class BackgroundWatcher {
+ static $folderMimetype = null;
+
+ static private function getFolderMimetype() {
+ if (!is_null(self::$folderMimetype)) {
+ return self::$folderMimetype;
+ }
+ $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?');
+ $result = $query->execute(array('httpd/unix-directory'));
+ $row = $result->fetchRow();
+ return $row['id'];
+ }
+
+ static private function checkUpdate($id) {
+ $cacheItem = Cache::getById($id);
+ if (is_null($cacheItem)) {
+ return;
+ }
+ list($storageId, $internalPath) = $cacheItem;
+ $mounts = Mount::findByStorageId($storageId);
+
+ if (count($mounts) === 0) {
+ //if the storage we need isn't mounted on default, try to find a user that has access to the storage
+ $permissionsCache = new Permissions($storageId);
+ $users = $permissionsCache->getUsers($id);
+ if (count($users) === 0) {
+ return;
+ }
+ Filesystem::initMountPoints($users[0]);
+ $mounts = Mount::findByStorageId($storageId);
+ if (count($mounts) === 0) {
+ return;
+ }
+ }
+ $storage = $mounts[0]->getStorage();
+ $watcher = new Watcher($storage);
+ $watcher->checkUpdate($internalPath);
+ }
+
+ /**
+ * get the next fileid in the cache
+ *
+ * @param int $previous
+ * @param bool $folder
+ * @return int
+ */
+ static private function getNextFileId($previous, $folder) {
+ if ($folder) {
+ $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` > ? AND mimetype = ' . self::getFolderMimetype() . ' ORDER BY `fileid` ASC', 1);
+ } else {
+ $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` > ? AND mimetype != ' . self::getFolderMimetype() . ' ORDER BY `fileid` ASC', 1);
+ }
+ $result = $query->execute(array($previous));
+ if ($row = $result->fetchRow()) {
+ return $row['fileid'];
+ } else {
+ return 0;
+ }
+ }
+
+ static public function checkNext() {
+ // check both 1 file and 1 folder, this way new files are detected quicker because there are less folders than files usually
+ $previousFile = \OC_Appconfig::getValue('files', 'backgroundwatcher_previous_file', 0);
+ $previousFolder = \OC_Appconfig::getValue('files', 'backgroundwatcher_previous_folder', 0);
+ $nextFile = self::getNextFileId($previousFile, false);
+ $nextFolder = self::getNextFileId($previousFolder, true);
+ \OC_Appconfig::setValue('files', 'backgroundwatcher_previous_file', $nextFile);
+ \OC_Appconfig::setValue('files', 'backgroundwatcher_previous_folder', $nextFolder);
+ if ($nextFile > 0) {
+ self::checkUpdate($nextFile);
+ }
+ if ($nextFolder > 0) {
+ self::checkUpdate($nextFolder);
+ }
+ }
+
+ static public function checkAll() {
+ $previous = 0;
+ $next = 1;
+ while ($next != 0) {
+ $next = self::getNextFileId($previous, true);
+ self::checkUpdate($next);
+ }
+ $previous = 0;
+ $next = 1;
+ while ($next != 0) {
+ $next = self::getNextFileId($previous, false);
+ self::checkUpdate($next);
+ }
+ }
+}
diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php
index 4e32ff2ba8a..3c2649cb1be 100644
--- a/lib/files/cache/cache.php
+++ b/lib/files/cache/cache.php
@@ -30,11 +30,9 @@ class Cache {
private $storageId;
/**
- * numeric storage id
- *
- * @var int $numericId
+ * @var Storage $storageCache
*/
- private $numericId;
+ private $storageCache;
private $mimetypeIds = array();
private $mimetypes = array();
@@ -52,19 +50,11 @@ class Cache {
$this->storageId = md5($this->storageId);
}
- $query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?');
- $result = $query->execute(array($this->storageId));
- if ($row = $result->fetchRow()) {
- $this->numericId = $row['numeric_id'];
- } else {
- $query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)');
- $query->execute(array($this->storageId));
- $this->numericId = \OC_DB::insertid('*PREFIX*storages');
- }
+ $this->storageCache = new Storage($storage);
}
public function getNumericStorageId() {
- return $this->numericId;
+ return $this->storageCache->getNumericId();
}
/**
@@ -111,7 +101,7 @@ class Cache {
public function get($file) {
if (is_string($file) or $file == '') {
$where = 'WHERE `storage` = ? AND `path_hash` = ?';
- $params = array($this->numericId, md5($file));
+ $params = array($this->getNumericStorageId(), md5($file));
} else { //file id
$where = 'WHERE `fileid` = ?';
$params = array($file);
@@ -199,14 +189,14 @@ class Cache {
list($queryParts, $params) = $this->buildParts($data);
$queryParts[] = '`storage`';
- $params[] = $this->numericId;
+ $params[] = $this->getNumericStorageId();
$valuesPlaceholder = array_fill(0, count($queryParts), '?');
$query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ')'
. ' VALUES(' . implode(', ', $valuesPlaceholder) . ')');
$result = $query->execute($params);
if (\OC_DB::isError($result)) {
- \OCP\Util::writeLog('cache', 'Insert to cache failed: '.$result, \OCP\Util::ERROR);
+ \OCP\Util::writeLog('cache', 'Insert to cache failed: ' . $result, \OCP\Util::ERROR);
}
return (int)\OC_DB::insertid('*PREFIX*filecache');
@@ -265,7 +255,7 @@ class Cache {
$pathHash = md5($file);
$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?');
- $result = $query->execute(array($this->numericId, $pathHash));
+ $result = $query->execute(array($this->getNumericStorageId(), $pathHash));
if ($row = $result->fetchRow()) {
return $row['fileid'];
@@ -329,19 +319,22 @@ class Cache {
* @param string $target
*/
public function move($source, $target) {
- $sourceId = $this->getId($source);
+ $sourceData = $this->get($source);
+ $sourceId = $sourceData['fileid'];
$newParentId = $this->getParentId($target);
- //find all child entries
- $query = \OC_DB::prepare('SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `path` LIKE ?');
- $result = $query->execute(array($source . '/%'));
- $childEntries = $result->fetchAll();
- $sourceLength = strlen($source);
- $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
-
- foreach ($childEntries as $child) {
- $targetPath = $target . substr($child['path'], $sourceLength);
- $query->execute(array($targetPath, md5($targetPath), $child['fileid']));
+ if ($sourceData['mimetype'] === 'httpd/unix-directory') {
+ //find all child entries
+ $query = \OC_DB::prepare('SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `path` LIKE ?');
+ $result = $query->execute(array($source . '/%'));
+ $childEntries = $result->fetchAll();
+ $sourceLength = strlen($source);
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ? WHERE `fileid` = ?');
+
+ foreach ($childEntries as $child) {
+ $targetPath = $target . substr($child['path'], $sourceLength);
+ $query->execute(array($targetPath, md5($targetPath), $child['fileid']));
+ }
}
$query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ?, `name` = ?, `parent` =?'
@@ -354,7 +347,7 @@ class Cache {
*/
public function clear() {
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage = ?');
- $query->execute(array($this->numericId));
+ $query->execute(array($this->getNumericStorageId()));
$query = \OC_DB::prepare('DELETE FROM `*PREFIX*storages` WHERE id = ?');
$query->execute(array($this->storageId));
@@ -368,7 +361,7 @@ class Cache {
public function getStatus($file) {
$pathHash = md5($file);
$query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?');
- $result = $query->execute(array($this->numericId, $pathHash));
+ $result = $query->execute(array($this->getNumericStorageId(), $pathHash));
if ($row = $result->fetchRow()) {
if ((int)$row['size'] === -1) {
return self::SHALLOW;
@@ -395,7 +388,7 @@ class Cache {
SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `unencrypted_size`, `etag`
FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?'
);
- $result = $query->execute(array($pattern, $this->numericId));
+ $result = $query->execute(array($pattern, $this->getNumericStorageId()));
$files = array();
while ($row = $result->fetchRow()) {
$row['mimetype'] = $this->getMimetype($row['mimetype']);
@@ -422,7 +415,7 @@ class Cache {
FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?'
);
$mimetype = $this->getMimetypeId($mimetype);
- $result = $query->execute(array($mimetype, $this->numericId));
+ $result = $query->execute(array($mimetype, $this->getNumericStorageId()));
$files = array();
while ($row = $result->fetchRow()) {
$row['mimetype'] = $this->getMimetype($row['mimetype']);
@@ -441,7 +434,7 @@ class Cache {
$this->calculateFolderSize($path);
if ($path !== '') {
$parent = dirname($path);
- if ($parent === '.') {
+ if ($parent === '.' or $parent === '/') {
$parent = '';
}
$this->correctFolderSize($parent);
@@ -460,7 +453,7 @@ class Cache {
return 0;
}
$query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?');
- $result = $query->execute(array($id, $this->numericId));
+ $result = $query->execute(array($id, $this->getNumericStorageId()));
$totalSize = 0;
$hasChilds = 0;
while ($row = $result->fetchRow()) {
@@ -487,7 +480,7 @@ class Cache {
*/
public function getAll() {
$query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?');
- $result = $query->execute(array($this->numericId));
+ $result = $query->execute(array($this->getNumericStorageId()));
$ids = array();
while ($row = $result->fetchRow()) {
$ids[] = $row['fileid'];
@@ -507,7 +500,7 @@ class Cache {
public function getIncomplete() {
$query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache`'
. ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1');
- $result = $query->execute(array($this->numericId));
+ $result = $query->execute(array($this->getNumericStorageId()));
if ($row = $result->fetchRow()) {
return $row['path'];
} else {
@@ -518,6 +511,7 @@ class Cache {
/**
* get the storage id of the storage for a file and the internal path of the file
*
+ * @param int $id
* @return array, first element holding the storage id, second the path
*/
static public function getById($id) {
@@ -530,10 +524,8 @@ class Cache {
return null;
}
- $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?');
- $result = $query->execute(array($numericId));
- if ($row = $result->fetchRow()) {
- return array($row['id'], $path);
+ if ($id = Storage::getStorageId($numericId)) {
+ return array($id, $path);
} else {
return null;
}
diff --git a/lib/files/cache/permissions.php b/lib/files/cache/permissions.php
index a5c9c144054..faa5ff5eacc 100644
--- a/lib/files/cache/permissions.php
+++ b/lib/files/cache/permissions.php
@@ -107,4 +107,19 @@ class Permissions {
$query->execute(array($fileId, $user));
}
}
+
+ /**
+ * get the list of users which have permissions stored for a file
+ *
+ * @param int $fileId
+ */
+ public function getUsers($fileId) {
+ $query = \OC_DB::prepare('SELECT `user` FROM `*PREFIX*permissions` WHERE `fileid` = ?');
+ $result = $query->execute(array($fileId));
+ $users = array();
+ while ($row = $result->fetchRow()) {
+ $users[] = $row['user'];
+ }
+ return $users;
+ }
}
diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php
index f019d4fc608..661bc486330 100644
--- a/lib/files/cache/scanner.php
+++ b/lib/files/cache/scanner.php
@@ -62,13 +62,15 @@ class Scanner {
* @return array with metadata of the scanned file
*/
public function scanFile($file, $checkExisting = false) {
- if (!self::isIgnoredFile($file)) {
+ if ( ! self::isPartialFile($file)
+ and ! \OC\Files\Filesystem::isFileBlacklisted($file)
+ ) {
\OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId));
$data = $this->getData($file);
if ($data) {
if ($file) {
$parent = dirname($file);
- if ($parent === '.') {
+ if ($parent === '.' or $parent === '/') {
$parent = '';
}
if (!$this->cache->inCache($parent)) {
@@ -166,10 +168,8 @@ class Scanner {
* @param String $file
* @return boolean
*/
- public static function isIgnoredFile($file) {
- if (pathinfo($file, PATHINFO_EXTENSION) === 'part'
- || \OC\Files\Filesystem::isFileBlacklisted($file)
- ) {
+ public static function isPartialFile($file) {
+ if (pathinfo($file, PATHINFO_EXTENSION) === 'part') {
return true;
}
return false;
diff --git a/lib/files/cache/storage.php b/lib/files/cache/storage.php
new file mode 100644
index 00000000000..72de376798c
--- /dev/null
+++ b/lib/files/cache/storage.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Cache;
+
+/**
+ * Class Storage
+ *
+ * cache storage specific data
+ *
+ * @package OC\Files\Cache
+ */
+class Storage {
+ private $storageId;
+ private $numericId;
+
+ /**
+ * @param \OC\Files\Storage\Storage|string $storage
+ */
+ public function __construct($storage) {
+ if ($storage instanceof \OC\Files\Storage\Storage) {
+ $this->storageId = $storage->getId();
+ } else {
+ $this->storageId = $storage;
+ }
+ if (strlen($this->storageId) > 64) {
+ $this->storageId = md5($this->storageId);
+ }
+
+ $query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?');
+ $result = $query->execute(array($this->storageId));
+ if ($row = $result->fetchRow()) {
+ $this->numericId = $row['numeric_id'];
+ } else {
+ $query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)');
+ $query->execute(array($this->storageId));
+ $this->numericId = \OC_DB::insertid('*PREFIX*storages');
+ }
+ }
+
+ public function getNumericId() {
+ return $this->numericId;
+ }
+
+ public static function getStorageId($numericId) {
+ $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?');
+ $result = $query->execute(array($numericId));
+ if ($row = $result->fetchRow()) {
+ return $row['id'];
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php
index 92a16d9d9b6..417a47f3830 100644
--- a/lib/files/cache/updater.php
+++ b/lib/files/cache/updater.php
@@ -132,7 +132,14 @@ class Updater {
* @param array $params
*/
static public function touchHook($params) {
- self::writeUpdate($params['path']);
+ $path = $params['path'];
+ list($storage, $internalPath) = self::resolvePath($path);
+ $cache = $storage->getCache();
+ $id = $cache->getId($internalPath);
+ if ($id !== -1) {
+ $cache->update($id, array('etag' => $storage->getETag($internalPath)));
+ }
+ self::writeUpdate($path);
}
/**