git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Shawn O. Pearce" <spearce@spearce.org>
To: git@vger.kernel.org
Subject: [RFC PATCH v2 05/16] Add multi_ack_2 capability to fetch-pack/upload-pack
Date: Mon, 12 Oct 2009 19:25:04 -0700	[thread overview]
Message-ID: <1255400715-10508-6-git-send-email-spearce@spearce.org> (raw)
In-Reply-To: <1255400715-10508-1-git-send-email-spearce@spearce.org>

When multi_ack_2 is enabled the ACK continue messages returned by the
remote upload-pack are broken out to describe the different states
within the peer.  This permits the client to better understand the
server's in-memory state.

The fetch-pack/upload-pack protocol now looks like:

NAK
---------------------------------
  Always sent in response to "done" if there was no common base
  selected from the "have" lines (or no have lines were sent).

  * no multi_ack or multi_ack_2:

    Sent when the client has sent a pkt-line flush ("0000") and
    the server has not yet found a common base object.

  * either multi_ack or multi_ack_2:

    Always sent in response to a pkt-line flush.

ACK %s
-----------------------------------
  * no multi_ack or multi_ack_2:

    Sent in response to "have" when the object exists on the remote
    side and is therefore an object in common between the peers.
    The argument is the SHA-1 of the common object.

  * either multi_ack or multi_ack_2:

    Sent in response to "done" if there are common objects.
    The argument is the last SHA-1 determined to be common.

ACK %s continue
-----------------------------------
  * multi_ack only:

    Sent in response to "have".

    The remote side wants the client to consider this object as
    common, and immediately stop transmitting additional "have"
    lines for objects that are reachable from it.  The reason
    the client should stop is not given, but is one of the two
    cases below available under multi_ack_2.

ACK %s common
-----------------------------------
  * multi_ack_2 only:

    Sent in response to "have".  Both sides have this object.
    Like with "ACK %s continue" above the client should stop
    sending have lines reachable for objects from the argument.

ACK %s ready
-----------------------------------
  * multi_ack_2 only:

    Sent in response to "have".

    The client should stop transmitting objects which are reachable
    from the argument, and send "done" soon to get the objects.

    If the remote side has the specified object, it should
    first send an "ACK %s common" message prior to sending
    "ACK %s ready".

    Clients may still submit additional "have" lines if there are
    more side branches for the client to explore that might be added
    to the common set and reduce the number of objects to transfer.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-fetch-pack.c |   41 ++++++++++++++++++++++++++++++++---------
 upload-pack.c        |   31 ++++++++++++++++++-------------
 2 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 7c09d46..b68b3eb 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -157,7 +157,15 @@ static const unsigned char *get_rev(void)
 	return commit->object.sha1;
 }
 
-static int get_ack(int fd, unsigned char *result_sha1)
+enum ack_type {
+	NAK = 0,
+	ACK,
+	ACK_continue,
+	ACK_common,
+	ACK_ready
+};
+
+static enum ack_type get_ack(int fd, unsigned char *result_sha1)
 {
 	static char line[1000];
 	int len = packet_read_line(fd, line, sizeof(line));
@@ -167,12 +175,16 @@ static int get_ack(int fd, unsigned char *result_sha1)
 	if (line[len-1] == '\n')
 		line[--len] = 0;
 	if (!strcmp(line, "NAK"))
-		return 0;
+		return NAK;
 	if (!prefixcmp(line, "ACK ")) {
 		if (!get_sha1_hex(line+4, result_sha1)) {
 			if (strstr(line+45, "continue"))
-				return 2;
-			return 1;
+				return ACK_continue;
+			if (strstr(line+45, "common"))
+				return ACK_common;
+			if (strstr(line+45, "ready"))
+				return ACK_ready;
+			return ACK;
 		}
 	}
 	die("git fetch_pack: expected ACK/NAK, got '%s'", line);
@@ -218,7 +230,8 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 		remote_hex = sha1_to_hex(remote);
 		if (!fetching) {
 			struct strbuf c = STRBUF_INIT;
-			if (multi_ack)          strbuf_addstr(&c, " multi_ack");
+			if (multi_ack == 2)     strbuf_addstr(&c, " multi_ack_2");
+			if (multi_ack == 1)     strbuf_addstr(&c, " multi_ack");
 			if (use_sideband == 2)  strbuf_addstr(&c, " side-band-64k");
 			if (use_sideband == 1)  strbuf_addstr(&c, " side-band");
 			if (args.use_thin_pack) strbuf_addstr(&c, " thin-pack");
@@ -298,18 +311,23 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 				if (args.verbose && ack)
 					fprintf(stderr, "got ack %d %s\n", ack,
 							sha1_to_hex(result_sha1));
-				if (ack == 1) {
+				switch (ack) {
+				case ACK:
 					flushes = 0;
 					multi_ack = 0;
 					retval = 0;
 					goto done;
-				} else if (ack == 2) {
+				case ACK_common:
+				case ACK_ready:
+				case ACK_continue: {
 					struct commit *commit =
 						lookup_commit(result_sha1);
 					mark_common(commit, 0, 1);
 					retval = 0;
 					in_vain = 0;
 					got_continue = 1;
+					break;
+					}
 				}
 			} while (ack);
 			flushes--;
@@ -336,7 +354,7 @@ done:
 			if (args.verbose)
 				fprintf(stderr, "got ack (%d) %s\n", ack,
 					sha1_to_hex(result_sha1));
-			if (ack == 1)
+			if (ack == ACK)
 				return 0;
 			multi_ack = 1;
 			continue;
@@ -618,7 +636,12 @@ static struct ref *do_fetch_pack(int fd[2],
 
 	if (is_repository_shallow() && !server_supports("shallow"))
 		die("Server does not support shallow clients");
-	if (server_supports("multi_ack")) {
+	if (server_supports("multi_ack_2")) {
+		if (args.verbose)
+			fprintf(stderr, "Server supports multi_ack_2\n");
+		multi_ack = 2;
+	}
+	else if (server_supports("multi_ack")) {
 		if (args.verbose)
 			fprintf(stderr, "Server supports multi_ack\n");
 		multi_ack = 1;
diff --git a/upload-pack.c b/upload-pack.c
index 38ddac2..5024b59 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -498,7 +498,7 @@ static int get_common_commits(void)
 {
 	static char line[1000];
 	unsigned char sha1[20];
-	char hex[41], last_hex[41];
+	char last_hex[41];
 
 	save_commit_buffer = 0;
 
@@ -515,19 +515,22 @@ static int get_common_commits(void)
 		if (!prefixcmp(line, "have ")) {
 			switch (got_sha1(line+5, sha1)) {
 			case -1: /* they have what we do not */
-				if (multi_ack && ok_to_give_up())
-					packet_write(1, "ACK %s continue\n",
-						     sha1_to_hex(sha1));
+				if (multi_ack && ok_to_give_up()) {
+					const char *hex = sha1_to_hex(sha1);
+					if (multi_ack == 2)
+						packet_write(1, "ACK %s ready\n", hex);
+					else
+						packet_write(1, "ACK %s continue\n", hex);
+				}
 				break;
 			default:
-				memcpy(hex, sha1_to_hex(sha1), 41);
-				if (multi_ack) {
-					const char *msg = "ACK %s continue\n";
-					packet_write(1, msg, hex);
-					memcpy(last_hex, hex, 41);
-				}
+				memcpy(last_hex, sha1_to_hex(sha1), 41);
+				if (multi_ack == 2)
+					packet_write(1, "ACK %s common\n", last_hex);
+				else if (multi_ack)
+					packet_write(1, "ACK %s continue\n", last_hex);
 				else if (have_obj.nr == 1)
-					packet_write(1, "ACK %s\n", hex);
+					packet_write(1, "ACK %s\n", last_hex);
 				break;
 			}
 			continue;
@@ -587,7 +590,9 @@ static void receive_needs(void)
 		    get_sha1_hex(line+5, sha1_buf))
 			die("git upload-pack: protocol error, "
 			    "expected to get sha, not '%s'", line);
-		if (strstr(line+45, "multi_ack"))
+		if (strstr(line+45, "multi_ack_2"))
+			multi_ack = 2;
+		else if (strstr(line+45, "multi_ack"))
 			multi_ack = 1;
 		if (strstr(line+45, "thin-pack"))
 			use_thin_pack = 1;
@@ -681,7 +686,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 {
 	static const char *capabilities = "multi_ack thin-pack side-band"
 		" side-band-64k ofs-delta shallow no-progress"
-		" include-tag";
+		" include-tag multi_ack_2";
 	struct object *o = parse_object(sha1);
 
 	if (!o)
-- 
1.6.5.52.g0ff2e

  parent reply	other threads:[~2009-10-13  2:34 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-13  2:24 [RFC PATCH v2 00/16] Return of smart HTTP Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 01/16] pkt-line: Add strbuf based functions Shawn O. Pearce
2009-10-13  7:29   ` Johannes Sixt
2009-10-13 18:10     ` Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 02/16] pkt-line: Make packet_read_line easier to debug Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 03/16] fetch-pack: Use a strbuf to compose the want list Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 04/16] Move "get_ack()" back to fetch-pack Shawn O. Pearce
2009-10-13  2:25 ` Shawn O. Pearce [this message]
2009-10-13 21:35   ` [RFC PATCH v2 05/16] Add multi_ack_2 capability to fetch-pack/upload-pack Jakub Narebski
2009-10-13 21:36     ` Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 06/16] remote-curl: Refactor walker initialization Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 07/16] remote-helpers: Fetch more than one ref in a batch Shawn O. Pearce
2009-10-13  3:56   ` Daniel Barkalow
2009-10-13 18:05     ` Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 08/16] remote-helpers: Support custom transport options Shawn O. Pearce
2009-10-13  4:23   ` Daniel Barkalow
2009-10-13 18:45     ` Shawn O. Pearce
2009-10-13 20:39       ` Daniel Barkalow
2009-10-13 20:52         ` Shawn O. Pearce
2009-10-13 21:41           ` Daniel Barkalow
2009-10-13 21:51             ` Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 09/16] Move WebDAV HTTP push under remote-curl Shawn O. Pearce
2009-10-13  4:41   ` Mike Hommey
2009-10-13 18:04     ` Johannes Schindelin
2009-10-13  2:25 ` [RFC PATCH v2 10/16] Git-aware CGI to provide dumb HTTP transport Shawn O. Pearce
2009-10-13 10:56   ` Johannes Sixt
2009-10-13  2:25 ` [RFC PATCH v2 11/16] Add one shot RPC options to upload-pack, receive-pack Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 12/16] Smart fetch and push over HTTP: server side Shawn O. Pearce
2009-10-13  7:30   ` Johannes Sixt
2009-10-13 18:24     ` Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 13/16] Discover refs via smart HTTP server when available Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 14/16] Smart push over HTTP: client side Shawn O. Pearce
2009-10-13 11:02   ` Felipe Contreras
2009-10-13  2:25 ` [RFC PATCH v2 15/16] Smart fetch " Shawn O. Pearce
2009-10-13  2:25 ` [RFC PATCH v2 16/16] Smart HTTP fetch: gzip requests Shawn O. Pearce
2009-10-13  8:38   ` Junio C Hamano
2009-10-13  3:45 ` [RFC PATCH v2 00/16] Return of smart HTTP eduard stefan
2009-10-13  6:42   ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1255400715-10508-6-git-send-email-spearce@spearce.org \
    --to=spearce@spearce.org \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).