/** * @brief rename/move versions of renamed/moved files * @param array with oldpath and newpath * * This function is connected to the rename signal of OC_Filesystem and adjust the name and location * of the stored versions along the actual file */ public static function rename_hook($params) { $versions_fileview = \OCP\Files::getStorage('files_versions'); $rel_oldpath = $params['oldpath']; $abs_oldpath = \OCP\Config::getSystemValue('datadirectory') . $versions_fileview->getAbsolutePath('') . $rel_oldpath . '.v'; $abs_newpath = \OCP\Config::getSystemValue('datadirectory') . $versions_fileview->getAbsolutePath('') . $params['newpath'] . '.v'; if (Storage::isversioned($rel_oldpath)) { $info = pathinfo($abs_newpath); if (!file_exists($info['dirname'])) { mkdir($info['dirname'], 0750, true); } $versions = Storage::getVersions($rel_oldpath); foreach ($versions as $v) { rename($abs_oldpath . $v['version'], $abs_newpath . $v['version']); } } }
/** * @brief Erase a file's versions which exceed the set quota */ private static function expire($filename, $versionsSize = null, $offset = 0) { if (\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED) == 'true') { list($uid, $filename) = self::getUidAndFilename($filename); $versionsFileview = new \OC\Files\View('/' . $uid . '/files_versions'); // get available disk space for user $softQuota = true; $quota = \OC_Preferences::getValue($uid, 'files', 'quota'); if ($quota === null || $quota === 'default') { $quota = \OC_Appconfig::getValue('files', 'default_quota'); } if ($quota === null || $quota === 'none') { $quota = \OC\Files\Filesystem::free_space('/'); $softQuota = false; } else { $quota = \OCP\Util::computerFileSize($quota); } // make sure that we have the current size of the version history if ($versionsSize === null) { $versionsSize = self::getVersionsSize($uid); if ($versionsSize === false || $versionsSize < 0) { $versionsSize = self::calculateSize($uid); } } // calculate available space for version history // subtract size of files and current versions size from quota if ($softQuota) { $files_view = new \OC\Files\View('/' . $uid . '/files'); $rootInfo = $files_view->getFileInfo('/'); $free = $quota - $rootInfo['size']; // remaining free space for user if ($free > 0) { $availableSpace = $free * self::DEFAULTMAXSIZE / 100 - ($versionsSize + $offset); // how much space can be used for versions } else { $availableSpace = $free - $versionsSize - $offset; } } else { $availableSpace = $quota - $offset; } // with the probability of 0.1% we reduce the number of all versions not only for the current file $random = rand(0, 1000); if ($random == 0) { $allFiles = true; } else { $allFiles = false; } $allVersions = Storage::getVersions($uid, $filename); $versionsByFile[$filename] = $allVersions; $sizeOfDeletedVersions = self::delOldVersions($versionsByFile, $allVersions, $versionsFileview); $availableSpace = $availableSpace + $sizeOfDeletedVersions; $versionsSize = $versionsSize - $sizeOfDeletedVersions; // if still not enough free space we rearrange the versions from all files if ($availableSpace <= 0 || $allFiles) { $result = Storage::getAllVersions($uid); $versionsByFile = $result['by_file']; $allVersions = $result['all']; $sizeOfDeletedVersions = self::delOldVersions($versionsByFile, $allVersions, $versionsFileview); $availableSpace = $availableSpace + $sizeOfDeletedVersions; $versionsSize = $versionsSize - $sizeOfDeletedVersions; } // Check if enough space is available after versions are rearranged. // If not we delete the oldest versions until we meet the size limit for versions, // but always keep the two latest versions $numOfVersions = count($allVersions) - 2; $i = 0; while ($availableSpace < 0 && $i < $numOfVersions) { $version = current($allVersions); $versionsFileview->unlink($version['path'] . '.v' . $version['version']); $versionsSize -= $version['size']; $availableSpace += $version['size']; next($allVersions); $i++; } return $versionsSize; // finally return the new size of the version history } return false; }
/** * Erase a file's versions which exceed the set quota */ private static function expire($filename, $versionsSize = null, $offset = 0) { if (\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED) == 'true') { list($uid, $filename) = self::getUidAndFilename($filename); $versionsFileview = new \OC\Files\View('/' . $uid . '/files_versions'); // get available disk space for user $softQuota = true; $quota = \OC_Preferences::getValue($uid, 'files', 'quota'); if ($quota === null || $quota === 'default') { $quota = \OC::$server->getAppConfig()->getValue('files', 'default_quota'); } if ($quota === null || $quota === 'none') { $quota = \OC\Files\Filesystem::free_space('/'); $softQuota = false; } else { $quota = \OCP\Util::computerFileSize($quota); } // make sure that we have the current size of the version history if ($versionsSize === null) { $versionsSize = self::getVersionsSize($uid); } // calculate available space for version history // subtract size of files and current versions size from quota if ($softQuota) { $files_view = new \OC\Files\View('/' . $uid . '/files'); $rootInfo = $files_view->getFileInfo('/', false); $free = $quota - $rootInfo['size']; // remaining free space for user if ($free > 0) { $availableSpace = $free * self::DEFAULTMAXSIZE / 100 - ($versionsSize + $offset); // how much space can be used for versions } else { $availableSpace = $free - $versionsSize - $offset; } } else { $availableSpace = $quota - $offset; } $allVersions = Storage::getVersions($uid, $filename); $time = time(); list($toDelete, $sizeOfDeletedVersions) = self::getExpireList($time, $allVersions); $availableSpace = $availableSpace + $sizeOfDeletedVersions; $versionsSize = $versionsSize - $sizeOfDeletedVersions; // if still not enough free space we rearrange the versions from all files if ($availableSpace <= 0) { $result = Storage::getAllVersions($uid); $allVersions = $result['all']; foreach ($result['by_file'] as $versions) { list($toDeleteNew, $size) = self::getExpireList($time, $versions); $toDelete = array_merge($toDelete, $toDeleteNew); $sizeOfDeletedVersions += $size; } $availableSpace = $availableSpace + $sizeOfDeletedVersions; $versionsSize = $versionsSize - $sizeOfDeletedVersions; } foreach ($toDelete as $key => $path) { \OC_Hook::emit('\\OCP\\Versions', 'preDelete', array('path' => $path)); self::deleteVersion($versionsFileview, $path); \OC_Hook::emit('\\OCP\\Versions', 'delete', array('path' => $path)); unset($allVersions[$key]); // update array with the versions we keep \OCP\Util::writeLog('files_versions', "Expire: " . $path, \OCP\Util::DEBUG); } // Check if enough space is available after versions are rearranged. // If not we delete the oldest versions until we meet the size limit for versions, // but always keep the two latest versions $numOfVersions = count($allVersions) - 2; $i = 0; while ($availableSpace < 0 && $i < $numOfVersions) { $version = current($allVersions); \OC_Hook::emit('\\OCP\\Versions', 'preDelete', array('path' => $version['path'] . '.v' . $version['version'])); self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']); \OC_Hook::emit('\\OCP\\Versions', 'delete', array('path' => $version['path'] . '.v' . $version['version'])); \OCP\Util::writeLog('files_versions', 'running out of space! Delete oldest version: ' . $version['path'] . '.v' . $version['version'], \OCP\Util::DEBUG); $versionsSize -= $version['size']; $availableSpace += $version['size']; next($allVersions); $i++; } return $versionsSize; // finally return the new size of the version history } return false; }