about summary refs log tree commit diff
path: root/src/libutil/serialise.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2011-12-15T12·32+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2011-12-15T12·32+0000
commita3e0656cbbfadba28518e0a29c324edaabb9874a (patch)
tree026d7097aed0755d3de2eca9e500b504f20b7410 /src/libutil/serialise.cc
parent3a48282b0681d68147e18f7464eaddf1d188c3be (diff)
* Buffer reads in FdSource. Together with write buffering, this
  significantly cuts down the number of syscalls (e.g., for "nix-store
  -qR /var/run/current-system" via the daemon, it reduced the number
  of syscalls in the client from 29134 to 4766 and in the daemon from
  44266 to 20666).

Diffstat (limited to 'src/libutil/serialise.cc')
-rw-r--r--src/libutil/serialise.cc24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc
index 66a64a6be4..e3a53c0d01 100644
--- a/src/libutil/serialise.cc
+++ b/src/libutil/serialise.cc
@@ -2,6 +2,7 @@
 #include "util.hh"
 
 #include <cstring>
+#include <cerrno>
 
 
 namespace nix {
@@ -38,7 +39,28 @@ void FdSink::flush()
 
 void FdSource::operator () (unsigned char * data, unsigned int len)
 {
-    readFull(fd, data, len);
+    if (!buffer) buffer = new unsigned char[bufSize];
+
+    while (len) {
+        if (!bufPosIn) {
+            /* Read as much data as is available (up to the buffer
+               size). */
+            checkInterrupt();
+            ssize_t n = read(fd, (char *) buffer, bufSize);
+            if (n == -1) {
+                if (errno == EINTR) continue;
+                throw SysError("reading from file");
+            }
+            if (n == 0) throw EndOfFile("unexpected end-of-file");
+            bufPosIn = n;
+        }
+            
+        /* Copy out the data in the buffer. */
+        size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len;
+        memcpy(data, buffer + bufPosOut, n);
+        data += n; bufPosOut += n; len -= n;
+        if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0;
+    }
 }