about summary refs log tree commit diff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-05-30T14·12-0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-05-30T14·12-0400
commitf5398d374beac34983bb639891ba3f1f50528c72 (patch)
treea3e81b3686c22634ee6cb90bc1d15225341dc4b3 /src/libstore/build.cc
parent881beb170d324f392a53168e6a76e2c5cfd24789 (diff)
Compress build logs on the fly using bzip2
Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc54
1 files changed, 44 insertions, 10 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 985ea5e98e..c27f8db5dc 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -31,6 +31,8 @@
 #include <pwd.h>
 #include <grp.h>
 
+#include <bzlib.h>
+
 
 /* Includes required for chroot support. */
 #if HAVE_SYS_PARAM_H
@@ -758,7 +760,8 @@ private:
     Path tmpDir;
 
     /* File descriptor for the log file. */
-    AutoCloseFD fdLogFile;
+    FILE * fLogFile;
+    BZFILE * bzLogFile;
 
     /* Pipe for the builder's standard output/error. */
     Pipe builderOut;
@@ -819,6 +822,9 @@ private:
     /* Open a log file and a pipe to it. */
     Path openLogFile();
 
+    /* Close the log file. */
+    void closeLogFile();
+
     /* Delete the temporary directory, if we have one. */
     void deleteTmpDir(bool force);
 
@@ -839,6 +845,8 @@ private:
 
 DerivationGoal::DerivationGoal(const Path & drvPath, Worker & worker)
     : Goal(worker)
+    , fLogFile(0)
+    , bzLogFile(0)
     , useChroot(false)
 {
     this->drvPath = drvPath;
@@ -855,6 +863,7 @@ DerivationGoal::~DerivationGoal()
     try {
         killChild();
         deleteTmpDir(false);
+        closeLogFile();
     } catch (...) {
         ignoreException();
     }
@@ -1241,7 +1250,7 @@ void DerivationGoal::buildDone()
     else builderOut.readSide.close();
 
     /* Close the log file. */
-    fdLogFile.close();
+    closeLogFile();
 
     /* When running under a build user, make sure that all processes
        running under that uid are gone.  This is to prevent a
@@ -2037,18 +2046,40 @@ Path DerivationGoal::openLogFile()
     /* Create a log file. */
     Path dir = (format("%1%/%2%") % nixLogDir % drvsLogDir).str();
     createDirs(dir);
-    
-    Path logFileName = (format("%1%/%2%") % dir % baseNameOf(drvPath)).str();
-    fdLogFile = open(logFileName.c_str(),
-        O_CREAT | O_WRONLY | O_TRUNC, 0666);
-    if (fdLogFile == -1)
+
+    Path logFileName = (format("%1%/%2%.bz2") % dir % baseNameOf(drvPath)).str();
+    AutoCloseFD fd = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
+    if (fd == -1)
         throw SysError(format("creating log file `%1%'") % logFileName);
-    closeOnExec(fdLogFile);
+    closeOnExec(fd);
+
+    if (!(fLogFile = fdopen(fd.borrow(), "w")))
+        throw SysError(format("opening file `%1%'") % logFileName);
+
+    int err;
+    if (!(bzLogFile = BZ2_bzWriteOpen(&err, fLogFile, 9, 0, 0)))
+        throw Error(format("cannot open compressed log file `%1%'") % logFileName);
 
     return logFileName;
 }
 
 
+void DerivationGoal::closeLogFile()
+{
+    if (bzLogFile) {
+        int err;
+        BZ2_bzWriteClose(&err, bzLogFile, 0, 0, 0);
+        bzLogFile = 0;
+        if (err != BZ_OK) throw Error(format("cannot close compressed log file (BZip2 error = %1%)") % err);
+    }
+
+    if (fLogFile) {
+        fclose(fLogFile);
+        fLogFile = 0;
+    }
+}
+
+
 void DerivationGoal::deleteTmpDir(bool force)
 {
     if (tmpDir != "") {
@@ -2073,8 +2104,11 @@ void DerivationGoal::handleChildOutput(int fd, const string & data)
     {
         if (verbosity >= buildVerbosity)
             writeToStderr((unsigned char *) data.data(), data.size());
-        if (fdLogFile != -1)
-            writeFull(fdLogFile, (unsigned char *) data.data(), data.size());
+        if (bzLogFile) {
+            int err;
+            BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size());
+            if (err != BZ_OK) throw Error(format("cannot write to compressed log file (BZip2 error = %1%)") % err);
+        }
     }
 
     if (hook && fd == hook->fromHook.readSide)