summaryrefslogtreecommitdiff
path: root/upload-pack.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2013-09-08 09:01:31 (GMT)
committerJunio C Hamano <gitster@pobox.com>2013-09-09 18:14:37 (GMT)
commit05e95155a10fab3d3c495076e51b2ce79fa26cf3 (patch)
treee1d0db6d0b9957ed5325488d06d24b96bd9d87dc /upload-pack.c
parentedca4152560522a431a51fc0a06147fc680b5b18 (diff)
downloadgit-05e95155a10fab3d3c495076e51b2ce79fa26cf3.zip
git-05e95155a10fab3d3c495076e51b2ce79fa26cf3.tar.gz
git-05e95155a10fab3d3c495076e51b2ce79fa26cf3.tar.bz2
upload-pack: send keepalive packets during pack computation
When upload-pack has started pack-objects, there may be a quiet period while pack-objects prepares the pack (i.e., counting objects and delta compression). Normally we would see (and send to the client) progress information, but if "--quiet" is in effect, pack-objects will produce nothing at all until the pack data is ready. On a large repository, this can take tens of seconds (or even minutes if the system is loaded or the repository is badly packed). Clients or intermediate proxies can sometimes give up in this situation, assuming that the server or connection has hung. This patch introduces a "keepalive" option; if upload-pack sees no data from pack-objects for a certain number of seconds, it will send an empty sideband data packet to let the other side know that we are still working on it. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'upload-pack.c')
-rw-r--r--upload-pack.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/upload-pack.c b/upload-pack.c
index bfa6279..289717e 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -40,6 +40,7 @@ static struct object_array have_obj;
static struct object_array want_obj;
static struct object_array extra_edge_obj;
static unsigned int timeout;
+static int keepalive = -1;
/* 0 for no sideband,
* otherwise maximum packet size (up to 65520 bytes).
*/
@@ -200,6 +201,7 @@ static void create_pack_file(void)
while (1) {
struct pollfd pfd[2];
int pe, pu, pollsize;
+ int ret;
reset_timeout();
@@ -222,7 +224,8 @@ static void create_pack_file(void)
if (!pollsize)
break;
- if (poll(pfd, pollsize, -1) < 0) {
+ ret = poll(pfd, pollsize, 1000 * keepalive);
+ if (ret < 0) {
if (errno != EINTR) {
error("poll failed, resuming: %s",
strerror(errno));
@@ -284,6 +287,21 @@ static void create_pack_file(void)
if (sz < 0)
goto fail;
}
+
+ /*
+ * We hit the keepalive timeout without saying anything; send
+ * an empty message on the data sideband just to let the other
+ * side know we're still working on it, but don't have any data
+ * yet.
+ *
+ * If we don't have a sideband channel, there's no room in the
+ * protocol to say anything, so those clients are just out of
+ * luck.
+ */
+ if (!ret && use_sideband) {
+ static const char buf[] = "0005\1";
+ write_or_die(1, buf, 5);
+ }
}
if (finish_command(&pack_objects)) {
@@ -785,6 +803,11 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
{
if (!strcmp("uploadpack.allowtipsha1inwant", var))
allow_tip_sha1_in_want = git_config_bool(var, value);
+ else if (!strcmp("uploadpack.keepalive", var)) {
+ keepalive = git_config_int(var, value);
+ if (!keepalive)
+ keepalive = -1;
+ }
return parse_hide_refs_config(var, value, "uploadpack");
}