* Garbage collector: option `--max-freed' to stop after at least N
bytes have been freed, `--max-links' to stop when the Nix store directory has fewer than N hard links (the latter being important for very large Nix stores on filesystems with a 32000 subdirectories limit).
This commit is contained in:
		
							parent
							
								
									a8f3b02092
								
							
						
					
					
						commit
						d3aa183beb
					
				
					 6 changed files with 47 additions and 12 deletions
				
			
		|  | @ -58,7 +58,7 @@ static void setLogType(string lt) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static unsigned int getIntArg(const string & opt, | unsigned int getIntArg(const string & opt, | ||||||
|     Strings::iterator & i, const Strings::iterator & end) |     Strings::iterator & i, const Strings::iterator & end) | ||||||
| { | { | ||||||
|     ++i; |     ++i; | ||||||
|  |  | ||||||
|  | @ -26,6 +26,9 @@ namespace nix { | ||||||
| Path makeRootName(const Path & gcRoot, int & counter); | Path makeRootName(const Path & gcRoot, int & counter); | ||||||
| void printGCWarning(); | void printGCWarning(); | ||||||
| 
 | 
 | ||||||
|  | unsigned int getIntArg(const string & opt, | ||||||
|  |     Strings::iterator & i, const Strings::iterator & end); | ||||||
|  | 
 | ||||||
| /* Whether we're running setuid. */ | /* Whether we're running setuid. */ | ||||||
| extern bool setuidMode; | extern bool setuidMode; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -439,6 +439,9 @@ Paths topoSortPaths(const PathSet & paths) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | struct GCLimitReached { }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,  | void LocalStore::tryToDelete(const GCOptions & options, GCResults & results,  | ||||||
|     const PathSet & livePaths, const PathSet & tempRootsClosed, PathSet & done,  |     const PathSet & livePaths, const PathSet & tempRootsClosed, PathSet & done,  | ||||||
|     const Path & path) |     const Path & path) | ||||||
|  | @ -512,6 +515,21 @@ void LocalStore::tryToDelete(const GCOptions & options, GCResults & results, | ||||||
|     results.bytesFreed += bytesFreed; |     results.bytesFreed += bytesFreed; | ||||||
|     results.blocksFreed += blocksFreed; |     results.blocksFreed += blocksFreed; | ||||||
| 
 | 
 | ||||||
|  |     if (results.bytesFreed > options.maxFreed) { | ||||||
|  |         printMsg(lvlInfo, format("deleted more than %1% bytes; stopping") % options.maxFreed); | ||||||
|  |         throw GCLimitReached(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (options.maxLinks) { | ||||||
|  |         struct stat st; | ||||||
|  |         if (stat(nixStore.c_str(), &st) == -1) | ||||||
|  |             throw SysError(format("statting `%1%'") % nixStore); | ||||||
|  |         if (st.st_nlink < options.maxLinks) { | ||||||
|  |             printMsg(lvlInfo, format("link count on the store has dropped below %1%; stopping") % options.maxLinks); | ||||||
|  |             throw GCLimitReached(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| #ifndef __CYGWIN__ | #ifndef __CYGWIN__ | ||||||
|     if (fdLock != -1) |     if (fdLock != -1) | ||||||
|         /* Write token to stale (deleted) lock file. */ |         /* Write token to stale (deleted) lock file. */ | ||||||
|  | @ -650,8 +668,11 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) | ||||||
|         : format("deleting garbage...")); |         : format("deleting garbage...")); | ||||||
| 
 | 
 | ||||||
|     PathSet done; |     PathSet done; | ||||||
|  |     try { | ||||||
|         foreach (PathSet::iterator, i, storePaths) |         foreach (PathSet::iterator, i, storePaths) | ||||||
|             tryToDelete(options, results, livePaths, tempRootsClosed, done, *i); |             tryToDelete(options, results, livePaths, tempRootsClosed, done, *i); | ||||||
|  |     } catch (GCLimitReached & e) { | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|   |   | ||||||
|  |  | ||||||
|  | @ -2,10 +2,21 @@ | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
| 
 | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | GCOptions::GCOptions() | ||||||
|  | { | ||||||
|  |     action = gcDeleteDead; | ||||||
|  |     ignoreLiveness = false; | ||||||
|  |     maxFreed = ULLONG_MAX; | ||||||
|  |     maxLinks = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| bool StoreAPI::hasSubstitutes(const Path & path) | bool StoreAPI::hasSubstitutes(const Path & path) | ||||||
| { | { | ||||||
|     PathSet paths = querySubstitutablePaths(); |     PathSet paths = querySubstitutablePaths(); | ||||||
|  |  | ||||||
|  | @ -60,16 +60,10 @@ struct GCOptions | ||||||
|     unsigned long long maxFreed; |     unsigned long long maxFreed; | ||||||
| 
 | 
 | ||||||
|     /* Stop after the number of hard links to the Nix store directory
 |     /* Stop after the number of hard links to the Nix store directory
 | ||||||
|        has dropped to at least `maxLinks'. */ |        has dropped below `maxLinks'. */ | ||||||
|     unsigned int maxLinks; |     unsigned int maxLinks; | ||||||
| 
 | 
 | ||||||
|     GCOptions()  |     GCOptions(); | ||||||
|     { |  | ||||||
|         action = gcDeleteDead; |  | ||||||
|         ignoreLiveness = false; |  | ||||||
|         maxFreed = ULLONG_MAX; |  | ||||||
|         maxLinks = UINT_MAX; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -528,6 +528,8 @@ static void opGC(Strings opFlags, Strings opArgs) | ||||||
|         else if (*i == "--print-live") options.action = GCOptions::gcReturnLive; |         else if (*i == "--print-live") options.action = GCOptions::gcReturnLive; | ||||||
|         else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead; |         else if (*i == "--print-dead") options.action = GCOptions::gcReturnDead; | ||||||
|         else if (*i == "--delete") options.action = GCOptions::gcDeleteDead; |         else if (*i == "--delete") options.action = GCOptions::gcDeleteDead; | ||||||
|  |         else if (*i == "--max-freed") options.maxFreed = getIntArg(*i, i, opFlags.end()); | ||||||
|  |         else if (*i == "--max-links") options.maxLinks = getIntArg(*i, i, opFlags.end()); | ||||||
|         else throw UsageError(format("bad sub-operation `%1%' in GC") % *i); |         else throw UsageError(format("bad sub-operation `%1%' in GC") % *i); | ||||||
| 
 | 
 | ||||||
|     PrintFreed freed( |     PrintFreed freed( | ||||||
|  | @ -744,8 +746,12 @@ void run(Strings args) | ||||||
|         } |         } | ||||||
|         else if (arg == "--indirect") |         else if (arg == "--indirect") | ||||||
|             indirectRoot = true; |             indirectRoot = true; | ||||||
|         else if (arg[0] == '-') |         else if (arg[0] == '-') {             | ||||||
|             opFlags.push_back(arg); |             opFlags.push_back(arg); | ||||||
|  |             if (arg == "--max-freed" || arg == "--max-links") { /* !!! hack */ | ||||||
|  |                 if (i != args.end()) opFlags.push_back(*i++); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         else |         else | ||||||
|             opArgs.push_back(arg); |             opArgs.push_back(arg); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue