mirror of https://github.com/grpc/grpc-java.git
[2/2] Swap Operation wrapping from Channel to Transport.
Session is now (properly) implementing transport API, so ChannelImpl has some testing. ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=69074094
This commit is contained in:
parent
4fd4845481
commit
4d642200e7
|
|
@ -43,6 +43,8 @@ public final class ChannelImpl extends AbstractService implements Channel {
|
||||||
public ChannelImpl(ClientTransportFactory transportFactory, ExecutorService executor) {
|
public ChannelImpl(ClientTransportFactory transportFactory, ExecutorService executor) {
|
||||||
this.transportFactory = transportFactory;
|
this.transportFactory = transportFactory;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
|
// FIXME(ejona): Remove once we have our top-level lifecycle.
|
||||||
|
startAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,95 @@
|
||||||
package com.google.net.stubby.stub;
|
package com.google.net.stubby;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.SettableFuture;
|
|
||||||
import com.google.net.stubby.AbstractResponse;
|
import com.google.net.stubby.AbstractResponse;
|
||||||
import com.google.net.stubby.Call;
|
|
||||||
import com.google.net.stubby.MethodDescriptor;
|
|
||||||
import com.google.net.stubby.Operation;
|
import com.google.net.stubby.Operation;
|
||||||
import com.google.net.stubby.Request;
|
import com.google.net.stubby.Request;
|
||||||
import com.google.net.stubby.Response;
|
import com.google.net.stubby.Response;
|
||||||
import com.google.net.stubby.Session;
|
import com.google.net.stubby.Session;
|
||||||
import com.google.net.stubby.Status;
|
import com.google.net.stubby.Status;
|
||||||
|
import com.google.net.stubby.newtransport.ClientStream;
|
||||||
|
import com.google.net.stubby.newtransport.StreamListener;
|
||||||
|
import com.google.net.stubby.newtransport.StreamState;
|
||||||
import com.google.net.stubby.transport.Transport;
|
import com.google.net.stubby.transport.Transport;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A temporary shim layer between the new (Channel) and the old (Session). Will go away when the
|
* A temporary shim layer between the new (Channel) and the old (Session). Will go away when the
|
||||||
* new transport layer is created.
|
* new transport layer is created.
|
||||||
*/
|
*/
|
||||||
// TODO(user): Delete this class when new transport interfaces are introduced
|
// TODO(user): Delete this class when new transport interfaces are introduced
|
||||||
public class SessionCall<RequestT, ResponseT> extends Call<RequestT, ResponseT> {
|
class SessionClientStream implements ClientStream {
|
||||||
|
private final StreamListener listener;
|
||||||
/**
|
/**
|
||||||
* The {@link Request} used by the stub to dispatch the call
|
* The {@link Request} used by the stub to dispatch the call
|
||||||
*/
|
*/
|
||||||
private Request request;
|
private Request request;
|
||||||
|
private Response response;
|
||||||
|
|
||||||
private Listener<ResponseT> responseListener;
|
public SessionClientStream(StreamListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
private final MethodDescriptor<RequestT, ResponseT> methodDescriptor;
|
|
||||||
private final Session session;
|
|
||||||
|
|
||||||
protected SessionCall(MethodDescriptor<RequestT, ResponseT> methodDescriptor, Session session) {
|
|
||||||
// This will go away when we introduce new transport API.... nothing to see here
|
|
||||||
this.methodDescriptor = methodDescriptor;
|
|
||||||
this.session = session;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void start(Request request) {
|
||||||
public void start(Listener<ResponseT> responseListener) {
|
this.request = request;
|
||||||
request = session.startRequest(methodDescriptor.getName(), new Response.ResponseBuilder() {
|
}
|
||||||
|
|
||||||
|
public Response.ResponseBuilder responseBuilder() {
|
||||||
|
return new Response.ResponseBuilder() {
|
||||||
@Override
|
@Override
|
||||||
public Response build(int id) {
|
public Response build(int id) {
|
||||||
return new CallResponse(id);
|
response = new SessionResponse(id);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response build() {
|
public Response build() {
|
||||||
return new CallResponse(-1);
|
response = new SessionResponse(-1);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
this.responseListener = responseListener;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendPayload(RequestT value, SettableFuture<Void> future) {
|
public StreamState state() {
|
||||||
request.addPayload(methodDescriptor.streamRequest(value), Operation.Phase.PAYLOAD);
|
boolean requestOpen = request.getPhase() != Operation.Phase.CLOSED;
|
||||||
if (future != null) {
|
boolean responseOpen = response.getPhase() != Operation.Phase.CLOSED;
|
||||||
future.set(null);
|
if (requestOpen && responseOpen) {
|
||||||
|
return StreamState.OPEN;
|
||||||
|
} else if (requestOpen) {
|
||||||
|
return StreamState.WRITE_ONLY;
|
||||||
|
} else if (responseOpen) {
|
||||||
|
return StreamState.READ_ONLY;
|
||||||
|
} else {
|
||||||
|
return StreamState.CLOSED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendContext(String name, InputStream value, SettableFuture<Void> future) {
|
public void close() {
|
||||||
|
request.close(Status.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeContext(String name, InputStream value, int length, Runnable accepted) {
|
||||||
request.addContext(name, value, Operation.Phase.HEADERS);
|
request.addContext(name, value, Operation.Phase.HEADERS);
|
||||||
if (future != null) {
|
if (accepted != null) {
|
||||||
future.set(null);
|
accepted.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeMessage(InputStream message, int length, Runnable accepted) {
|
||||||
|
request.addPayload(message, Operation.Phase.PAYLOAD);
|
||||||
|
if (accepted != null) {
|
||||||
|
accepted.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An error occurred while producing the request output. Cancel the request
|
* An error occurred while producing the request output. Cancel the request
|
||||||
* and close the response stream.
|
* and close the response stream.
|
||||||
|
|
@ -76,25 +99,28 @@ public class SessionCall<RequestT, ResponseT> extends Call<RequestT, ResponseT>
|
||||||
request.close(new Status(Transport.Code.CANCELLED));
|
request.close(new Status(Transport.Code.CANCELLED));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void halfClose() {
|
|
||||||
request.close(Status.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapts the transport layer response to calls on the response observer or
|
* Adapts the transport layer response to calls on the response observer or
|
||||||
* recorded context state.
|
* recorded context state.
|
||||||
*/
|
*/
|
||||||
private class CallResponse extends AbstractResponse {
|
private class SessionResponse extends AbstractResponse {
|
||||||
|
|
||||||
private CallResponse(int id) {
|
private SessionResponse(int id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int available(InputStream is) {
|
||||||
|
try {
|
||||||
|
return is.available();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Operation addContext(String type, InputStream message, Phase nextPhase) {
|
public Operation addContext(String type, InputStream message, Phase nextPhase) {
|
||||||
try {
|
try {
|
||||||
responseListener.onContext(type, message);
|
listener.contextRead(type, message, available(message));
|
||||||
return super.addContext(type, message, nextPhase);
|
return super.addContext(type, message, nextPhase);
|
||||||
} finally {
|
} finally {
|
||||||
if (getPhase() == Phase.CLOSED) {
|
if (getPhase() == Phase.CLOSED) {
|
||||||
|
|
@ -106,7 +132,7 @@ public class SessionCall<RequestT, ResponseT> extends Call<RequestT, ResponseT>
|
||||||
@Override
|
@Override
|
||||||
public Operation addPayload(InputStream payload, Phase nextPhase) {
|
public Operation addPayload(InputStream payload, Phase nextPhase) {
|
||||||
try {
|
try {
|
||||||
responseListener.onPayload(methodDescriptor.parseResponse(payload));
|
listener.messageRead(payload, available(payload));
|
||||||
return super.addPayload(payload, nextPhase);
|
return super.addPayload(payload, nextPhase);
|
||||||
} finally {
|
} finally {
|
||||||
if (getPhase() == Phase.CLOSED) {
|
if (getPhase() == Phase.CLOSED) {
|
||||||
|
|
@ -125,7 +151,7 @@ public class SessionCall<RequestT, ResponseT> extends Call<RequestT, ResponseT>
|
||||||
}
|
}
|
||||||
|
|
||||||
private void propagateClosed() {
|
private void propagateClosed() {
|
||||||
responseListener.onClose(getStatus());
|
listener.closed(getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.google.net.stubby;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.AbstractService;
|
||||||
|
import com.google.net.stubby.MethodDescriptor;
|
||||||
|
import com.google.net.stubby.newtransport.ClientStream;
|
||||||
|
import com.google.net.stubby.newtransport.ClientTransport;
|
||||||
|
import com.google.net.stubby.newtransport.ClientTransportFactory;
|
||||||
|
import com.google.net.stubby.newtransport.StreamListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shim between Session and Channel. Will be removed when Session is removed.
|
||||||
|
*
|
||||||
|
* <p>This factory always returns the same instance, which does not adhere to the API.
|
||||||
|
*/
|
||||||
|
public class SessionClientTransportFactory implements ClientTransportFactory {
|
||||||
|
private final SessionClientTransport transport;
|
||||||
|
|
||||||
|
public SessionClientTransportFactory(Session session) {
|
||||||
|
transport = new SessionClientTransport(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientTransport newClientTransport() {
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SessionClientTransport extends AbstractService implements ClientTransport {
|
||||||
|
private final Session session;
|
||||||
|
|
||||||
|
public SessionClientTransport(Session session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doStart() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doStop() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClientStream newStream(MethodDescriptor<?, ?> method, StreamListener listener) {
|
||||||
|
final SessionClientStream stream = new SessionClientStream(listener);
|
||||||
|
Request request = session.startRequest(method.getName(), stream.responseBuilder());
|
||||||
|
stream.start(request);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package com.google.net.stubby.stub;
|
|
||||||
|
|
||||||
import com.google.net.stubby.Channel;
|
|
||||||
import com.google.net.stubby.MethodDescriptor;
|
|
||||||
import com.google.net.stubby.Session;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is a shim between Session & Channel. Will be removed when the new transport
|
|
||||||
* API is introduced.
|
|
||||||
*/
|
|
||||||
public class SessionChannel implements Channel {
|
|
||||||
private final Session session;
|
|
||||||
|
|
||||||
public SessionChannel(Session session) {
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <ReqT, RespT> SessionCall<ReqT, RespT> newCall(MethodDescriptor<ReqT, RespT> method) {
|
|
||||||
return new SessionCall<ReqT, RespT>(method, session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue