]> source.dussan.org Git - nextcloud-server.git/commitdiff
every 1000s run reduce the number of versions for all files, not only for the current...
authorBjörn Schießle <schiessle@owncloud.com>
Wed, 9 Jan 2013 16:11:46 +0000 (17:11 +0100)
committerBjörn Schießle <schiessle@owncloud.com>
Wed, 9 Jan 2013 16:11:46 +0000 (17:11 +0100)
apps/files_versions/lib/versions.php

index ccbbf3ab2cdaab2cab480fb69fc47b611bbaddc8..e890715b5a5076f13320d5aec981d57d013f0e37 100644 (file)
@@ -16,16 +16,6 @@ namespace OCA_Versions;
 
 class Storage {
 
-
-       // config.php configuration:
-       //   - files_versions
-       //   - files_versionsfolder
-       //   - files_versionsmaxfilesize
-       //
-       // todo:
-       //   - finish porting to OC_FilesystemView to enable network transparency
-       //   - add transparent compression. first test if it´s worth it.
-
        const DEFAULTENABLED=true;
        const DEFAULTMAXSIZE=50; // unit: percentage; 50% of available disk space/quota
        
@@ -177,14 +167,14 @@ class Storage {
 
                        $files_view = new \OC_FilesystemView('/'.$uid.'/files');
                        $local_file = $files_view->getLocalFile($filename);
-                       $versions_fileview = \OCP\Files::getStorage('files_versions');
 
                        foreach( $matches as $ma ) {
 
                                $i++;
                                $versions[$i]['cur'] = 0;
                                $parts = explode( '.v', $ma );
-                               $versions[$i]['version'] = ( end( $parts ) );\r
+                               $versions[$i]['version'] = ( end( $parts ) );
+                               $versions[$i]['path'] = $filename;\r
                                $versions[$i]['size'] = $versions_fileview->filesize($filename.'.v'.$versions[$i]['version']);
 
                                // if file with modified date exists, flag it in array as currently enabled version
@@ -226,6 +216,62 @@ class Storage {
                }
 
        }
+       
+       /**
+        * @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' ) {\r
+                       $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);\r
+                       
+                       $versions = array();
+                       
+                       foreach ($iterator as $path) {
+                               if ( preg_match('/^.+\.v(\d+)$/', $path, $match) ) {
+                                       $relpath = substr($path, strlen($versionsRoot)-1);
+                                       $versions[$match[1].'#'.$relpath] = array('path' => $relpath, 'timestamp' => $match[1]);
+                               }
+                       }\r
+                       
+                       ksort($versions);
+                       
+                       $i = 0;
+                       
+                       $result = array();
+                       $file_count = array();
+                       
+                       foreach( $versions as $key => $value ) {\r
+                               $i++;
+                               $size = $versions_fileview->filesize($value['path']);
+                               $filename = substr($value['path'], 0, -strlen($value['timestamp'])-2);
+\r
+                               $result['all'][$i]['version'] = $value['timestamp'];
+                               $result['all'][$i]['path'] = $filename;\r
+                               $result['all'][$i]['size'] = $size;
+                               
+                               if ( key_exists($filename, $file_count) ) {
+                                       $c = $file_count[$filename] +1;
+                                       $file_count[$filename] = $c;
+                               } else {
+                                       $file_count[$filename] = 1;
+                                       $c = 1;
+                               }
+                               $filename = substr($value['path'], 0, -strlen($value['timestamp'])-2);
+                               $result['by_file'][$filename][$c]['version'] = $value['timestamp'];
+                               $result['by_file'][$filename][$c]['path'] = $filename;\r
+                               $result['by_file'][$filename][$c]['size'] = $size;
+                               \r
+                       }
+
+                       return $result;
+               }
+       }
 
        /**
         * @brief Erase a file's versions which exceed the set quota
@@ -248,56 +294,67 @@ class Storage {
                        $free = $quota-$rootInfo['size']; // remaining free space for user
 
                        if ( $free > 0 ) {
-                               $availableSpace = 100* self::DEFAULTMAXSIZE / ($quota-$rootInfo['size']); // how much space can be used for versions
+                               $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;
-                       
-                       $versions = Storage::getVersions($filename);
-                       $versions = array_reverse($versions);   // newest version first
+
+                       // after every 1000s run reduce the number of all versions not only for the current file 
+                       $random = rand(0, 1000);
+                       if ($random == 0) {
+                               $result = Storage::getAllVersions($uid);
+                               $versions_by_file = $result['by_file'];
+                               $all_versions = $result['all'];
+                       } else {
+                               $all_versions = Storage::getVersions($filename);
+                               $versions_by_file[$filename] = $all_versions;
+                       }
                        
                        $time = time();
-                       $numOfVersions = count($versions);
                        
-                       $interval = 1;
-                       $step = Storage::$max_versions_per_interval[$interval]['step'];                 
-                       if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) {
-                               $nextInterval = -1;
-                       } else {
-                               $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
-                       }
+                       foreach ($versions_by_file as $filename => $versions) {
+                               $versions = array_reverse($versions);   // newest version first
+                       
+                               $numOfVersions = count($versions);
+                               $interval = 1;
+                               $step = Storage::$max_versions_per_interval[$interval]['step'];                 
+                               if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1) {
+                                       $nextInterval = -1;
+                               } else {
+                                       $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
+                               }
                                                
-                       $nextVersion = $versions[0]['version'] - $step;
+                               $nextVersion = $versions[0]['version'] - $step;
                        
-                       for ($i=1; $i<$numOfVersions; $i++) {
-                               if ( $nextInterval == -1 || $versions[$i]['version'] >= $nextInterval ) {
-                                       if ( $versions[$i]['version'] > $nextVersion ) {
-                                               //distance between two version to small, delete version
-                                               $versions_fileview->unlink($filename.'.v'.$versions[$i]['version']);
-                                               $availableSpace += $versions[$i]['size'];
-                                       } else {
+                               for ($i=1; $i<$numOfVersions; $i++) {
+                                       if ( $nextInterval == -1 || $versions[$i]['version'] >= $nextInterval ) {
+                                               if ( $versions[$i]['version'] > $nextVersion ) {
+                                                       //distance between two version to small, delete version
+                                                       $versions_fileview->unlink($versions[$i]['path'].'.v'.$versions[$i]['version']);
+                                                       $availableSpace += $versions[$i]['size'];
+                                               } else {
+                                                       $nextVersion = $versions[$i]['version'] - $step;
+                                               }
+                                       } else { // time to move on to the next interval
+                                               $interval++;
+                                               $i--; // need to go one version back to check the same version against the new interval.
+                                               $step = Storage::$max_versions_per_interval[$interval]['step'];
                                                $nextVersion = $versions[$i]['version'] - $step;
-                                       }
-                               } else { // time to move on to the next interval
-                                       $interval++;
-                                       $step = Storage::$max_versions_per_interval[$interval]['step'];
-                                       $nextVersion = $versions[$i]['version'] - $step;
-                                       if ( Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1 ) {
-                                               $nextInterval = -1;
-                                       } else {\r
-                                               $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
+                                               if ( Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] == -1 ) {
+                                                       $nextInterval = -1;
+                                               } else {\r
+                                                       $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
+                                               }
                                        }
                                }
                        }
-                       
                        // check if enough space is available after versions are rearranged
-                       $versions = array_reverse( $versions ); // oldest version first
-                       $numOfVersions = count($versions);
+                       $numOfVersions = count($all_versions);
                        $i = 0; 
                        while ($availableSpace < 0) {
-                               $versions_fileview->unlink($filename.'.v'.$versions[$i]['version']);
-                               $availableSpace += $versions[$i]['size'];
+                               $versions_fileview->unlink($all_versions[$i]['path'].'.v'.$all_versions[$i]['version']);
+                               $availableSpace += $all_versions[$i]['size'];
                                $i++;
                                if ($i = $numOfVersions-2) break; // keep at least the last version
                        }
                }
        }
-}
\ No newline at end of file
+}