Browse Source

Teach UploadPack how to use an RPC style interface

If biDirectionalPipe is false UploadPack does not start out with
the advertisement but instead assumes it should read one block of
want/have lines, process that, and write the ACK/NAKs out.

This means it only is doing one read through the input followed by
one write to the output, which fits with the HTTP request processing
model, and any other type of RPC system.

Change-Id: Ia9f7c46ee556f996367180f15d2caa8572cdd59f
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
stable-0.7
Shawn O. Pearce 15 years ago
parent
commit
e187618b6b
  1. 56
      org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java

56
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java

@ -103,6 +103,19 @@ public class UploadPack {
/** Timeout in seconds to wait for client interaction. */ /** Timeout in seconds to wait for client interaction. */
private int timeout; private int timeout;
/**
* Is the client connection a bi-directional socket or pipe?
* <p>
* If true, this class assumes it can perform multiple read and write cycles
* with the client over the input and output streams. This matches the
* functionality available with a standard TCP/IP connection, or a local
* operating system or in-memory pipe.
* <p>
* If false, this class runs in a read everything then output results mode,
* making it suitable for single round-trip systems RPCs such as HTTP.
*/
private boolean biDirectionalPipe = true;
/** Timer to manage {@link #timeout}. */ /** Timer to manage {@link #timeout}. */
private InterruptTimer timer; private InterruptTimer timer;
@ -198,6 +211,27 @@ public class UploadPack {
timeout = seconds; timeout = seconds;
} }
/**
* @return true if this class expects a bi-directional pipe opened between
* the client and itself. The default is true.
*/
public boolean isBiDirectionalPipe() {
return biDirectionalPipe;
}
/**
* @param twoWay
* if true, this class will assume the socket is a fully
* bidirectional pipe between the two peers and takes advantage
* of that by first transmitting the known refs, then waiting to
* read commands. If false, this class assumes it must read the
* commands before writing output and does not perform the
* initial advertising.
*/
public void setBiDirectionalPipe(final boolean twoWay) {
biDirectionalPipe = twoWay;
}
/** /**
* Execute the upload task on the socket. * Execute the upload task on the socket.
* *
@ -247,7 +281,19 @@ public class UploadPack {
} }
private void service() throws IOException { private void service() throws IOException {
if (biDirectionalPipe)
sendAdvertisedRefs(); sendAdvertisedRefs();
else {
refs = db.getAllRefs();
for (Ref r : refs.values()) {
try {
walk.parseAny(r.getObjectId()).add(ADVERTISED);
} catch (IOException e) {
// Skip missing/corrupt objects
}
}
}
recvWants(); recvWants();
if (wantAll.isEmpty()) if (wantAll.isEmpty())
return; return;
@ -259,7 +305,7 @@ public class UploadPack {
else else
multiAck = MultiAck.OFF; multiAck = MultiAck.OFF;
negotiate(); if (negotiate())
sendPack(); sendPack();
} }
@ -336,7 +382,7 @@ public class UploadPack {
} }
} }
private void negotiate() throws IOException { private boolean negotiate() throws IOException {
ObjectId last = ObjectId.zeroId(); ObjectId last = ObjectId.zeroId();
for (;;) { for (;;) {
String line; String line;
@ -350,6 +396,9 @@ public class UploadPack {
if (commonBase.isEmpty() || multiAck != MultiAck.OFF) if (commonBase.isEmpty() || multiAck != MultiAck.OFF)
pckOut.writeString("NAK\n"); pckOut.writeString("NAK\n");
pckOut.flush(); pckOut.flush();
if (!biDirectionalPipe)
return false;
} else if (line.startsWith("have ") && line.length() == 45) { } else if (line.startsWith("have ") && line.length() == 45) {
final ObjectId id = ObjectId.fromString(line.substring(5)); final ObjectId id = ObjectId.fromString(line.substring(5));
if (matchHave(id)) { if (matchHave(id)) {
@ -389,7 +438,8 @@ public class UploadPack {
else if (multiAck != MultiAck.OFF) else if (multiAck != MultiAck.OFF)
pckOut.writeString("ACK " + last.name() + "\n"); pckOut.writeString("ACK " + last.name() + "\n");
break;
return true;
} else { } else {
throw new PackProtocolException("expected have; got " + line); throw new PackProtocolException("expected have; got " + line);

Loading…
Cancel
Save