extern struct stats stats;
+/**
+ * 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.
+ **/
+const char *io_phase_name = "unknown";
+
+
/** Ignore EOF errors while reading a module listing if the remote
version is 24 or less. */
int kludge_around_eof = False;
}
+/**
+ * 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.
*
* across the stream */
io_multiplexing_close();
rprintf(FERROR, RSYNC_NAME
- ": error writing %d unbuffered bytes"
- " - exiting: %s\n", len,
+ ": writefd_unbuffered failed to write %ld bytes: phase \"%s\": %s\n",
+ (long) len, io_phase_name,
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;