Shortcut store files before lstat
readdir() already returns the inode numbers, so we don't need to call lstat to know if a file was already linked or not.
This commit is contained in:
		
							parent
							
								
									d73ffc552f
								
							
						
					
					
						commit
						3b9ea8452f
					
				
					 2 changed files with 37 additions and 9 deletions
				
			
		|  | @ -315,6 +315,7 @@ private: | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     InodeHash loadInodeHash(); |     InodeHash loadInodeHash(); | ||||||
|  |     Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash, OptimiseStats & stats); | ||||||
|     void optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & inodeHash); |     void optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & inodeHash); | ||||||
| 
 | 
 | ||||||
|     // Internal versions that are not wrapped in retry_sqlite.
 |     // Internal versions that are not wrapped in retry_sqlite.
 | ||||||
|  |  | ||||||
|  | @ -42,7 +42,7 @@ struct MakeReadOnly | ||||||
| LocalStore::InodeHash LocalStore::loadInodeHash() | LocalStore::InodeHash LocalStore::loadInodeHash() | ||||||
| { | { | ||||||
|     printMsg(lvlDebug, "loading hash inodes in memory"); |     printMsg(lvlDebug, "loading hash inodes in memory"); | ||||||
|     InodeHash hashes; |     InodeHash inodeHash; | ||||||
| 
 | 
 | ||||||
|     AutoCloseDir dir = opendir(linksDir.c_str()); |     AutoCloseDir dir = opendir(linksDir.c_str()); | ||||||
|     if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); |     if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); | ||||||
|  | @ -51,16 +51,42 @@ LocalStore::InodeHash LocalStore::loadInodeHash() | ||||||
|     while (errno = 0, dirent = readdir(dir)) { /* sic */ |     while (errno = 0, dirent = readdir(dir)) { /* sic */ | ||||||
|         checkInterrupt(); |         checkInterrupt(); | ||||||
|         // We don't care if we hit non-hash files, anything goes
 |         // We don't care if we hit non-hash files, anything goes
 | ||||||
|         hashes.insert(dirent->d_ino); |         inodeHash.insert(dirent->d_ino); | ||||||
|     } |     } | ||||||
|     if (errno) throw SysError(format("reading directory `%1%'") % linksDir); |     if (errno) throw SysError(format("reading directory `%1%'") % linksDir); | ||||||
| 
 | 
 | ||||||
|     printMsg(lvlInfo, format("loaded %1% hash inodes") % hashes.size()); |     printMsg(lvlInfo, format("loaded %1% hash inodes") % inodeHash.size()); | ||||||
| 
 | 
 | ||||||
|     return hashes; |     return inodeHash; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & hashes) | Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash, OptimiseStats & stats) | ||||||
|  | { | ||||||
|  |     Strings names; | ||||||
|  | 
 | ||||||
|  |     AutoCloseDir dir = opendir(path.c_str()); | ||||||
|  |     if (!dir) throw SysError(format("opening directory `%1%'") % path); | ||||||
|  | 
 | ||||||
|  |     struct dirent * dirent; | ||||||
|  |     while (errno = 0, dirent = readdir(dir)) { /* sic */ | ||||||
|  |         checkInterrupt(); | ||||||
|  | 
 | ||||||
|  |         if (inodeHash.count(dirent->d_ino)) { | ||||||
|  |             printMsg(lvlDebug, format("`%1%' is already linked") % dirent->d_name); | ||||||
|  |             stats.totalFiles++; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         string name = dirent->d_name; | ||||||
|  |         if (name == "." || name == "..") continue; | ||||||
|  |         names.push_back(name); | ||||||
|  |     } | ||||||
|  |     if (errno) throw SysError(format("reading directory `%1%'") % path); | ||||||
|  | 
 | ||||||
|  |     return names; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & inodeHash) | ||||||
| { | { | ||||||
|     checkInterrupt(); |     checkInterrupt(); | ||||||
|      |      | ||||||
|  | @ -69,9 +95,9 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa | ||||||
|         throw SysError(format("getting attributes of path `%1%'") % path); |         throw SysError(format("getting attributes of path `%1%'") % path); | ||||||
| 
 | 
 | ||||||
|     if (S_ISDIR(st.st_mode)) { |     if (S_ISDIR(st.st_mode)) { | ||||||
|         Strings names = readDirectory(path); |         Strings names = readDirectoryIgnoringInodes(path, inodeHash, stats); | ||||||
|         foreach (Strings::iterator, i, names) |         foreach (Strings::iterator, i, names) | ||||||
|             optimisePath_(stats, path + "/" + *i, hashes); |             optimisePath_(stats, path + "/" + *i, inodeHash); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -93,7 +119,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa | ||||||
| 
 | 
 | ||||||
|     stats.totalFiles++; |     stats.totalFiles++; | ||||||
| 
 | 
 | ||||||
|     if (st.st_nlink > 1 && hashes.count(st.st_ino)) { |     /* This can still happen on top-level files */ | ||||||
|  |     if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) { | ||||||
|         printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2)); |         printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2)); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  | @ -116,7 +143,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa | ||||||
|     if (!pathExists(linkPath)) { |     if (!pathExists(linkPath)) { | ||||||
|         /* Nope, create a hard link in the links directory. */ |         /* Nope, create a hard link in the links directory. */ | ||||||
|         if (link(path.c_str(), linkPath.c_str()) == 0) { |         if (link(path.c_str(), linkPath.c_str()) == 0) { | ||||||
|             hashes.insert(st.st_ino); |             inodeHash.insert(st.st_ino); | ||||||
|             return; |             return; | ||||||
| 	} | 	} | ||||||
|         if (errno != EEXIST) |         if (errno != EEXIST) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue