Support the new --files-from option.
[rsync/rsync.git] / io.c
diff --git a/io.c b/io.c
index 07e1feb..f8d29d8 100644 (file)
--- a/io.c
+++ b/io.c
@@ -52,6 +52,24 @@ extern int io_timeout;
 extern struct stats stats;
 
 
+const char phase_unknown[] = "unknown";
+
+/**
+ * The connection might be dropped at some point; perhaps because the
+ * remote instance crashed.  Just giving the offset on the stream is
+ * not very helpful.  So instead we try to make io_phase_name point to
+ * something useful.
+ *
+ * For buffered/multiplexed IO these names will be somewhat
+ * approximate; perhaps for ease of support we would rather make the
+ * buffer always flush when a single application-level IO finishes.
+ *
+ * @todo Perhaps we want some simple stack functionality, but there's
+ * no need to overdo it.
+ **/
+const char *io_write_phase = phase_unknown;
+const char *io_read_phase = phase_unknown;
+
 /** Ignore EOF errors while reading a module listing if the remote
     version is 24 or less. */
 int kludge_around_eof = False;
@@ -86,7 +104,7 @@ static void check_timeout(void)
        }
 }
 
-/** Setup the fd used to propogate errors */
+/** Setup the fd used to propagate errors */
 void io_set_error_fd(int fd)
 {
        io_error_fd = fd;
@@ -390,6 +408,33 @@ unsigned char read_byte(int f)
 }
 
 
+/**
+ * Sleep after writing to limit I/O bandwidth usage.
+ *
+ * @todo Rather than sleeping after each write, it might be better to
+ * use some kind of averaging.  The current algorithm seems to always
+ * use a bit less bandwidth than specified, because it doesn't make up
+ * for slow periods.  But arguably this is a feature.  In addition, we
+ * ought to take the time used to write the data into account.
+ **/
+static void sleep_for_bwlimit(int bytes_written)
+{
+       struct timeval tv;
+
+       if (!bwlimit)
+               return;
+
+       assert(bytes_written > 0);
+       assert(bwlimit > 0);
+       
+       tv.tv_usec = bytes_written * 1000 / bwlimit;
+       tv.tv_sec  = tv.tv_usec / 1000000;
+       tv.tv_usec = tv.tv_usec % 1000000;
+
+       select(0, NULL, NULL, NULL, &tv);
+}
+
+
 /**
  * Write len bytes to the file descriptor @p fd.
  *
@@ -464,24 +509,13 @@ static void writefd_unbuffered(int fd,char *buf,size_t len)
                                 * across the stream */
                                io_multiplexing_close();
                                rprintf(FERROR, RSYNC_NAME
-                                       ": writefd_unbuffered failed to write %ld bytes: %s\n",
-                                       (long) len, 
+                                       ": writefd_unbuffered failed to write %ld bytes: phase \"%s\": %s\n",
+                                       (long) len, io_write_phase, 
                                        strerror(errno));
                                exit_cleanup(RERR_STREAMIO);
                        }
 
-                       /* Sleep after writing to limit I/O bandwidth */
-                       if (bwlimit)
-                       {
-                           tv.tv_sec = 0;
-                           tv.tv_usec = ret * 1000 / bwlimit;
-                           while (tv.tv_usec > 1000000)
-                           {
-                               tv.tv_sec++;
-                               tv.tv_usec -= 1000000;
-                           }
-                           select(0, NULL, NULL, NULL, &tv);
-                       }
+                       sleep_for_bwlimit(ret);
  
                        total += ret;
 
@@ -592,6 +626,14 @@ void write_int(int f,int32 x)
 }
 
 
+void write_int_named(int f, int32 x, const char *phase)
+{
+       io_write_phase = phase;
+       write_int(f, x);
+       io_write_phase = phase_unknown;
+}
+
+
 /*
  * Note: int64 may actually be a 32-bit type if ./configure couldn't find any
  * 64-bit types on this platform.
@@ -606,11 +648,16 @@ void write_longint(int f, int64 x)
                return;
        }
 
+#ifdef NO_INT64
+       rprintf(FERROR,"Integer overflow - attempted 64 bit offset\n");
+       exit_cleanup(RERR_UNSUPPORTED);
+#else
        write_int(f, (int32)0xFFFFFFFF);
        SIVAL(b,0,(x&0xFFFFFFFF));
        SIVAL(b,4,((x>>32)&0xFFFFFFFF));
 
        writefd(f,b,8);
+#endif
 }
 
 void write_buf(int f,char *buf,size_t len)