Commit 7bcd9e23e8f64c8622e9213ee0fa3d75d058053b

Ben Straub 2012-10-19T19:23:32

gitno_buffer: callback on each packet The fetch code takes advantage of this to implement a progress callback every 100kb of transfer.

diff --git a/examples/network/clone.c b/examples/network/clone.c
index fd30bca..5ad9330 100644
--- a/examples/network/clone.c
+++ b/examples/network/clone.c
@@ -18,10 +18,11 @@ static void print_progress(const progress_data *pd)
 	int network_percent = (100*pd->fetch_progress.received) / pd->fetch_progress.total;
 	int index_percent = (100*pd->fetch_progress.processed) / pd->fetch_progress.total;
 	int checkout_percent = (int)(100.f * pd->checkout_progress);
-	printf("net %3d%%  /  idx %3d%%  /  chk %3d%%  %50s\r",
-			network_percent, index_percent, checkout_percent, pd->path);
+	int kbytes = pd->fetch_progress.bytes / 1024;
+	printf("net %3d%% (%6d kb)  /  idx %3d%%  /  chk %3d%%  %50s\n",
+			network_percent, kbytes, index_percent, checkout_percent, pd->path);
 	/*
-	printf("net %5d /%5d  –  idx %5d /%5d  –  chk %.04f   %20s\r",
+	printf("net %5d /%5d  –  idx %5d /%5d  –  chk %.04f   %20s\n",
 			pd->fetch_progress.received, pd->fetch_progress.total,
 			pd->fetch_progress.processed, pd->fetch_progress.total,
 			pd->checkout_progress, pd->path);
diff --git a/include/git2/indexer.h b/include/git2/indexer.h
index 0d3c9dd..ae01fd6 100644
--- a/include/git2/indexer.h
+++ b/include/git2/indexer.h
@@ -20,6 +20,7 @@ typedef struct git_indexer_stats {
 	unsigned int total;
 	unsigned int processed;
 	unsigned int received;
+	size_t bytes;
 } git_indexer_stats;
 
 
diff --git a/src/fetch.c b/src/fetch.c
index 583c79a..3f69c2c 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -19,6 +19,8 @@
 #include "netops.h"
 #include "pkt.h"
 
+#define NETWORK_XFER_THRESHOLD (100*1024)
+
 struct filter_payload {
 	git_remote *remote;
 	const git_refspec *spec, *tagspec;
@@ -348,6 +350,28 @@ static int no_sideband(git_transport *t, git_indexer_stream *idx, gitno_buffer *
 	return 0;
 }
 
+struct network_packetsize_payload
+{
+	git_indexer_progress_callback callback;
+	void *payload;
+	git_indexer_stats *stats;
+	git_off_t last_fired_bytes;
+};
+
+static void network_packetsize(int received, void *payload)
+{
+	struct network_packetsize_payload *npp = (struct network_packetsize_payload*)payload;
+
+	/* Accumulate bytes */
+	npp->stats->bytes += received;
+
+	/* Fire notification if the threshold is reached */
+	if ((npp->stats->bytes - npp->last_fired_bytes) > NETWORK_XFER_THRESHOLD) {
+		npp->last_fired_bytes = npp->stats->bytes;
+		npp->callback(npp->stats, npp->payload);
+	}
+}
+
 /* Receiving data from a socket and storing it is pretty much the same for git and HTTP */
 int git_fetch__download_pack(
 	git_transport *t,
@@ -361,6 +385,15 @@ int git_fetch__download_pack(
 	gitno_buffer *buf = &t->buffer;
 	git_indexer_stream *idx = NULL;
 	int error = -1;
+	struct network_packetsize_payload npp = {0};
+
+	if (progress_cb) {
+		npp.callback = progress_cb;
+		npp.payload = progress_payload;
+		npp.stats = stats;
+		buf->packetsize_cb = &network_packetsize;
+		buf->packetsize_payload = &npp;
+	}
 
 	if (git_buf_joinpath(&path, git_repository_path(repo), "objects/pack") < 0)
 		return -1;
diff --git a/src/netops.c b/src/netops.c
index df502e6..d9663e6 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -117,6 +117,7 @@ static int gitno__recv_ssl(gitno_buffer *buf)
 	}
 
 	buf->offset += ret;
+	if (buf->packetsize_cb) buf->packetsize_cb(ret, buf->packetsize_payload);
 	return ret;
 }
 #endif
@@ -132,6 +133,7 @@ int gitno__recv(gitno_buffer *buf)
 	}
 
 	buf->offset += ret;
+	if (buf->packetsize_cb) buf->packetsize_cb(ret, buf->packetsize_payload);
 	return ret;
 }
 
@@ -142,7 +144,6 @@ void gitno_buffer_setup_callback(
 	size_t len,
 	int (*recv)(gitno_buffer *buf), void *cb_data)
 {
-	memset(buf, 0x0, sizeof(gitno_buffer));
 	memset(data, 0x0, len);
 	buf->data = data;
 	buf->len = len;
diff --git a/src/netops.h b/src/netops.h
index 7c53fd0..64da7fb 100644
--- a/src/netops.h
+++ b/src/netops.h
@@ -20,6 +20,8 @@ struct gitno_buffer {
 #endif
 	int (*recv)(gitno_buffer *buffer);
 	void *cb_data;
+	void (*packetsize_cb)(int received, void *payload);
+	void *packetsize_payload;
 };
 
 void gitno_buffer_setup(git_transport *t, gitno_buffer *buf, char *data, size_t len);
diff --git a/src/transports/http.c b/src/transports/http.c
index 93dd0c3..0efd220 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -379,6 +379,8 @@ static int http_recv_cb(gitno_buffer *buf)
 
 #ifndef GIT_WINHTTP
 	gitno_buffer_setup(transport, &inner, buffer, sizeof(buffer));
+	inner.packetsize_cb = buf->packetsize_cb;
+	inner.packetsize_payload = buf->packetsize_payload;
 
 	if ((error = gitno_recv(&inner)) < 0)
 		return -1;