#include "commit-graph.h"
#include "commit-reach.h"
#include "shallow.h"
+#include "trace.h"
#include "write-or-die.h"
#include "json-writer.h"
#include "strmap.h"
};
static int relay_pack_data(int pack_objects_out, struct output_state *os,
- int use_sideband, int write_packfile_line)
+ int use_sideband, int write_packfile_line,
+ bool *did_send_data)
{
/*
* We keep the last byte to ourselves
*/
ssize_t readsz;
+ *did_send_data = false;
+
readsz = xread(pack_objects_out, os->buffer + os->used,
sizeof(os->buffer) - os->used);
if (readsz < 0) {
if (os->packfile_uris_started)
packet_delim(1);
packet_write_fmt(1, "\1packfile\n");
+ *did_send_data = true;
}
break;
}
}
*p = '\0';
packet_write_fmt(1, "\1%s\n", os->buffer);
+ *did_send_data = true;
os->used -= p - os->buffer + 1;
memmove(os->buffer, p + 1, os->used);
os->used = 0;
}
+ *did_send_data = true;
return readsz;
}
char progress[128];
char abort_msg[] = "aborting due to possible repository "
"corruption on the remote side.";
+ uint64_t last_sent_ms = 0;
ssize_t sz;
int i;
FILE *pipe_fd;
*/
while (1) {
+ uint64_t now_ms = getnanotime() / 1000000;
struct pollfd pfd[2];
- int pe, pu, pollsize, polltimeout;
+ int pe, pu, pollsize, polltimeout_ms;
int ret;
+ if (!last_sent_ms)
+ last_sent_ms = now_ms;
+
reset_timeout(pack_data->timeout);
pollsize = 0;
if (!pollsize)
break;
- polltimeout = pack_data->keepalive < 0
- ? -1
- : 1000 * pack_data->keepalive;
+ if (pack_data->keepalive < 0) {
+ polltimeout_ms = -1;
+ } else {
+ /*
+ * The polling timeout needs to be adjusted based on
+ * the time we have sent our last package. The longer
+ * it's been in the past, the shorter the timeout
+ * becomes until we eventually don't block at all.
+ */
+ polltimeout_ms = 1000 * pack_data->keepalive - (now_ms - last_sent_ms);
+ if (polltimeout_ms < 0)
+ polltimeout_ms = 0;
+ }
- ret = poll(pfd, pollsize, polltimeout);
+ ret = poll(pfd, pollsize, polltimeout_ms);
if (ret < 0) {
if (errno != EINTR) {
}
continue;
}
+
if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
/* Status ready; we ship that in the side-band
* or dump to the standard error.
*/
sz = xread(pack_objects.err, progress,
sizeof(progress));
- if (0 < sz)
+ if (0 < sz) {
send_client_data(2, progress, sz,
pack_data->use_sideband);
- else if (sz == 0) {
+ last_sent_ms = now_ms;
+ } else if (sz == 0) {
close(pack_objects.err);
pack_objects.err = -1;
}
/* give priority to status messages */
continue;
}
+
if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
+ bool did_send_data;
int result = relay_pack_data(pack_objects.out,
output_state,
pack_data->use_sideband,
- !!uri_protocols);
+ !!uri_protocols,
+ &did_send_data);
if (result == 0) {
close(pack_objects.out);
} else if (result < 0) {
goto fail;
}
+
+ if (did_send_data)
+ last_sent_ms = now_ms;
}
/*
if (!ret && pack_data->use_sideband) {
static const char buf[] = "0005\1";
write_or_die(1, buf, 5);
+ last_sent_ms = now_ms;
}
}