diff options
author | blizzz <blizzz@owncloud.com> | 2013-03-27 22:10:22 +0400 |
---|---|---|
committer | blizzz <blizzz@owncloud.com> | 2013-03-27 22:10:22 +0400 |
commit | 4d50a21eb49c834c54a46c2dd845d836573de472 (patch) | |
tree | 3dfdf23e6b964319e4100eda90ef55c6d5192174 | |
parent | 37971133f1478880b7a73f183aa0c42badda7035 (diff) | |
parent | 4411de0dbf7e387ad71aa0184bfd143e2832a199 (diff) |
Merge pull request #2558 from owncloud/fix_cache_upgrade
Fix cache upgrade
-rw-r--r-- | core/ajax/update.php | 43 | ||||
-rw-r--r-- | db_structure.xml | 16 | ||||
-rw-r--r-- | lib/files/cache/legacy.php | 33 | ||||
-rw-r--r-- | lib/files/cache/scanner.php | 11 | ||||
-rw-r--r-- | lib/files/cache/upgrade.php | 59 |
5 files changed, 149 insertions, 13 deletions
diff --git a/core/ajax/update.php b/core/ajax/update.php index 8b20150d432..e40d0def4e4 100644 --- a/core/ajax/update.php +++ b/core/ajax/update.php @@ -14,6 +14,10 @@ if (OC::checkUpgrade(false)) { try { $result = OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/db_structure.xml'); $watcher->success('Updated database'); + + // do a file cache upgrade for users with files + // this can take loooooooooooooooooooooooong + __doFileCacheUpgrade($watcher); } catch (Exception $exception) { $watcher->failure($exception->getMessage()); } @@ -26,6 +30,45 @@ if (OC::checkUpgrade(false)) { $watcher->done(); } +/** + * The FileCache Upgrade routine + * + * @param UpdateWatcher $watcher + */ +function __doFileCacheUpgrade($watcher) { + $query = \OC_DB::prepare(' + SELECT DISTINCT user + FROM`*PREFIX*fscache` + '); + $result = $query->execute(); + $users = $result->fetchAll(); + if(count($users) == 0) { + return; + } + $step = 100 / count($users); + $percentCompleted = 0; + $lastPercentCompletedOutput = 0; + $startInfoShown = false; + foreach($users as $userRow) { + $user = $userRow['user']; + \OC\Files\Filesystem::initMountPoints($user); + \OC\Files\Cache\Upgrade::doSilentUpgrade($user); + if(!$startInfoShown) { + //We show it only now, because otherwise Info about upgraded apps + //will appear between this and progress info + $watcher->success('Updating filecache, this may take really long...'); + $startInfoShown = true; + } + $percentCompleted += $step; + $out = floor($percentCompleted); + if($out != $lastPercentCompletedOutput) { + $watcher->success('... '. $out.'% done ...'); + $lastPercentCompletedOutput = $out; + } + } + $watcher->success('Updated filecache'); +} + class UpdateWatcher { /** * @var \OC_EventSource $eventSource; diff --git a/db_structure.xml b/db_structure.xml index 3ce41096d9e..0f3def9fcd9 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -651,6 +651,22 @@ <length>255</length> </field> + <index> + <name>property_index</name> + <field> + <name>propertyname</name> + <sorting>ascending</sorting> + </field> + <field> + <name>propertypath</name> + <sorting>ascending</sorting> + </field> + <field> + <name>userid</name> + <sorting>ascending</sorting> + </field> + </index> + </declaration> </table> diff --git a/lib/files/cache/legacy.php b/lib/files/cache/legacy.php index 2b8689fcbda..efe441c56bc 100644 --- a/lib/files/cache/legacy.php +++ b/lib/files/cache/legacy.php @@ -72,7 +72,32 @@ class Legacy { $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `path` = ?'); } $result = $query->execute(array($path)); - return $result->fetchRow(); + $data = $result->fetchRow(); + $data['etag'] = $this->getEtag($data['path']); + return $data; + } + + /** + * Get the ETag for the given path + * + * @param type $path + * @return string + */ + function getEtag($path) { + static $query = null; + list(, $user, , $relativePath) = explode('/', $path, 4); + if (is_null($relativePath)) { + $relativePath = ''; + } + if(is_null($query)){ + $query = \OC_DB::prepare('SELECT `propertyvalue` FROM `*PREFIX*properties` WHERE `userid` = ? AND propertypath = ? AND propertyname = "{DAV:}getetag"'); + } + $result = $query->execute(array($user, '/' . $relativePath)); + if ($row = $result->fetchRow()) { + return trim($row['propertyvalue'], '"'); + } else { + return ''; + } } /** @@ -82,6 +107,10 @@ class Legacy { function getChildren($id) { $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `parent` = ?'); $result = $query->execute(array($id)); - return $result->fetchAll(); + $data = $result->fetchAll(); + foreach ($data as $i => $item) { + $data[$i]['etag'] = $this->getEtag($item['path']); + } + return $data; } } diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 88f208547f6..e1f5cb1f377 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -74,13 +74,16 @@ class Scanner { $this->scanFile($parent); } } - if ($checkExisting and $cacheData = $this->cache->get($file)) { + if($cacheData = $this->cache->get($file)) { + if ($data['mtime'] === $cacheData['mtime'] && + $data['size'] === $cacheData['size']) { + $data['etag'] = $cacheData['etag']; + } + } + if ($checkExisting and $cacheData) { if ($data['size'] === -1) { $data['size'] = $cacheData['size']; } - if ($data['mtime'] === $cacheData['mtime']) { - $data['etag'] = $cacheData['etag']; - } } $this->cache->put($file, $data); } diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 230690d35c3..0d5bed5c817 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -36,7 +36,6 @@ class Upgrade { return; } \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path); - if ($row = $this->legacy->get($path)) { $data = $this->getNewData($row); if ($data) { @@ -67,14 +66,16 @@ class Upgrade { * @param array $data the data for the new cache */ function insert($data) { - if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) { + static $insertQuery = null; + if(is_null($insertQuery)) { $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` - ( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) - VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); - + ( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` ) + VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); + } + if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) { $insertQuery->execute(array($data['id'], $data['storage'], $data['path'], $data['path_hash'], $data['parent'], $data['name'], - $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'])); + $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'], $data['etag'])); } } @@ -85,7 +86,10 @@ class Upgrade { * @return bool */ function inCache($storage, $pathHash, $id) { - $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?'); + static $query = null; + if(is_null($query)) { + $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?'); + } $result = $query->execute(array($storage, $pathHash, $id)); return (bool)$result->fetchRow(); } @@ -94,6 +98,25 @@ class Upgrade { * get the new data array from the old one * * @param array $data the data from the old cache + * Example data array + * Array + * ( + * [id] => 418 + * [path] => /tina/files/picture.jpg //relative to datadir + * [path_hash] => 66d4547e372888deed80b24fec9b192b + * [parent] => 234 + * [name] => picture.jpg + * [user] => tina + * [size] => 1265283 + * [ctime] => 1363909709 + * [mtime] => 1363909709 + * [mimetype] => image/jpeg + * [mimepart] => image + * [encrypted] => 0 + * [versioned] => 0 + * [writable] => 1 + * ) + * * @return array */ function getNewData($data) { @@ -104,6 +127,7 @@ class Upgrade { */ list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']); if ($storage) { + $newData['etag'] = $data['etag']; $newData['path_hash'] = md5($internalPath); $newData['path'] = $internalPath; $newData['storage'] = $this->getNumericId($storage); @@ -166,4 +190,25 @@ class Upgrade { static function upgradeDone($user) { \OCP\Config::setUserValue($user, 'files', 'cache_version', 5); } + + /** + * Does a "silent" upgrade, i.e. without an Event-Source as triggered + * on User-Login via Ajax. This method is called within the regular + * ownCloud upgrade. + * + * @param string $user a User ID + */ + public static function doSilentUpgrade($user) { + if(!self::needUpgrade($user)) { + return; + } + $legacy = new \OC\Files\Cache\Legacy($user); + if ($legacy->hasItems()) { + \OC_DB::beginTransaction(); + $upgrade = new \OC\Files\Cache\Upgrade($legacy); + $upgrade->upgradePath('/' . $user . '/files'); + \OC_DB::commit(); + } + \OC\Files\Cache\Upgrade::upgradeDone($user); + } } |