From dca0fda2ad84401f984410a7b9ae2526e47234bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 10 Jan 2013 18:04:30 +0100 Subject: [PATCH] keep track of the size of the versions directory --- apps/files_versions/lib/hooks.php | 18 +++---- apps/files_versions/lib/versions.php | 78 ++++++++++++++++++++++++---- 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/apps/files_versions/lib/hooks.php b/apps/files_versions/lib/hooks.php index e897a81f7a..736d9cd868 100644 --- a/apps/files_versions/lib/hooks.php +++ b/apps/files_versions/lib/hooks.php @@ -39,15 +39,15 @@ class Hooks { * cleanup the versions directory if the actual file gets deleted */ public static function remove_hook($params) { - $versions_fileview = \OCP\Files::getStorage('files_versions'); - $rel_path = $params['path']; - $abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$rel_path.'.v'; - if(Storage::isversioned($rel_path)) { - $versions = Storage::getVersions($rel_path); - foreach ($versions as $v) { - unlink($abs_path . $v['version']); - } - } + if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { + + $versions = new Storage( new \OC_FilesystemView('') ); + + $path = $params[\OC_Filesystem::signal_param_path]; + + if($path<>'') $versions->delete( $path ); + + } } /** diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 58e4a2ce13..fc8adf646a 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -82,14 +82,39 @@ class Storage { } // store a new version of a file - $users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename)); - + $result = $users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename)); + if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) { + $versionsSize = self::calculateSize($uid); + } + $versionsSize += $users_view->filesize('files'.$filename); + // expire old revisions if necessary - Storage::expire($filename); + self::expire($filename, $versionsSize); } } + /** + * Delete versions of a file + */ + public static function delete($filename) { + list($uid, $filename) = self::getUidAndFilename($filename); + $versions_fileview = new \OC_FilesystemView('/'.$uid .'/files_versions'); + + $abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$filename.'.v'; + if(Storage::isversioned($filename)) { + $versions = self::getVersions($filename); + if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) { + $versionsSize = self::calculateSize($uid); + } + foreach ($versions as $v) { + unlink($abs_path . $v['version']); + $versionsSize -= $v['size']; + } + \OCP\Config::setAppValue('files_versions', 'size', $versionsSize); + } + } + /** * rollback to an old version of a file. */ @@ -216,13 +241,37 @@ class Storage { } } + + /** + * @brief get the size of all stored versions from a given user + * @param $uid id from the user + * @return size of vesions + */ + private static function calculateSize($uid) { + if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { + $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); + $versionsRoot = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath(''); + + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($versionsRoot), \RecursiveIteratorIterator::CHILD_FIRST); + + $size = 0; + + foreach ($iterator as $path) { + if ( preg_match('/^.+\.v(\d+)$/', $path, $match) ) { + $relpath = substr($path, strlen($versionsRoot)-1); + $size += $versions_fileview->filesize($relpath); + } + } + + return $size; + } + } /** * @brief returns all stored file versions from a given user * @param $uid id to the user * @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename */ - private static function getAllVersions($uid) { if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); @@ -280,7 +329,7 @@ class Storage { /** * @brief Erase a file's versions which exceed the set quota */ - public static function expire($filename) { + public static function expire($filename, $versionsSize = null) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); @@ -293,13 +342,20 @@ class Storage { if ( $quota == null ) { $quota = \OC_Filesystem::free_space('/'); } - + + if ( $versionsSize === null ) { + if ( ($versionsSize = \OCP\Config::getAppValue('files_versions', 'size')) === null ) { + $versionsSize = self::calculateSize($uid); + } + } + $rootInfo = \OC_FileCache::get('', '/'. $uid . '/files'); $free = $quota-$rootInfo['size']; // remaining free space for user - if ( $free > 0 ) { - $availableSpace = 100* self::DEFAULTMAXSIZE / ($free); // how much space can be used for versions - } // otherwise available space negative and we need to reach at least 0 at the end of the expiration process; + $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $versionsSize; // how much space can be used for versions + } else { + $availableSpace = $free-$versionsSize; + } // after every 1000s run reduce the number of all versions not only for the current file $random = rand(0, 1000); @@ -334,6 +390,7 @@ class Storage { //distance between two version to small, delete version $versions_fileview->unlink($versions[$i]['path'].'.v'.$versions[$i]['version']); $availableSpace += $versions[$i]['size']; + $versionsSize -= $versions[$i]['size']; } else { $nextVersion = $versions[$i]['version'] - $step; } @@ -355,10 +412,13 @@ class Storage { $i = 0; while ($availableSpace < 0) { $versions_fileview->unlink($all_versions[$i]['path'].'.v'.$all_versions[$i]['version']); + $versionsSize -= $all_versions[$i]['size']; $availableSpace += $all_versions[$i]['size']; $i++; if ($i = $numOfVersions-2) break; // keep at least the last version } + + \OCP\Config::setAppValue('files_versions', 'size', $versionsSize); } } }