Skip to content
Snippets Groups Projects
Commit dca0fda2 authored by Björn Schießle's avatar Björn Schießle
Browse files

keep track of the size of the versions directory

parent 417498d5
No related branches found
No related tags found
No related merge requests found
...@@ -39,15 +39,15 @@ class Hooks { ...@@ -39,15 +39,15 @@ class Hooks {
* cleanup the versions directory if the actual file gets deleted * cleanup the versions directory if the actual file gets deleted
*/ */
public static function remove_hook($params) { public static function remove_hook($params) {
$versions_fileview = \OCP\Files::getStorage('files_versions'); if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
$rel_path = $params['path'];
$abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$rel_path.'.v'; $versions = new Storage( new \OC_FilesystemView('') );
if(Storage::isversioned($rel_path)) {
$versions = Storage::getVersions($rel_path); $path = $params[\OC_Filesystem::signal_param_path];
foreach ($versions as $v) {
unlink($abs_path . $v['version']); if($path<>'') $versions->delete( $path );
}
} }
} }
/** /**
......
...@@ -82,14 +82,39 @@ class Storage { ...@@ -82,14 +82,39 @@ class Storage {
} }
// store a new version of a file // 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 // 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. * rollback to an old version of a file.
*/ */
...@@ -216,13 +241,37 @@ class Storage { ...@@ -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 * @brief returns all stored file versions from a given user
* @param $uid id to the 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 * @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) { private static function getAllVersions($uid) {
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
...@@ -280,7 +329,7 @@ class Storage { ...@@ -280,7 +329,7 @@ class Storage {
/** /**
* @brief Erase a file's versions which exceed the set quota * @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') { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
list($uid, $filename) = self::getUidAndFilename($filename); list($uid, $filename) = self::getUidAndFilename($filename);
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
...@@ -293,13 +342,20 @@ class Storage { ...@@ -293,13 +342,20 @@ class Storage {
if ( $quota == null ) { if ( $quota == null ) {
$quota = \OC_Filesystem::free_space('/'); $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'); $rootInfo = \OC_FileCache::get('', '/'. $uid . '/files');
$free = $quota-$rootInfo['size']; // remaining free space for user $free = $quota-$rootInfo['size']; // remaining free space for user
if ( $free > 0 ) { if ( $free > 0 ) {
$availableSpace = 100* self::DEFAULTMAXSIZE / ($free); // how much space can be used for versions $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $versionsSize; // 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; } else {
$availableSpace = $free-$versionsSize;
}
// after every 1000s run reduce the number of all versions not only for the current file // after every 1000s run reduce the number of all versions not only for the current file
$random = rand(0, 1000); $random = rand(0, 1000);
...@@ -334,6 +390,7 @@ class Storage { ...@@ -334,6 +390,7 @@ class Storage {
//distance between two version to small, delete version //distance between two version to small, delete version
$versions_fileview->unlink($versions[$i]['path'].'.v'.$versions[$i]['version']); $versions_fileview->unlink($versions[$i]['path'].'.v'.$versions[$i]['version']);
$availableSpace += $versions[$i]['size']; $availableSpace += $versions[$i]['size'];
$versionsSize -= $versions[$i]['size'];
} else { } else {
$nextVersion = $versions[$i]['version'] - $step; $nextVersion = $versions[$i]['version'] - $step;
} }
...@@ -355,10 +412,13 @@ class Storage { ...@@ -355,10 +412,13 @@ class Storage {
$i = 0; $i = 0;
while ($availableSpace < 0) { while ($availableSpace < 0) {
$versions_fileview->unlink($all_versions[$i]['path'].'.v'.$all_versions[$i]['version']); $versions_fileview->unlink($all_versions[$i]['path'].'.v'.$all_versions[$i]['version']);
$versionsSize -= $all_versions[$i]['size'];
$availableSpace += $all_versions[$i]['size']; $availableSpace += $all_versions[$i]['size'];
$i++; $i++;
if ($i = $numOfVersions-2) break; // keep at least the last version if ($i = $numOfVersions-2) break; // keep at least the last version
} }
\OCP\Config::setAppValue('files_versions', 'size', $versionsSize);
} }
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment