Merge branch 'jc/sideband' into jc/archive
authorJunio C Hamano <junkio@cox.net>
Mon, 11 Sep 2006 00:58:45 +0000 (17:58 -0700)
committerJunio C Hamano <junkio@cox.net>
Mon, 11 Sep 2006 00:58:45 +0000 (17:58 -0700)
* jc/sideband:
Prepare larger packet buffer for upload-pack protocol.
Move sideband server side support into reusable form.
Move sideband client side support into reusable form.
get_sha1_hex() micro-optimization

Makefile
fetch-clone.c
fetch-pack.c
sha1_file.c
sideband.c [new file with mode: 0644]
sideband.h [new file with mode: 0644]
upload-pack.c
index 4ac85fdc7b1585746fbdb11bdcbfda3b70467085..c724b481a4426ed3336c12289eafdcb581c09e42 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -233,7 +233,7 @@ XDIFF_LIB=xdiff/lib.a
 
 LIB_H = \
        archive.h blob.h cache.h commit.h csum-file.h delta.h \
-       diff.h object.h pack.h pkt-line.h quote.h refs.h \
+       diff.h object.h pack.h pkt-line.h quote.h refs.h sideband.h \
        run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
        tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h
 
@@ -245,7 +245,7 @@ DIFF_OBJS = \
 LIB_OBJS = \
        blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
        date.o diff-delta.o entry.o exec_cmd.o ident.o lockfile.o \
-       object.o pack-check.o patch-delta.o path.o pkt-line.o \
+       object.o pack-check.o patch-delta.o path.o pkt-line.o sideband.o \
        quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \
        server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
        tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
index c5cf4776fabb8f9f09028dd1f0cfaf1d55e1397c..b632ca0438b378944b37a7d64fd508ea3f7f470f 100644 (file)
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "exec_cmd.h"
 #include "pkt-line.h"
+#include "sideband.h"
 #include <sys/wait.h>
 #include <sys/time.h>
 
@@ -114,36 +115,13 @@ static pid_t setup_sideband(int sideband, const char *me, int fd[2], int xd[2])
                die("%s: unable to fork off sideband demultiplexer", me);
        if (!side_pid) {
                /* subprocess */
+               char buf[LARGE_PACKET_MAX];
+
                close(fd[0]);
                if (xd[0] != xd[1])
                        close(xd[1]);
-               while (1) {
-                       char buf[1024];
-                       int len = packet_read_line(xd[0], buf, sizeof(buf));
-                       if (len == 0)
-                               break;
-                       if (len < 1)
-                               die("%s: protocol error: no band designator",
-                                   me);
-                       len--;
-                       switch (buf[0] & 0xFF) {
-                       case 3:
-                               safe_write(2, "remote: ", 8);
-                               safe_write(2, buf+1, len);
-                               safe_write(2, "\n", 1);
-                               exit(1);
-                       case 2:
-                               safe_write(2, "remote: ", 8);
-                               safe_write(2, buf+1, len);
-                               continue;
-                       case 1:
-                               safe_write(fd[1], buf+1, len);
-                               continue;
-                       default:
-                               die("%s: protocol error: bad band #%d",
-                                   me, (buf[0] & 0xFF));
-                       }
-               }
+               if (recv_sideband(me, xd[0], fd[1], 2, buf, sizeof(buf)))
+                       exit(1);
                exit(0);
        }
        close(xd[0]);
index 377feded1ccafdece86499d1917d297145fd28ac..1b2d6ee20d16d03a59d2cd2aafb46e9a03c492b0 100644 (file)
@@ -166,10 +166,11 @@ static int find_common(int fd[2], unsigned char *result_sha1,
                }
 
                if (!fetching)
-                       packet_write(fd[1], "want %s%s%s%s\n",
+                       packet_write(fd[1], "want %s%s%s%s%s\n",
                                     sha1_to_hex(remote),
                                     (multi_ack ? " multi_ack" : ""),
-                                    (use_sideband ? " side-band" : ""),
+                                    (use_sideband == 2 ? " side-band-64k" : ""),
+                                    (use_sideband == 1 ? " side-band" : ""),
                                     (use_thin_pack ? " thin-pack" : ""));
                else
                        packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
@@ -426,7 +427,12 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
                        fprintf(stderr, "Server supports multi_ack\n");
                multi_ack = 1;
        }
-       if (server_supports("side-band")) {
+       if (server_supports("side-band-64k")) {
+               if (verbose)
+                       fprintf(stderr, "Server supports side-band-64k\n");
+               use_sideband = 2;
+       }
+       else if (server_supports("side-band")) {
                if (verbose)
                        fprintf(stderr, "Server supports side-band\n");
                use_sideband = 1;
index 428d791ba8e2f62e3c30627a8f9463236c77cc60..b64b92de4e7a6c59edfb3e60ff1440a98cacdeea 100644 (file)
@@ -26,15 +26,43 @@ const unsigned char null_sha1[20];
 
 static unsigned int sha1_file_open_flag = O_NOATIME;
 
-static unsigned hexval(char c)
-{
-       if (c >= '0' && c <= '9')
-               return c - '0';
-       if (c >= 'a' && c <= 'f')
-               return c - 'a' + 10;
-       if (c >= 'A' && c <= 'F')
-               return c - 'A' + 10;
-       return ~0;
+static inline unsigned int hexval(unsigned int c)
+{
+       static signed char val[256] = {
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 00-07 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 08-0f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 10-17 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 18-1f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 20-27 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 28-2f */
+                 0,  1,  2,  3,  4,  5,  6,  7,                /* 30-37 */
+                 8,  9, -1, -1, -1, -1, -1, -1,                /* 38-3f */
+                -1, 10, 11, 12, 13, 14, 15, -1,                /* 40-47 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 48-4f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 50-57 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 58-5f */
+                -1, 10, 11, 12, 13, 14, 15, -1,                /* 60-67 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 68-67 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 70-77 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 78-7f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 80-87 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 88-8f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 90-97 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 98-9f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* a0-a7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* a8-af */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* b0-b7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* b8-bf */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* c0-c7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* c8-cf */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* d0-d7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* d8-df */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* e0-e7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* e8-ef */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* f0-f7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* f8-ff */
+       };
+       return val[c];
 }
 
 int get_sha1_hex(const char *hex, unsigned char *sha1)
diff --git a/sideband.c b/sideband.c
new file mode 100644 (file)
index 0000000..1b14ff8
--- /dev/null
@@ -0,0 +1,74 @@
+#include "pkt-line.h"
+#include "sideband.h"
+
+/*
+ * Receive multiplexed output stream over git native protocol.
+ * in_stream is the input stream from the remote, which carries data
+ * in pkt_line format with band designator.  Demultiplex it into out
+ * and err and return error appropriately.  Band #1 carries the
+ * primary payload.  Things coming over band #2 is not necessarily
+ * error; they are usually informative message on the standard error
+ * stream, aka "verbose").  A message over band #3 is a signal that
+ * the remote died unexpectedly.  A flush() concludes the stream.
+ */
+int recv_sideband(const char *me, int in_stream, int out, int err, char *buf, int bufsz)
+{
+       while (1) {
+               int len = packet_read_line(in_stream, buf, bufsz);
+               if (len == 0)
+                       break;
+               if (len < 1) {
+                       len = sprintf(buf, "%s: protocol error: no band designator\n", me);
+                       safe_write(err, buf, len);
+                       return SIDEBAND_PROTOCOL_ERROR;
+               }
+               len--;
+               switch (buf[0] & 0xFF) {
+               case 3:
+                       safe_write(err, "remote: ", 8);
+                       safe_write(err, buf+1, len);
+                       safe_write(err, "\n", 1);
+                       return SIDEBAND_REMOTE_ERROR;
+               case 2:
+                       safe_write(err, "remote: ", 8);
+                       safe_write(err, buf+1, len);
+                       continue;
+               case 1:
+                       safe_write(out, buf+1, len);
+                       continue;
+               default:
+                       len = sprintf(buf + 1,
+                                     "%s: protocol error: bad band #%d\n",
+                                     me, buf[0] & 0xFF);
+                       safe_write(err, buf+1, len);
+                       return SIDEBAND_PROTOCOL_ERROR;
+               }
+       }
+       return 0;
+}
+
+/*
+ * fd is connected to the remote side; send the sideband data
+ * over multiplexed packet stream.
+ */
+ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max)
+{
+       ssize_t ssz = sz;
+       const char *p = data;
+
+       while (sz) {
+               unsigned n;
+               char hdr[5];
+
+               n = sz;
+               if (packet_max - 5 < n)
+                       n = packet_max - 5;
+               sprintf(hdr, "%04x", n + 5);
+               hdr[4] = band;
+               safe_write(fd, hdr, 5);
+               safe_write(fd, p, n);
+               p += n;
+               sz -= n;
+       }
+       return ssz;
+}
diff --git a/sideband.h b/sideband.h
new file mode 100644 (file)
index 0000000..4872106
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef SIDEBAND_H
+#define SIDEBAND_H
+
+#define SIDEBAND_PROTOCOL_ERROR -2
+#define SIDEBAND_REMOTE_ERROR -1
+
+#define DEFAULT_PACKET_MAX 1000
+#define LARGE_PACKET_MAX 65520
+
+int recv_sideband(const char *me, int in_stream, int out, int err, char *, int);
+ssize_t send_sideband(int fd, int band, const char *data, ssize_t sz, int packet_max);
+
+#endif
index 51ce936b060d34a2f759dba4f7aeeecf47a59a4b..b673d8cb9748de0758d1c5269178e70a018f43a1 100644 (file)
@@ -4,6 +4,7 @@
 #include "cache.h"
 #include "refs.h"
 #include "pkt-line.h"
+#include "sideband.h"
 #include "tag.h"
 #include "object.h"
 #include "commit.h"
@@ -19,6 +20,9 @@ static int use_thin_pack;
 static struct object_array have_obj;
 static struct object_array want_obj;
 static unsigned int timeout;
+/* 0 for no sideband,
+ * otherwise maximum packet size (up to 65520 bytes).
+ */
 static int use_sideband;
 
 static void reset_timeout(void)
@@ -33,45 +37,18 @@ static int strip(char *line, int len)
        return len;
 }
 
-#define PACKET_MAX 1000
 static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
 {
-       ssize_t ssz;
-       const char *p;
-
-       if (!data) {
-               if (!use_sideband)
-                       return 0;
-               packet_flush(1);
-       }
-
-       if (!use_sideband) {
-               if (fd == 3)
-                       /* emergency quit */
-                       fd = 2;
-               if (fd == 2) {
-                       xwrite(fd, data, sz);
-                       return sz;
-               }
-               return safe_write(fd, data, sz);
-       }
-       p = data;
-       ssz = sz;
-       while (sz) {
-               unsigned n;
-               char hdr[5];
-
-               n = sz;
-               if (PACKET_MAX - 5 < n)
-                       n = PACKET_MAX - 5;
-               sprintf(hdr, "%04x", n + 5);
-               hdr[4] = fd;
-               safe_write(1, hdr, 5);
-               safe_write(1, p, n);
-               p += n;
-               sz -= n;
+       if (use_sideband)
+               return send_sideband(1, fd, data, sz, use_sideband);
+       if (fd == 3)
+               /* emergency quit */
+               fd = 2;
+       if (fd == 2) {
+               xwrite(fd, data, sz);
+               return sz;
        }
-       return ssz;
+       return safe_write(fd, data, sz);
 }
 
 static void create_pack_file(void)
@@ -308,7 +285,8 @@ static void create_pack_file(void)
                                goto fail;
                        fprintf(stderr, "flushed.\n");
                }
-               send_client_data(1, NULL, 0);
+               if (use_sideband)
+                       packet_flush(1);
                return;
        }
  fail:
@@ -413,8 +391,10 @@ static void receive_needs(void)
                        multi_ack = 1;
                if (strstr(line+45, "thin-pack"))
                        use_thin_pack = 1;
-               if (strstr(line+45, "side-band"))
-                       use_sideband = 1;
+               if (strstr(line+45, "side-band-64k"))
+                       use_sideband = LARGE_PACKET_MAX;
+               else if (strstr(line+45, "side-band"))
+                       use_sideband = DEFAULT_PACKET_MAX;
 
                /* We have sent all our refs already, and the other end
                 * should have chosen out of them; otherwise they are
@@ -436,7 +416,7 @@ static void receive_needs(void)
 
 static int send_ref(const char *refname, const unsigned char *sha1)
 {
-       static const char *capabilities = "multi_ack thin-pack side-band";
+       static const char *capabilities = "multi_ack thin-pack side-band side-band-64k";
        struct object *o = parse_object(sha1);
 
        if (!o)