diff options
Diffstat (limited to 'lib/private/files/cache/upgrade.php')
-rw-r--r-- | lib/private/files/cache/upgrade.php | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/lib/private/files/cache/upgrade.php b/lib/private/files/cache/upgrade.php new file mode 100644 index 00000000000..cfb9a117311 --- /dev/null +++ b/lib/private/files/cache/upgrade.php @@ -0,0 +1,227 @@ +<?php +/** + * Copyright (c) 2012 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 Upgrade { + /** + * @var Legacy $legacy + */ + private $legacy; + + private $numericIds = array(); + + private $mimeTypeIds = array(); + + /** + * @param Legacy $legacy + */ + public function __construct($legacy) { + $this->legacy = $legacy; + } + + /** + * Preform a upgrade a path and it's childs + * + * @param string $path + * @param bool $mode + */ + function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) { + if (!$this->legacy->hasItems()) { + return; + } + \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path); + if ($row = $this->legacy->get($path)) { + $data = $this->getNewData($row); + if ($data) { + $this->insert($data); + $this->upgradeChilds($data['id'], $mode); + } + } + } + + /** + * upgrade all child elements of an item + * + * @param int $id + * @param bool $mode + */ + function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) { + $children = $this->legacy->getChildren($id); + foreach ($children as $child) { + $childData = $this->getNewData($child); + \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']); + if ($childData) { + $this->insert($childData); + if ($mode == Scanner::SCAN_RECURSIVE) { + $this->upgradeChilds($child['id']); + } + } + } + } + + /** + * insert data into the new cache + * + * @param array $data the data for the new cache + */ + function insert($data) { + 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`, `etag` ) + VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); + } + if (!$this->inCache($data['storage'], $data['path_hash'], $data['id'])) { + \OC_DB::executeAudited($insertQuery, 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['etag'])); + } + } + + /** + * check if an item is already in the new cache + * + * @param string $storage + * @param string $pathHash + * @param string $id + * @return bool + */ + function inCache($storage, $pathHash, $id) { + static $query = null; + if(is_null($query)) { + $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE (`storage` = ? AND `path_hash` = ?) OR `fileid` = ?'); + } + $result = \OC_DB::executeAudited($query, array($storage, $pathHash, $id)); + return (bool)$result->fetchRow(); + } + + /** + * 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) { + //Make sure there is a path, otherwise we can do nothing. + if(!isset($data['path'])) { + return false; + } + $newData = $data; + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath; + */ + 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); + $newData['parent'] = ($internalPath === '') ? -1 : $data['parent']; + $newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ; + $newData['storage_object'] = $storage; + $newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage); + $newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage); + return $newData; + } else { + \OC_Log::write('core', 'Unable to migrate data from old cache for '.$data['path'].' because the storage was not found', \OC_Log::ERROR); + return false; + } + } + + /** + * get the numeric storage id + * + * @param \OC\Files\Storage\Storage $storage + * @return int + */ + function getNumericId($storage) { + $storageId = $storage->getId(); + if (!isset($this->numericIds[$storageId])) { + $cache = $storage->getCache(); + $this->numericIds[$storageId] = $cache->getNumericStorageId(); + } + return $this->numericIds[$storageId]; + } + + /** + * get the numeric id for a mimetype + * + * @param string $mimetype + * @param \OC\Files\Storage\Storage $storage + * @return int + */ + function getMimetypeId($mimetype, $storage) { + if (!isset($this->mimeTypeIds[$mimetype])) { + $cache = new Cache($storage); + $this->mimeTypeIds[$mimetype] = $cache->getMimetypeId($mimetype); + } + return $this->mimeTypeIds[$mimetype]; + } + + /** + * check if a cache upgrade is required for $user + * + * @param string $user + * @return bool + */ + static function needUpgrade($user) { + $cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4); + return $cacheVersion < 5; + } + + /** + * mark the filecache as upgrade + * + * @param string $user + */ + 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); + } +} |