gitno_buffer: callback on each packet The fetch code takes advantage of this to implement a progress callback every 100kb of transfer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
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;