[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
59/64: Shortcut store files before lstat
From: |
Ludovic Courtès |
Subject: |
59/64: Shortcut store files before lstat |
Date: |
Mon, 05 Jan 2015 16:39:12 +0000 |
civodul pushed a commit to branch nix
in repository guix.
commit 3b9ea8452f102595874826e349fa38f85c00aa39
Author: Wout Mertens <address@hidden>
Date: Thu May 15 09:02:22 2014 +0200
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.
---
src/libstore/local-store.hh | 1 +
src/libstore/optimise-store.cc | 45 ++++++++++++++++++++++++++++++++--------
2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index b335092..487bb71 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -315,6 +315,7 @@ private:
#endif
InodeHash loadInodeHash();
+ Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash &
inodeHash, OptimiseStats & stats);
void optimisePath_(OptimiseStats & stats, const Path & path, InodeHash &
inodeHash);
// Internal versions that are not wrapped in retry_sqlite.
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index ed41801..3615bc3 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -42,7 +42,7 @@ struct MakeReadOnly
LocalStore::InodeHash LocalStore::loadInodeHash()
{
printMsg(lvlDebug, "loading hash inodes in memory");
- InodeHash hashes;
+ InodeHash inodeHash;
AutoCloseDir dir = opendir(linksDir.c_str());
if (!dir) throw SysError(format("opening directory `%1%'") % linksDir);
@@ -51,16 +51,42 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
while (errno = 0, dirent = readdir(dir)) { /* sic */
checkInterrupt();
// 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);
- printMsg(lvlInfo, format("loaded %1% hash inodes") % hashes.size());
+ printMsg(lvlInfo, format("loaded %1% hash inodes") % inodeHash.size());
+
+ return inodeHash;
+}
+
+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 hashes;
+ return names;
}
-void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path,
InodeHash & hashes)
+void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path,
InodeHash & inodeHash)
{
checkInterrupt();
@@ -69,9 +95,9 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const
Path & path, InodeHa
throw SysError(format("getting attributes of path `%1%'") % path);
if (S_ISDIR(st.st_mode)) {
- Strings names = readDirectory(path);
+ Strings names = readDirectoryIgnoringInodes(path, inodeHash, stats);
foreach (Strings::iterator, i, names)
- optimisePath_(stats, path + "/" + *i, hashes);
+ optimisePath_(stats, path + "/" + *i, inodeHash);
return;
}
@@ -93,7 +119,8 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const
Path & path, InodeHa
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));
return;
}
@@ -116,7 +143,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const
Path & path, InodeHa
if (!pathExists(linkPath)) {
/* Nope, create a hard link in the links directory. */
if (link(path.c_str(), linkPath.c_str()) == 0) {
- hashes.insert(st.st_ino);
+ inodeHash.insert(st.st_ino);
return;
}
if (errno != EEXIST)
- 52/64: Shortcut already-hardlinked files, (continued)
- 52/64: Shortcut already-hardlinked files, Ludovic Courtès, 2015/01/05
- 54/64: nix-instantiate --eval: Apply auto-arguments if the result is a function, Ludovic Courtès, 2015/01/05
- 47/64: Fix Debian tests, Ludovic Courtès, 2015/01/05
- 60/64: Merge branch 'master' of github.com:wmertens/nix, Ludovic Courtès, 2015/01/05
- 58/64: Use the inodes given by readdir directly, Ludovic Courtès, 2015/01/05
- 57/64: Remove redundant code, Ludovic Courtès, 2015/01/05
- 55/64: Prepare nix-mode to be uploaded to marmalade, Ludovic Courtès, 2015/01/05
- 56/64: Preload linked hashes to speed up lookups, Ludovic Courtès, 2015/01/05
- 63/64: lvlInfo -> lvlTalkative, Ludovic Courtès, 2015/01/05
- 42/64: When running as root, use build users by default, Ludovic Courtès, 2015/01/05
- 59/64: Shortcut store files before lstat,
Ludovic Courtès <=
- 64/64: Merge commit '8d5f472f2c49c79a0d3ae2e506f4d4d76224b328' into nix, Ludovic Courtès, 2015/01/05
- 61/64: Remove tab, Ludovic Courtès, 2015/01/05
- 62/64: nix-store --optimise: Remove bogus statistics, Ludovic Courtès, 2015/01/05