extern int am_sender;
extern int am_generator;
extern int eol_nulls;
+extern int read_batch;
extern int csum_length;
extern int checksum_seed;
extern int protocol_version;
extern struct file_list *the_file_list;
const char phase_unknown[] = "unknown";
-int select_timeout = SELECT_TIMEOUT;
int ignore_timeout = 0;
int batch_fd = -1;
int batch_gen_fd = -1;
static int io_multiplexing_out;
static int io_multiplexing_in;
-static time_t last_io;
+static time_t last_io_in;
+static time_t last_io_out;
static int no_flush;
static int write_batch_monitor_in = -1;
static char io_filesfrom_lastchar;
static int io_filesfrom_buflen;
static size_t contiguous_write_len = 0;
+static int select_timeout = SELECT_TIMEOUT;
static void read_loop(int fd, char *buf, size_t len);
static struct flist_ndx_list redo_list, hlink_list;
-struct msg_list {
- struct msg_list *next;
+struct msg_list_item {
+ struct msg_list_item *next;
char *buf;
int len;
};
-static struct msg_list *msg_list_head;
-static struct msg_list *msg_list_tail;
+struct msg_list {
+ struct msg_list_item *head, *tail;
+};
+
+static struct msg_list msg_list;
static void flist_ndx_push(struct flist_ndx_list *lp, int ndx)
{
if (!io_timeout || ignore_timeout)
return;
- if (!last_io) {
- last_io = time(NULL);
+ if (!last_io_in) {
+ last_io_in = time(NULL);
return;
}
t = time(NULL);
- if (t - last_io >= io_timeout) {
+ if (t - last_io_in >= io_timeout) {
if (!am_server && !am_daemon) {
rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
- (int)(t-last_io));
+ (int)(t-last_io_in));
}
exit_cleanup(RERR_TIMEOUT);
}
sock_f_out = f_out;
}
+void set_io_timeout(int secs)
+{
+ io_timeout = secs;
+
+ if (!io_timeout || io_timeout > SELECT_TIMEOUT)
+ select_timeout = SELECT_TIMEOUT;
+ else
+ select_timeout = io_timeout;
+
+ allowed_lull = read_batch ? 0 : (io_timeout + 1) / 2;
+}
+
/* Setup the fd used to receive MSG_* messages. Only needed during the
* early stages of being a local sender (up through the sending of the
* file list) or when we're the generator (to fetch the messages from
/* Add a message to the pending MSG_* list. */
static void msg_list_add(int code, char *buf, int len)
{
- struct msg_list *ml;
+ struct msg_list_item *ml;
- if (!(ml = new(struct msg_list)))
+ if (!(ml = new(struct msg_list_item)))
out_of_memory("msg_list_add");
ml->next = NULL;
if (!(ml->buf = new_array(char, len+4)))
SIVAL(ml->buf, 0, ((code+MPLEX_BASE)<<24) | len);
memcpy(ml->buf+4, buf, len);
ml->len = len+4;
- if (msg_list_tail)
- msg_list_tail->next = ml;
+ if (msg_list.tail)
+ msg_list.tail->next = ml;
else
- msg_list_head = ml;
- msg_list_tail = ml;
-}
-
-void send_msg(enum msgcode code, char *buf, int len)
-{
- if (msg_fd_out < 0) {
- io_multiplex_write(code, buf, len);
- return;
- }
- msg_list_add(code, buf, len);
- msg_list_push(NORMAL_FLUSH);
+ msg_list.head = ml;
+ msg_list.tail = ml;
}
/* Read a message from the MSG_* fd and handle it. This is called either
/* Try to push messages off the list onto the wire. If we leave with more
* to do, return 0. On error, return -1. If everything flushed, return 1.
* This is only active in the receiver. */
-int msg_list_push(int flush_it_all)
+static int msg_list_flush(int flush_it_all)
{
static int written = 0;
struct timeval tv;
if (msg_fd_out < 0)
return -1;
- while (msg_list_head) {
- struct msg_list *ml = msg_list_head;
+ while (msg_list.head) {
+ struct msg_list_item *ml = msg_list.head;
int n = write(msg_fd_out, ml->buf + written, ml->len - written);
if (n < 0) {
if (errno == EINTR)
check_timeout();
} else if ((written += n) == ml->len) {
free(ml->buf);
- msg_list_head = ml->next;
- if (!msg_list_head)
- msg_list_tail = NULL;
+ msg_list.head = ml->next;
+ if (!msg_list.head)
+ msg_list.tail = NULL;
free(ml);
written = 0;
}
return 1;
}
+void send_msg(enum msgcode code, char *buf, int len)
+{
+ if (msg_fd_out < 0) {
+ io_multiplex_write(code, buf, len);
+ return;
+ }
+ msg_list_add(code, buf, len);
+ msg_list_flush(NORMAL_FLUSH);
+}
+
int get_redo_num(int itemizing, enum logcode code)
{
while (1) {
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
FD_SET(fd, &r_fds);
- if (msg_list_head) {
+ if (msg_list.head) {
FD_SET(msg_fd_out, &w_fds);
if (msg_fd_out > maxfd)
maxfd = msg_fd_out;
continue;
}
- if (msg_list_head && FD_ISSET(msg_fd_out, &w_fds))
- msg_list_push(NORMAL_FLUSH);
+ if (msg_list.head && FD_ISSET(msg_fd_out, &w_fds))
+ msg_list_flush(NORMAL_FLUSH);
if (io_filesfrom_f_out >= 0) {
if (io_filesfrom_buflen) {
len -= n;
ret += n;
- if (fd == sock_f_in && (io_timeout || am_generator))
- last_io = time(NULL);
+ if (fd == sock_f_in && io_timeout)
+ last_io_in = time(NULL);
}
return ret;
void maybe_flush_socket(void)
{
- if (iobuf_out && iobuf_out_cnt && time(NULL) - last_io >= 5)
+ if (iobuf_out && iobuf_out_cnt && time(NULL) - last_io_out >= 5)
io_flush(NORMAL_FLUSH);
}
void maybe_send_keepalive(void)
{
- if (time(NULL) - last_io >= allowed_lull) {
+ if (time(NULL) - last_io_out >= allowed_lull) {
if (!iobuf_out || !iobuf_out_cnt) {
if (protocol_version < 29)
return; /* there's nothing we can do */
static size_t iobuf_in_ndx;
size_t msg_bytes;
int tag, ret = 0;
-#if MAXPATHLEN < 4096
- char line[4096+1024];
-#else
- char line[MAXPATHLEN+1024];
-#endif
+ char line[BIGPATHBUFLEN];
if (!iobuf_in || fd != sock_f_in)
return read_timeout(fd, buf, len);
/* Write len bytes to the file descriptor fd, looping as necessary to get
- * the job done and also (in certain circumstnces) reading any data on
+ * the job done and also (in certain circumstances) reading any data on
* msg_fd_in to avoid deadlock.
*
* This function underlies the multiplexing system. The body of the
/* If the other side is sending us error messages, try
* to grab any messages they sent before they died. */
while (fd == sock_f_out && io_multiplexing_in) {
- io_timeout = select_timeout = 30;
+ set_io_timeout(30);
ignore_timeout = 0;
readfd_unbuffered(sock_f_in, io_filesfrom_buf,
sizeof io_filesfrom_buf);
if (fd == sock_f_out) {
if (io_timeout || am_generator)
- last_io = time(NULL);
+ last_io_out = time(NULL);
sleep_for_bwlimit(ret);
}
}
**/
static void mplex_write(enum msgcode code, char *buf, size_t len)
{
- char buffer[4096];
+ char buffer[BIGPATHBUFLEN];
size_t n = len;
SIVAL(buffer, 0, ((MPLEX_BASE + (int)code)<<24) + len);
void io_flush(int flush_it_all)
{
- msg_list_push(flush_it_all);
+ msg_list_flush(flush_it_all);
if (!iobuf_out_cnt || no_flush)
return;
void io_printf(int fd, const char *format, ...)
{
va_list ap;
- char buf[1024];
+ char buf[BIGPATHBUFLEN];
int len;
va_start(ap, format);
if (len < 0)
exit_cleanup(RERR_STREAMIO);
+ if (len > (int)sizeof buf) {
+ rprintf(FERROR, "io_printf() was too long for the buffer.\n");
+ exit_cleanup(RERR_STREAMIO);
+ }
+
write_sbuf(fd, buf);
}