summaryrefslogtreecommitdiff
path: root/nix/libstore/optimise-store.cc
diff options
context:
space:
mode:
authorCongcong Kuo <congcong.kuo@gmail.com>2025-07-21 11:02:40 +0800
committerLudovic Courtès <ludo@gnu.org>2025-10-19 21:29:39 +0200
commit3af52f845fe2ceb448416ac7b9f48925673c594e (patch)
treec8623599d15363a8e760adf1ad9dd01477ceabd7 /nix/libstore/optimise-store.cc
parentcbda925613b2962db8c6dbb2ea3dda7e3b433611 (diff)
daemon: Bump to C++20 and use ‘std::format’ instead of ‘boost::format’.
* nix/boost: This directory and all files inside it are removed. * nix/libstore/build.cc (Goal::trace): Use ‘std::string’ instead of ‘const format &’. (DerivationGoal::startBuilder, ...): Use ‘std::format’ or ‘std::vformat’ instead of ‘boost::format’. * nix/libstore/builtins.cc (builtinDownload): Same. * nix/libstore/derivations.cc (DerivationOutput::parseHashInfo, ...): Same. * nix/libstore/gc.cc (LocalStore::openGCLock, ...): Same. * nix/libstore/globals.cc (Settings::_get): Same. * nix/libstore/local-store.cc: (checkStoreNotSymlink, ...): Same. * nix/libstore/misc.cc (dfsVisit, showBytes): Same * nix/libstore/optimise-store.cc (makeWritable, ...): Same. * nix/libstore/pathlocks.cc (openLockFile, ...): Same. * nix/libstore/references.cc (search, scanForReferences): Same. * nix/libstore/sqlite.hh (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/sqlite.cc (throwSQLiteError): Use ‘std::string’ instead of ‘const format &’. * nix/libstore/store-api.cc (assertStorePath, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/affinity.cc (setAffinityTo): Same. * nix/libutil/archive.cc (dumpContents, ...): Same. * nix/libutil/hash.cc (parseHash, parseHash32, parseHash16or32, hashFile): Same. * nix/libutil/hash.hh (parseHash, parseHash32, parseHash16or32, isHash): Same. * nix/libutil/serialise.cc : Add ‘<cassert>’ header file. * nix/libutil/spawn.cc (addPhaseAfter, ...): Use ‘std::format’ instead of ‘boost::format’. * nix/libutil/types.hh (FormatOrString): Removed. (BaseError, BaseError::addPrefix, SysError, MakeError): Use ‘std::string or std::string_view’ instead of ‘FormatOrString’. * nix/libutil/util.hh (Nest::open, printMsg_, warnOnce, expect): Same. * nix/libutil/util.cc (BaseError::BaseError, ...): Same. (writeToStderr, _interrupted): Use std::uncaught_exceptions() instead of std::uncaught_exception() * nix/nix-daemon/nix-daemon.cc (performOp, ...): Same. * nix/nix-daemon/guix-daemon.cc (string_to_bool, ...): Same. * nix/local.mk: Remove ‘libformat.a’ from ‘noinst_LIBRARIES’, remove ‘libformat_a_SOURCES’ and ‘libformat_headers’, remove ‘libformat_a_CPPFLAGS’ from ‘libutil_a_CPPFLAGS’ and ‘guix_daemon_LDADD’, update ‘AM_CXXFLAGS’ to ‘-std=c++20’. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
Diffstat (limited to 'nix/libstore/optimise-store.cc')
-rw-r--r--nix/libstore/optimise-store.cc61
1 files changed, 30 insertions, 31 deletions
diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc
index e17d9160d6c..d69c43e9978 100644
--- a/nix/libstore/optimise-store.cc
+++ b/nix/libstore/optimise-store.cc
@@ -12,7 +12,7 @@
12#include <unistd.h> 12#include <unistd.h>
13#include <errno.h> 13#include <errno.h>
14#include <stdio.h> 14#include <stdio.h>
15 15#include <format>
16 16
17namespace nix { 17namespace nix {
18 18
@@ -24,9 +24,9 @@ static void makeWritable(const Path & path)
24{ 24{
25 struct stat st; 25 struct stat st;
26 if (lstat(path.c_str(), &st)) 26 if (lstat(path.c_str(), &st))
27 throw SysError(format("getting attributes of path `%1%'") % path); 27 throw SysError(std::format("getting attributes of path `{}'", path));
28 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) 28 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
29 throw SysError(format("changing writability of `%1%'") % path); 29 throw SysError(std::format("changing writability of `{}'", path));
30} 30}
31 31
32 32
@@ -52,7 +52,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
52 InodeHash inodeHash; 52 InodeHash inodeHash;
53 53
54 AutoCloseDir dir = opendir(linksDir.c_str()); 54 AutoCloseDir dir = opendir(linksDir.c_str());
55 if (!dir) throw SysError(format("opening directory `%1%'") % linksDir); 55 if (!dir) throw SysError(std::format("opening directory `{}'", linksDir));
56 56
57 struct dirent * dirent; 57 struct dirent * dirent;
58 while (errno = 0, dirent = readdir(dir)) { /* sic */ 58 while (errno = 0, dirent = readdir(dir)) { /* sic */
@@ -60,9 +60,9 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
60 // We don't care if we hit non-hash files, anything goes 60 // We don't care if we hit non-hash files, anything goes
61 inodeHash.insert(dirent->d_ino); 61 inodeHash.insert(dirent->d_ino);
62 } 62 }
63 if (errno) throw SysError(format("reading directory `%1%'") % linksDir); 63 if (errno) throw SysError(std::format("reading directory `{}'", linksDir));
64 64
65 printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size()); 65 printMsg(lvlTalkative, std::format("loaded {} hash inodes", inodeHash.size()));
66 66
67 return inodeHash; 67 return inodeHash;
68} 68}
@@ -73,14 +73,14 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
73 Strings names; 73 Strings names;
74 74
75 AutoCloseDir dir = opendir(path.c_str()); 75 AutoCloseDir dir = opendir(path.c_str());
76 if (!dir) throw SysError(format("opening directory `%1%'") % path); 76 if (!dir) throw SysError(std::format("opening directory `{}'", path));
77 77
78 struct dirent * dirent; 78 struct dirent * dirent;
79 while (errno = 0, dirent = readdir(dir)) { /* sic */ 79 while (errno = 0, dirent = readdir(dir)) { /* sic */
80 checkInterrupt(); 80 checkInterrupt();
81 81
82 if (inodeHash.count(dirent->d_ino)) { 82 if (inodeHash.count(dirent->d_ino)) {
83 printMsg(lvlDebug, format("`%1%' is already linked") % dirent->d_name); 83 printMsg(lvlDebug, std::format("`{}' is already linked", dirent->d_name));
84 continue; 84 continue;
85 } 85 }
86 86
@@ -88,7 +88,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
88 if (name == "." || name == "..") continue; 88 if (name == "." || name == "..") continue;
89 names.push_back(name); 89 names.push_back(name);
90 } 90 }
91 if (errno) throw SysError(format("reading directory `%1%'") % path); 91 if (errno) throw SysError(std::format("reading directory `{}'", path));
92 92
93 return names; 93 return names;
94} 94}
@@ -100,7 +100,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
100 100
101 struct stat st; 101 struct stat st;
102 if (lstat(path.c_str(), &st)) 102 if (lstat(path.c_str(), &st))
103 throw SysError(format("getting attributes of path `%1%'") % path); 103 throw SysError(std::format("getting attributes of path `{}'", path));
104 104
105 if (S_ISDIR(st.st_mode)) { 105 if (S_ISDIR(st.st_mode)) {
106 Strings names = readDirectoryIgnoringInodes(path, inodeHash); 106 Strings names = readDirectoryIgnoringInodes(path, inodeHash);
@@ -121,13 +121,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
121 Guix System (example: $fontconfig/var/cache being modified). Skip 121 Guix System (example: $fontconfig/var/cache being modified). Skip
122 those files. FIXME: check the modification time. */ 122 those files. FIXME: check the modification time. */
123 if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) { 123 if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
124 printMsg(lvlError, format("skipping suspicious writable file `%1%'") % path); 124 printMsg(lvlError, std::format("skipping suspicious writable file `{}'", path));
125 return; 125 return;
126 } 126 }
127 127
128 /* This can still happen on top-level files. */ 128 /* This can still happen on top-level files. */
129 if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) { 129 if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
130 printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2)); 130 printMsg(lvlDebug, std::format("`{}' is already linked, with {} other file(s).", path, (st.st_nlink - 2)));
131 return; 131 return;
132 } 132 }
133 133
@@ -141,7 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
141 contents of the symlink (i.e. the result of readlink()), not 141 contents of the symlink (i.e. the result of readlink()), not
142 the contents of the target (which may not even exist). */ 142 the contents of the target (which may not even exist). */
143 Hash hash = hashPath(htSHA256, path).first; 143 Hash hash = hashPath(htSHA256, path).first;
144 printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash)); 144 printMsg(lvlDebug, std::format("`{}' has hash `{}'", path, printHash(hash)));
145 145
146 /* Check if this is a known hash. */ 146 /* Check if this is a known hash. */
147 Path linkPath = linksDir + "/" + printHash32(hash); 147 Path linkPath = linksDir + "/" + printHash32(hash);
@@ -164,12 +164,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
164 /* On ext4, that probably means the directory index is full. When 164 /* On ext4, that probably means the directory index is full. When
165 that happens, it's fine to ignore it: we just effectively 165 that happens, it's fine to ignore it: we just effectively
166 disable deduplication of this file. */ 166 disable deduplication of this file. */
167 printMsg(lvlInfo, format("cannot link `%1%' to `%2%': %3%") 167 printMsg(lvlInfo, std::format("cannot link `{}' to `{}': {}",
168 % linkPath % path % strerror(ENOSPC)); 168 linkPath, path, strerror(ENOSPC)));
169 return; 169 return;
170 170
171 default: 171 default:
172 throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path); 172 throw SysError(std::format("cannot link `{}' to `{}'", linkPath, path));
173 } 173 }
174 } 174 }
175 175
@@ -177,20 +177,20 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
177 current file with a hard link to that file. */ 177 current file with a hard link to that file. */
178 struct stat stLink; 178 struct stat stLink;
179 if (lstat(linkPath.c_str(), &stLink)) 179 if (lstat(linkPath.c_str(), &stLink))
180 throw SysError(format("getting attributes of path `%1%'") % linkPath); 180 throw SysError(std::format("getting attributes of path `{}'", linkPath));
181 181
182 if (st.st_ino == stLink.st_ino) { 182 if (st.st_ino == stLink.st_ino) {
183 printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % linkPath); 183 printMsg(lvlDebug, std::format("`{}' is already linked to `{}'", path, linkPath));
184 return; 184 return;
185 } 185 }
186 186
187 if (st.st_size != stLink.st_size) { 187 if (st.st_size != stLink.st_size) {
188 printMsg(lvlError, format("removing corrupted link %1%") % linkPath); 188 printMsg(lvlError, std::format("removing corrupted link `%1%'", linkPath));
189 unlink(linkPath.c_str()); 189 unlink(linkPath.c_str());
190 goto retry; 190 goto retry;
191 } 191 }
192 192
193 printMsg(lvlTalkative, format("linking %1% to %2%") % path % linkPath); 193 printMsg(lvlTalkative, std::format("linking `%1%' to `%2%'", path, linkPath));
194 194
195 /* Make the containing directory writable, but only if it's not 195 /* Make the containing directory writable, but only if it's not
196 the store itself (we don't want or need to mess with its 196 the store itself (we don't want or need to mess with its
@@ -202,8 +202,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
202 its timestamp back to 0. */ 202 its timestamp back to 0. */
203 MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : ""); 203 MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
204 204
205 Path tempLink = (format("%1%/.tmp-link-%2%-%3%") 205 Path tempLink = std::format("{}/.tmp-link-{}-{}", settings.nixStore, getpid(), rand());
206 % settings.nixStore % getpid() % rand()).str();
207 206
208 if (link(linkPath.c_str(), tempLink.c_str()) == -1) { 207 if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
209 if (errno == EMLINK) { 208 if (errno == EMLINK) {
@@ -211,27 +210,27 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
211 systems). This is likely to happen with empty files. 210 systems). This is likely to happen with empty files.
212 Just shrug and ignore. */ 211 Just shrug and ignore. */
213 if (st.st_size) 212 if (st.st_size)
214 printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath); 213 printMsg(lvlInfo, std::format("`{}' has maximum number of links", linkPath));
215 return; 214 return;
216 } 215 }
217 throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath); 216 throw SysError(std::format("cannot link `{}' to `{}'", tempLink, linkPath));
218 } 217 }
219 218
220 /* Atomically replace the old file with the new hard link. */ 219 /* Atomically replace the old file with the new hard link. */
221 if (rename(tempLink.c_str(), path.c_str()) == -1) { 220 if (rename(tempLink.c_str(), path.c_str()) == -1) {
222 int renameErrno = errno; 221 int renameErrno = errno;
223 if (unlink(tempLink.c_str()) == -1) 222 if (unlink(tempLink.c_str()) == -1)
224 printMsg(lvlError, format("unable to unlink `%1%'") % tempLink); 223 printMsg(lvlError, std::format("unable to unlink `{}'", tempLink));
225 if (renameErrno == EMLINK) { 224 if (renameErrno == EMLINK) {
226 /* Some filesystems generate too many links on the rename, 225 /* Some filesystems generate too many links on the rename,
227 rather than on the original link. (Probably it 226 rather than on the original link. (Probably it
228 temporarily increases the st_nlink field before 227 temporarily increases the st_nlink field before
229 decreasing it again.) */ 228 decreasing it again.) */
230 if (st.st_size) 229 if (st.st_size)
231 printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath); 230 printMsg(lvlInfo, std::format("`{}' has maximum number of links", linkPath));
232 return; 231 return;
233 } 232 }
234 throw SysError(format("cannot rename `%1%' to `%2%'") % tempLink % path); 233 throw SysError(std::format("cannot rename `{}' to `{}'", tempLink, path));
235 } 234 }
236 235
237 stats.filesLinked++; 236 stats.filesLinked++;
@@ -248,7 +247,7 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
248 for (auto& i : paths) { 247 for (auto& i : paths) {
249 addTempRoot(i); 248 addTempRoot(i);
250 if (!isValidPath(i)) continue; /* path was GC'ed, probably */ 249 if (!isValidPath(i)) continue; /* path was GC'ed, probably */
251 startNest(nest, lvlChatty, format("hashing files in `%1%'") % i); 250 startNest(nest, lvlChatty, std::format("hashing files in `{}'", i));
252 optimisePath_(stats, i, inodeHash); 251 optimisePath_(stats, i, inodeHash);
253 } 252 }
254} 253}
@@ -260,9 +259,9 @@ void LocalStore::optimiseStore()
260 optimiseStore(stats); 259 optimiseStore(stats);
261 260
262 printMsg(lvlError, 261 printMsg(lvlError,
263 format("%1% freed by hard-linking %2% files") 262 std::format("{} freed by hard-linking {} files",
264 % showBytes(stats.bytesFreed) 263 showBytes(stats.bytesFreed),
265 % stats.filesLinked); 264 stats.filesLinked));
266} 265}
267 266
268void LocalStore::optimisePath(const Path & path) 267void LocalStore::optimisePath(const Path & path)