keep track of the size of the versions directory

This commit is contained in:
Björn Schießle 2013-01-10 18:04:30 +01:00
parent 417498d519
commit dca0fda2ad
2 changed files with 78 additions and 18 deletions

View File

@ -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 );
}
} }
} }
/** /**

View File

@ -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 {
} }
} }
/**
* @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 {
/** /**
* @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 {
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 {
//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 {
$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);
} }
} }
} }