aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-03-03 13:58:02 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-03-03 13:58:02 +0000
commit4bbdcfbb45112fc3b025f0feff7b995ee373b091 (patch)
tree0b23d65ee3c994465997f759c62869f3f3efbca3
parent9e6bca876518fbcd32c67d72721310f6b60f6f75 (diff)
* Don't use fork() in copyPath(), but a string buffer.
-rw-r--r--src/libstore/store.cc61
-rw-r--r--src/libutil/archive.hh3
2 files changed, 17 insertions, 47 deletions
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index 4b9e807d2..0ac9473bc 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -1,7 +1,6 @@
#include <iostream>
#include <algorithm>
-#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -126,20 +125,24 @@ void createStoreTransaction(Transaction & txn)
struct CopySink : DumpSink
{
- int fd;
+ string s;
virtual void operator () (const unsigned char * data, unsigned int len)
{
- writeFull(fd, data, len);
+ s.append((const char *) data, len);
}
};
struct CopySource : RestoreSource
{
- int fd;
+ string & s;
+ unsigned int pos;
+ CopySource(string & _s) : s(_s), pos(0) { }
virtual void operator () (unsigned char * data, unsigned int len)
{
- readFull(fd, data, len);
+ s.copy((char *) data, len, pos);
+ pos += len;
+ assert(pos <= s.size());
}
};
@@ -148,52 +151,19 @@ void copyPath(const Path & src, const Path & dst)
{
debug(format("copying `%1%' to `%2%'") % src % dst);
- /* Unfortunately C++ doesn't support coprocedures, so we have no
- nice way to chain CopySink and CopySource together. Instead we
- fork off a child to run the sink. (Fork-less platforms should
- use a thread). */
-
- /* Create a pipe. */
- Pipe pipe;
- pipe.create();
-
- /* Fork. */
- Pid pid;
- pid = fork();
- switch (pid) {
-
- case -1:
- throw SysError("unable to fork");
-
- case 0: /* child */
- try {
- pipe.writeSide.close();
- CopySource source;
- source.fd = pipe.readSide;
- restorePath(dst, source);
- _exit(0);
- } catch (exception & e) {
- cerr << "error: " << e.what() << endl;
- }
- _exit(1);
- }
-
- /* Parent. */
+ /* Dump an archive of the path `src' into a string buffer, then
+ restore the archive to `dst'. This is not a very good method
+ for very large paths, but `copyPath' is mainly used for small
+ files. */
- pipe.readSide.close();
-
CopySink sink;
- sink.fd = pipe.writeSide;
{
SwitchToOriginalUser sw;
dumpPath(src, sink);
}
- /* Wait for the child to finish. */
- int status = pid.wait(true);
- if (!statusOk(status))
- throw Error(format("cannot copy `%1% to `%2%': child %3%")
- % src % dst % statusToString(status));
+ CopySource source(sink.s);
+ restorePath(dst, source);
}
@@ -619,9 +589,6 @@ Path addToStore(const Path & _srcPath)
if (pathExists(dstPath)) deletePath(dstPath);
- /* !!! race: srcPath might change between hashPath() and
- here! */
-
copyPath(srcPath, dstPath);
Hash h2 = hashPath(htSHA256, dstPath);
diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh
index 67e236668..b498c95c1 100644
--- a/src/libutil/archive.hh
+++ b/src/libutil/archive.hh
@@ -42,6 +42,7 @@
struct DumpSink
{
+ virtual ~DumpSink() { }
virtual void operator () (const unsigned char * data, unsigned int len) = 0;
};
@@ -50,6 +51,8 @@ void dumpPath(const Path & path, DumpSink & sink);
struct RestoreSource
{
+ virtual ~RestoreSource() { }
+
/* The callee should store exactly *len bytes in the buffer
pointed to by data. It should block if that much data is not
yet available, or throw an error if it is not going to be