Browse Source

Enable smart HTTP transport to place EOF at end of pack

When fetching over smart HTTP the InputStream that gets fed into
a PackParser doesn't really support EOF at the end of the pack. It
instead tries to make a new HTTP request, which fails because there
is no request body currently buffered by the client.

Make EOF work correctly on the end of an HTTP derived InputStream
for the pack by denoting no more requests are expected as the higher
level code is now consuming the pack (or side-band embedded pack).
Smart HTTP support doesn't automatically enqueue execute support onto
the end of the UnionInputStream, which allows the UnionInputStream
to correctly reflect EOF when the HTTP response is consumed.

Change-Id: I975f1ab1c81ab1c1af925716970088bc7b8d6b1a
tags/v2.0.0.201206130900-r
Shawn O. Pearce 12 years ago
parent
commit
dfff04742f

+ 10
- 0
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackFetchConnection.java View File

} }


private void receivePack(final ProgressMonitor monitor) throws IOException { private void receivePack(final ProgressMonitor monitor) throws IOException {
onReceivePack();
InputStream input = in; InputStream input = in;
if (sideband) if (sideband)
input = new SideBandInputStream(input, monitor, getMessageWriter()); input = new SideBandInputStream(input, monitor, getMessageWriter());
} }
} }


/**
* Notification event delivered just before the pack is received from the
* network. This event can be used by RPC such as {@link TransportHttp} to
* disable its request magic and ensure the pack stream is read correctly.
*/
protected void onReceivePack() {
// By default do nothing for TCP based protocols.
}

private static class CancelledException extends Exception { private static class CancelledException extends Exception {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

+ 25
- 7
org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java View File

} }


class SmartHttpFetchConnection extends BasePackFetchConnection { class SmartHttpFetchConnection extends BasePackFetchConnection {
private Service svc;

SmartHttpFetchConnection(final InputStream advertisement) SmartHttpFetchConnection(final InputStream advertisement)
throws TransportException { throws TransportException {
super(TransportHttp.this); super(TransportHttp.this);
protected void doFetch(final ProgressMonitor monitor, protected void doFetch(final ProgressMonitor monitor,
final Collection<Ref> want, final Set<ObjectId> have) final Collection<Ref> want, final Set<ObjectId> have)
throws TransportException { throws TransportException {
final Service svc = new Service(SVC_UPLOAD_PACK);
init(svc.in, svc.out);
super.doFetch(monitor, want, have);
try {
svc = new Service(SVC_UPLOAD_PACK);
init(svc.in, svc.out);
super.doFetch(monitor, want, have);
} finally {
svc = null;
}
}

@Override
protected void onReceivePack() {
svc.finalRequest = true;
} }
} }




private final HttpExecuteStream execute; private final HttpExecuteStream execute;


boolean finalRequest;

final UnionInputStream in; final UnionInputStream in;


final HttpOutputStream out; final HttpOutputStream out;
out.close(); out.close();


if (conn == null) { if (conn == null) {
// Output hasn't started yet, because everything fit into
// our request buffer. Send with a Content-Length header.
//
if (out.length() == 0) { if (out.length() == 0) {
// Request output hasn't started yet, but more data is being
// requested. If there is no request data buffered and the
// final request was already sent, do nothing to ensure the
// caller is shown EOF on the InputStream; otherwise an
// programming error has occurred within this module.
if (finalRequest)
return;
throw new TransportException(uri, throw new TransportException(uri,
JGitText.get().startingReadStageWithoutWrittenRequestDataPendingIsNotSupported); JGitText.get().startingReadStageWithoutWrittenRequestDataPendingIsNotSupported);
} }
} }


in.add(openInputStream(conn)); in.add(openInputStream(conn));
in.add(execute);
if (!finalRequest)
in.add(execute);
conn = null; conn = null;
} }



Loading…
Cancel
Save