* importPath() -> importPaths(). Because of buffering of the input

stream it's now necessary for the daemon to process the entire
  sequence of exported paths, rather than letting the client do it.
This commit is contained in:
Eelco Dolstra 2011-12-16 22:31:25 +00:00
parent 8d3dfa2c17
commit 273b288a7e
10 changed files with 75 additions and 57 deletions

View File

@ -1156,7 +1156,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
PathSet references; PathSet references;
queryReferences(path, references); queryReferences(path, references);
writeStringSet(references, hashAndWriteSink); writeStrings(references, hashAndWriteSink);
Path deriver = queryDeriver(path); Path deriver = queryDeriver(path);
writeString(deriver, hashAndWriteSink); writeString(deriver, hashAndWriteSink);
@ -1243,7 +1243,7 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
Path dstPath = readStorePath(hashAndReadSource); Path dstPath = readStorePath(hashAndReadSource);
PathSet references = readStorePaths(hashAndReadSource); PathSet references = readStorePaths<PathSet>(hashAndReadSource);
Path deriver = readString(hashAndReadSource); Path deriver = readString(hashAndReadSource);
if (deriver != "") assertStorePath(deriver); if (deriver != "") assertStorePath(deriver);
@ -1330,6 +1330,19 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
} }
Paths LocalStore::importPaths(bool requireSignature, Source & source)
{
Paths res;
while (true) {
unsigned long long n = readLongLong(source);
if (n == 0) break;
if (n != 1) throw Error("input doesn't look like something created by `nix-store --export'");
res.push_back(importPath(requireSignature, source));
}
return res;
}
void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFreed, void LocalStore::deleteFromStore(const Path & path, unsigned long long & bytesFreed,
unsigned long long & blocksFreed) unsigned long long & blocksFreed)
{ {

View File

@ -146,7 +146,7 @@ public:
void exportPath(const Path & path, bool sign, void exportPath(const Path & path, bool sign,
Sink & sink); Sink & sink);
Path importPath(bool requireSignature, Source & source); Paths importPaths(bool requireSignature, Source & source);
void buildDerivations(const PathSet & drvPaths); void buildDerivations(const PathSet & drvPaths);
@ -259,6 +259,8 @@ private:
Path createTempDirInStore(); Path createTempDirInStore();
Path importPath(bool requireSignature, Source & source);
void checkDerivationOutputs(const Path & drvPath, const Derivation & drv); void checkDerivationOutputs(const Path & drvPath, const Derivation & drv);
}; };

View File

@ -27,13 +27,15 @@ Path readStorePath(Source & from)
} }
PathSet readStorePaths(Source & from) template<class T> T readStorePaths(Source & from)
{ {
PathSet paths = readStringSet(from); T paths = readStrings<T>(from);
foreach (PathSet::iterator, i, paths) assertStorePath(*i); foreach (typename T::iterator, i, paths) assertStorePath(*i);
return paths; return paths;
} }
template PathSet readStorePaths(Source & from);
RemoteStore::RemoteStore() RemoteStore::RemoteStore()
{ {
@ -215,7 +217,7 @@ PathSet RemoteStore::queryValidPaths()
openConnection(); openConnection();
writeInt(wopQueryValidPaths, to); writeInt(wopQueryValidPaths, to);
processStderr(); processStderr();
return readStorePaths(from); return readStorePaths<PathSet>(from);
} }
@ -242,7 +244,7 @@ bool RemoteStore::querySubstitutablePathInfo(const Path & path,
if (reply == 0) return false; if (reply == 0) return false;
info.deriver = readString(from); info.deriver = readString(from);
if (info.deriver != "") assertStorePath(info.deriver); if (info.deriver != "") assertStorePath(info.deriver);
info.references = readStorePaths(from); info.references = readStorePaths<PathSet>(from);
info.downloadSize = readLongLong(from); info.downloadSize = readLongLong(from);
info.narSize = GET_PROTOCOL_MINOR(daemonVersion) >= 7 ? readLongLong(from) : 0; info.narSize = GET_PROTOCOL_MINOR(daemonVersion) >= 7 ? readLongLong(from) : 0;
return true; return true;
@ -260,7 +262,7 @@ ValidPathInfo RemoteStore::queryPathInfo(const Path & path)
info.deriver = readString(from); info.deriver = readString(from);
if (info.deriver != "") assertStorePath(info.deriver); if (info.deriver != "") assertStorePath(info.deriver);
info.hash = parseHash(htSHA256, readString(from)); info.hash = parseHash(htSHA256, readString(from));
info.references = readStorePaths(from); info.references = readStorePaths<PathSet>(from);
info.registrationTime = readInt(from); info.registrationTime = readInt(from);
info.narSize = readLongLong(from); info.narSize = readLongLong(from);
return info; return info;
@ -285,7 +287,7 @@ void RemoteStore::queryReferences(const Path & path,
writeInt(wopQueryReferences, to); writeInt(wopQueryReferences, to);
writeString(path, to); writeString(path, to);
processStderr(); processStderr();
PathSet references2 = readStorePaths(from); PathSet references2 = readStorePaths<PathSet>(from);
references.insert(references2.begin(), references2.end()); references.insert(references2.begin(), references2.end());
} }
@ -297,7 +299,7 @@ void RemoteStore::queryReferrers(const Path & path,
writeInt(wopQueryReferrers, to); writeInt(wopQueryReferrers, to);
writeString(path, to); writeString(path, to);
processStderr(); processStderr();
PathSet referrers2 = readStorePaths(from); PathSet referrers2 = readStorePaths<PathSet>(from);
referrers.insert(referrers2.begin(), referrers2.end()); referrers.insert(referrers2.begin(), referrers2.end());
} }
@ -320,7 +322,7 @@ PathSet RemoteStore::queryDerivationOutputs(const Path & path)
writeInt(wopQueryDerivationOutputs, to); writeInt(wopQueryDerivationOutputs, to);
writeString(path, to); writeString(path, to);
processStderr(); processStderr();
return readStorePaths(from); return readStorePaths<PathSet>(from);
} }
@ -350,7 +352,7 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
writeInt(wopAddTextToStore, to); writeInt(wopAddTextToStore, to);
writeString(name, to); writeString(name, to);
writeString(s, to); writeString(s, to);
writeStringSet(references, to); writeStrings(references, to);
processStderr(); processStderr();
return readStorePath(from); return readStorePath(from);
@ -369,14 +371,14 @@ void RemoteStore::exportPath(const Path & path, bool sign,
} }
Path RemoteStore::importPath(bool requireSignature, Source & source) Paths RemoteStore::importPaths(bool requireSignature, Source & source)
{ {
openConnection(); openConnection();
writeInt(wopImportPath, to); writeInt(wopImportPaths, to);
/* We ignore requireSignature, since the worker forces it to true /* We ignore requireSignature, since the worker forces it to true
anyway. */ anyway. */
processStderr(0, &source); processStderr(0, &source);
return readStorePath(from); return readStorePaths<Paths>(from);
} }
@ -384,7 +386,7 @@ void RemoteStore::buildDerivations(const PathSet & drvPaths)
{ {
openConnection(); openConnection();
writeInt(wopBuildDerivations, to); writeInt(wopBuildDerivations, to);
writeStringSet(drvPaths, to); writeStrings(drvPaths, to);
processStderr(); processStderr();
readInt(from); readInt(from);
} }
@ -451,7 +453,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
writeInt(wopCollectGarbage, to); writeInt(wopCollectGarbage, to);
writeInt(options.action, to); writeInt(options.action, to);
writeStringSet(options.pathsToDelete, to); writeStrings(options.pathsToDelete, to);
writeInt(options.ignoreLiveness, to); writeInt(options.ignoreLiveness, to);
writeLongLong(options.maxFreed, to); writeLongLong(options.maxFreed, to);
writeInt(options.maxLinks, to); writeInt(options.maxLinks, to);
@ -463,7 +465,7 @@ void RemoteStore::collectGarbage(const GCOptions & options, GCResults & results)
processStderr(); processStderr();
results.paths = readStringSet(from); results.paths = readStrings<PathSet>(from);
results.bytesFreed = readLongLong(from); results.bytesFreed = readLongLong(from);
results.blocksFreed = readLongLong(from); results.blocksFreed = readLongLong(from);
} }
@ -474,7 +476,7 @@ PathSet RemoteStore::queryFailedPaths()
openConnection(); openConnection();
writeInt(wopQueryFailedPaths, to); writeInt(wopQueryFailedPaths, to);
processStderr(); processStderr();
return readStorePaths(from); return readStorePaths<PathSet>(from);
} }
@ -482,7 +484,7 @@ void RemoteStore::clearFailedPaths(const PathSet & paths)
{ {
openConnection(); openConnection();
writeInt(wopClearFailedPaths, to); writeInt(wopClearFailedPaths, to);
writeStringSet(paths, to); writeStrings(paths, to);
processStderr(); processStderr();
readInt(from); readInt(from);
} }
@ -504,8 +506,7 @@ void RemoteStore::processStderr(Sink * sink, Source * source)
size_t len = readInt(from); size_t len = readInt(from);
unsigned char * buf = new unsigned char[len]; unsigned char * buf = new unsigned char[len];
AutoDeleteArray<unsigned char> d(buf); AutoDeleteArray<unsigned char> d(buf);
size_t n = source->read(buf, len); writeString(buf, source->read(buf, len), to);
writeString(string((const char *) buf, n), to); // !!! inefficient
to.flush(); to.flush();
} }
else { else {

View File

@ -56,7 +56,7 @@ public:
void exportPath(const Path & path, bool sign, void exportPath(const Path & path, bool sign,
Sink & sink); Sink & sink);
Path importPath(bool requireSignature, Source & source); Paths importPaths(bool requireSignature, Source & source);
void buildDerivations(const PathSet & drvPaths); void buildDerivations(const PathSet & drvPaths);

View File

@ -169,9 +169,9 @@ public:
virtual void exportPath(const Path & path, bool sign, virtual void exportPath(const Path & path, bool sign,
Sink & sink) = 0; Sink & sink) = 0;
/* Import a NAR dump created by exportPath() into the Nix /* Import a sequence of NAR dumps created by exportPaths() into
store. */ the Nix store. */
virtual Path importPath(bool requireSignature, Source & source) = 0; virtual Paths importPaths(bool requireSignature, Source & source) = 0;
/* Ensure that the output paths of the derivation are valid. If /* Ensure that the output paths of the derivation are valid. If
they are already valid, this is a no-op. Otherwise, validity they are already valid, this is a no-op. Otherwise, validity

View File

@ -29,7 +29,6 @@ typedef enum {
wopSyncWithGC = 13, wopSyncWithGC = 13,
wopFindRoots = 14, wopFindRoots = 14,
wopExportPath = 16, wopExportPath = 16,
wopImportPath = 17,
wopQueryDeriver = 18, wopQueryDeriver = 18,
wopSetOptions = 19, wopSetOptions = 19,
wopCollectGarbage = 20, wopCollectGarbage = 20,
@ -39,6 +38,7 @@ typedef enum {
wopQueryFailedPaths = 24, wopQueryFailedPaths = 24,
wopClearFailedPaths = 25, wopClearFailedPaths = 25,
wopQueryPathInfo = 26, wopQueryPathInfo = 26,
wopImportPaths = 27,
} WorkerOp; } WorkerOp;
@ -58,7 +58,7 @@ typedef enum {
Path readStorePath(Source & from); Path readStorePath(Source & from);
PathSet readStorePaths(Source & from); template<class T> T readStorePaths(Source & from);
} }

View File

@ -163,13 +163,16 @@ void writeString(const string & s, Sink & sink)
} }
void writeStringSet(const StringSet & ss, Sink & sink) template<class T> void writeStrings(const T & ss, Sink & sink)
{ {
writeInt(ss.size(), sink); writeInt(ss.size(), sink);
for (StringSet::iterator i = ss.begin(); i != ss.end(); ++i) foreach (typename T::const_iterator, i, ss)
writeString(*i, sink); writeString(*i, sink);
} }
template void writeStrings(const Paths & ss, Sink & sink);
template void writeStrings(const PathSet & ss, Sink & sink);
void readPadding(size_t len, Source & source) void readPadding(size_t len, Source & source)
{ {
@ -234,14 +237,17 @@ string readString(Source & source)
} }
StringSet readStringSet(Source & source) template<class T> T readStrings(Source & source)
{ {
unsigned int count = readInt(source); unsigned int count = readInt(source);
StringSet ss; T ss;
while (count--) while (count--)
ss.insert(readString(source)); ss.insert(ss.end(), readString(source));
return ss; return ss;
} }
template Paths readStrings(Source & source);
template PathSet readStrings(Source & source);
} }

View File

@ -116,14 +116,14 @@ void writeInt(unsigned int n, Sink & sink);
void writeLongLong(unsigned long long n, Sink & sink); void writeLongLong(unsigned long long n, Sink & sink);
void writeString(const unsigned char * buf, size_t len, Sink & sink); void writeString(const unsigned char * buf, size_t len, Sink & sink);
void writeString(const string & s, Sink & sink); void writeString(const string & s, Sink & sink);
void writeStringSet(const StringSet & ss, Sink & sink); template<class T> void writeStrings(const T & ss, Sink & sink);
void readPadding(size_t len, Source & source); void readPadding(size_t len, Source & source);
unsigned int readInt(Source & source); unsigned int readInt(Source & source);
unsigned long long readLongLong(Source & source); unsigned long long readLongLong(Source & source);
size_t readString(unsigned char * buf, size_t max, Source & source); size_t readString(unsigned char * buf, size_t max, Source & source);
string readString(Source & source); string readString(Source & source);
StringSet readStringSet(Source & source); template<class T> T readStrings(Source & source);
MakeError(SerialisationError, Error) MakeError(SerialisationError, Error)

View File

@ -600,12 +600,10 @@ static void opImport(Strings opFlags, Strings opArgs)
if (!opArgs.empty()) throw UsageError("no arguments expected"); if (!opArgs.empty()) throw UsageError("no arguments expected");
FdSource source(STDIN_FILENO); FdSource source(STDIN_FILENO);
while (true) { Paths paths = store->importPaths(requireSignature, source);
unsigned long long n = readLongLong(source);
if (n == 0) break; foreach (Paths::iterator, i, paths)
if (n != 1) throw Error("input doesn't look like something created by `nix-store --export'"); cout << format("%1%\n") % *i << std::flush;
cout << format("%1%\n") % store->importPath(requireSignature, source) << std::flush;
}
} }

View File

@ -327,7 +327,7 @@ static void performOp(unsigned int clientVersion,
store->queryReferrers(path, paths); store->queryReferrers(path, paths);
else paths = store->queryDerivationOutputs(path); else paths = store->queryDerivationOutputs(path);
stopWork(); stopWork();
writeStringSet(paths, to); writeStrings(paths, to);
break; break;
} }
@ -377,7 +377,7 @@ static void performOp(unsigned int clientVersion,
case wopAddTextToStore: { case wopAddTextToStore: {
string suffix = readString(from); string suffix = readString(from);
string s = readString(from); string s = readString(from);
PathSet refs = readStorePaths(from); PathSet refs = readStorePaths<PathSet>(from);
startWork(); startWork();
Path path = store->addTextToStore(suffix, s, refs); Path path = store->addTextToStore(suffix, s, refs);
stopWork(); stopWork();
@ -396,19 +396,17 @@ static void performOp(unsigned int clientVersion,
break; break;
} }
case wopImportPath: { case wopImportPaths: {
startWork(); startWork();
if (GET_PROTOCOL_MINOR(clientVersion) < 9)
throw Error("import not supported; upgrade your client");
TunnelSource source(from); TunnelSource source(from);
Path path = store->importPath(true, source); Paths paths = store->importPaths(true, source);
stopWork(); stopWork();
writeString(path, to); writeStrings(paths, to);
break; break;
} }
case wopBuildDerivations: { case wopBuildDerivations: {
PathSet drvs = readStorePaths(from); PathSet drvs = readStorePaths<PathSet>(from);
startWork(); startWork();
store->buildDerivations(drvs); store->buildDerivations(drvs);
stopWork(); stopWork();
@ -466,7 +464,7 @@ static void performOp(unsigned int clientVersion,
case wopCollectGarbage: { case wopCollectGarbage: {
GCOptions options; GCOptions options;
options.action = (GCOptions::GCAction) readInt(from); options.action = (GCOptions::GCAction) readInt(from);
options.pathsToDelete = readStorePaths(from); options.pathsToDelete = readStorePaths<PathSet>(from);
options.ignoreLiveness = readInt(from); options.ignoreLiveness = readInt(from);
options.maxFreed = readLongLong(from); options.maxFreed = readLongLong(from);
options.maxLinks = readInt(from); options.maxLinks = readInt(from);
@ -484,7 +482,7 @@ static void performOp(unsigned int clientVersion,
store->collectGarbage(options, results); store->collectGarbage(options, results);
stopWork(); stopWork();
writeStringSet(results.paths, to); writeStrings(results.paths, to);
writeLongLong(results.bytesFreed, to); writeLongLong(results.bytesFreed, to);
writeLongLong(results.blocksFreed, to); writeLongLong(results.blocksFreed, to);
@ -522,7 +520,7 @@ static void performOp(unsigned int clientVersion,
writeInt(res ? 1 : 0, to); writeInt(res ? 1 : 0, to);
if (res) { if (res) {
writeString(info.deriver, to); writeString(info.deriver, to);
writeStringSet(info.references, to); writeStrings(info.references, to);
writeLongLong(info.downloadSize, to); writeLongLong(info.downloadSize, to);
if (GET_PROTOCOL_MINOR(clientVersion) >= 7) if (GET_PROTOCOL_MINOR(clientVersion) >= 7)
writeLongLong(info.narSize, to); writeLongLong(info.narSize, to);
@ -534,7 +532,7 @@ static void performOp(unsigned int clientVersion,
startWork(); startWork();
PathSet paths = store->queryValidPaths(); PathSet paths = store->queryValidPaths();
stopWork(); stopWork();
writeStringSet(paths, to); writeStrings(paths, to);
break; break;
} }
@ -542,12 +540,12 @@ static void performOp(unsigned int clientVersion,
startWork(); startWork();
PathSet paths = store->queryFailedPaths(); PathSet paths = store->queryFailedPaths();
stopWork(); stopWork();
writeStringSet(paths, to); writeStrings(paths, to);
break; break;
} }
case wopClearFailedPaths: { case wopClearFailedPaths: {
PathSet paths = readStringSet(from); PathSet paths = readStrings<PathSet>(from);
startWork(); startWork();
store->clearFailedPaths(paths); store->clearFailedPaths(paths);
stopWork(); stopWork();
@ -562,7 +560,7 @@ static void performOp(unsigned int clientVersion,
stopWork(); stopWork();
writeString(info.deriver, to); writeString(info.deriver, to);
writeString(printHash(info.hash), to); writeString(printHash(info.hash), to);
writeStringSet(info.references, to); writeStrings(info.references, to);
writeInt(info.registrationTime, to); writeInt(info.registrationTime, to);
writeLongLong(info.narSize, to); writeLongLong(info.narSize, to);
break; break;