Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

[REEF-362] Implement a Wake Transport using HTTP #1341

Open
wants to merge 38 commits into
base: master
Choose a base branch
from

Conversation

nhne
Copy link
Contributor

@nhne nhne commented Jul 23, 2017

Additional implementation for Wake via HTTP

  • new package org.apache.reef.wake.remote.transport.netty.http
  • no new package created.
  • followed default implementation of netty
  • Added TransportHttpTest
  • currently tested only for HTTP

JIRA:
REEF-362

Pull Request
This closes #1341

Additional implementation for Wake via HTTP

JIRA:
[REEF-362](https://issues.apache.org/jira/browse/REEF-362)

Pull Request
This closes #
@DifferentSC
Copy link

@nhne How about adding tests on RemoteManager using HttpMessagingTransportFactory?

@nhne
Copy link
Contributor Author

nhne commented Jul 25, 2017

Added one Test on RemoteManager with HttpMessagingTransportFactory.

@taegeonum
Copy link
Contributor

taegeonum commented Aug 8, 2017

@nhne I've skimmed through this PR, but it looks like it has a bunch of duplicated codes. Can't we minimize the duplicated codes? Maybe we need to refactor the original code to do this.

@nhne
Copy link
Contributor Author

nhne commented Aug 8, 2017

I implmeneted in this way to avoid modify the original code. I just worried I can insert err code into original code and compatibility issues. I think refactoring the original code can be eliminate many duplicated code since It does not have much difference. What Do you think would be better?

Refactored Netty Messaging Transportand Netty Link and Listeners. but still have to change implmentation of MessagingTransportFactory
Copy link

@DifferentSC DifferentSC left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have done the initial pass.

/**
* Option for use http.
*/
@NamedParameter(doc = "Option for use http.", default_value = "" + PROTOCOL_NETTY)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converting String using blank string and + is a bad practice. Use String.valueOf instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was used across the original source. Is it better to update to String.valueOf every use?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to make another issue for refactoring the whole project.

* @return transport
*/
Transport newInstance(final String hostAddress,
int port,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no final here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be refactored during another PR. Thank you!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to refactor it in another PR because it is a new code. Please just add final here.

final int retryTimeout,
final int protocol) {
try {
TcpPortProvider tcpPortProvider = Tang.Factory.getTang().newInjector().getInstance(TcpPortProvider.class);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

import io.netty.channel.ChannelFutureListener;
import org.apache.reef.wake.remote.transport.LinkListener;

class NettyChannelFutureListener<T> implements ChannelFutureListener {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class should be public & final if there is no class extending it.

/**
* the buffer size of the frame decoder.
*/
public static final int MAXFRAMELENGTH = 10 * 1024 * 1024;
private final NettyChannelHandlerFactory handlerFactory;
private final SslContext sslContext;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think explanations on these variables are necessary.

}

final Channel channel = ctx.channel();
byte[] message = new byte[content.readableBytes()];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

}

@Override
protected void exceptionCleanup(final ChannelHandlerContext ctx, final Throwable cause) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no operation here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required method to extend AbstractNettyEventyListener and it only performs close channel when it is clientListener.


if (this.uri != null) {
try {
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uri.getRawPath());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

if (listener != null) {
future.addListener(new NettyChannelFutureListener<>(message, listener));
}
} catch (InterruptedException ex) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

private final AbstractNettyEventListener clientEventListener;
private final AbstractNettyEventListener serverEventListener;

private final boolean ssl = System.getProperty("ssl") != null;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think initializing final variable here is good, because it is not a static variable. How about moving this into the constructor?

@nhne
Copy link
Contributor Author

nhne commented Aug 17, 2017

@DifferentSC Thank you for reviewing my work! I'll check the things you reviewed.

Copy link
Contributor

@motus motus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done with my round of nit-picking :)

* Unique protocol numbers for choosing protocols.
*/
public static final int PROTOCOL_NETTY = 100;
public static final int PROTOCOL_HTTP = 101;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use enum here.

Copy link
Contributor Author

@nhne nhne Aug 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, @DifferentSC said that using enum which is related to Tang Configuration might be not supported for now. Instead, I suggest it could be changed to static final String.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transport newInstance(final int port,
final EventHandler<TransportEvent> clientHandler,
final EventHandler<TransportEvent> serverHandler,
final EventHandler<Exception> exHandler);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love my variables final, but we probably should not mix functional and non-functional updates in one PR. Next time please submit your stylistic fixes in a separate pull request (and yes, we welcome such updates!) :)

@@ -93,7 +93,7 @@ public Transport newInstance(final String hostAddress,
final int numberOfTries,
final int retryTimeout) {
try {
TcpPortProvider tcpPortProvider = Tang.Factory.getTang().newInjector().getInstance(TcpPortProvider.class);
final TcpPortProvider tcpPortProvider = Tang.Factory.getTang().newInjector().getInstance(TcpPortProvider.class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tang.Factory.getTang() called many times in this class. Can declare

private static final Tang TANG = Tang.Factory.getTang();


private static final int HANDLER_NETTY = 100;
private static final int HANDLER_HTTP_SERVER = 101;
private static final int HANDLER_HTTP_CLIENT = 102;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum?

final class NettyHttpClientEventListener extends AbstractNettyEventListener {

private static final Logger LOG = Logger.getLogger(NettyHttpClientEventListener.class.getName());
private StringBuilder buf = new StringBuilder();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final?

new InetSocketAddress(hostAddress, port),
new ObjectSerializableCodec<String>(),
new LoggingLinkListener<String>());
link.write(new String("hello1"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for new String(...) - "hello1" is a string already

Copy link
Contributor Author

@nhne nhne Aug 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test was pasted from former TransportTest. This whole test would be changed after refactoring code. Thank you!

new ObjectSerializableCodec<String>(),
new LoggingLinkListener<String>());
link.write(new String("hello1"));
link.write(new String("hello2"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above


@Test
public void testHttpTransportTestEvent() throws Exception {
System.out.println(LOG_PREFIX + name.getMethodName());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use logging instead

link.write(new TestEvent("hello2", 1.0));

monitor.mwait();
transport.close();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transport implements AutoCloseable - can use it in try block instead of calling .close() explicitly

private final Codec<T> codec;
private final Monitor monitor;
private final int expected;
private AtomicInteger count = new AtomicInteger(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

@nhne
Copy link
Contributor Author

nhne commented Aug 21, 2017

@motus I appreciate for your kind and precise review! I'll check out all about these. thanks a lot!

@DifferentSC
Copy link

Thanks a lot for your detailed comments, @motus! We have decided to split this issue into two, by making a new JIRA issue for refactoring and changing styles of Transport. @nhne will work on implementing HTTP transport after the refactoring is done. Thanks!

@@ -108,23 +150,3 @@ public String toString() {
return "NettyLink: " + channel; // Channel has good .toString() implementation
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is separted into another file "NettyChannelFutureListener.java"

Copy link
Contributor

@taegeonum taegeonum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did my first pass. Thanks a lot for the work @nhne !

final EStage<TransportEvent> serverStage,
final int numberOfTries,
final int retryTimeout,
final String protocol);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using enum?

final EStage<TransportEvent> serverStage,
final int numberOfTries,
final int retryTimeout,
final String protocol) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this variable is not used

* @return transport
*/
Transport newInstance(final String hostAddress,
int port,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to refactor it in another PR because it is a new code. Please just add final here.

public final class NettyChannelFutureListener<T> implements ChannelFutureListener {

private final T message;
private LinkListener<T> listener;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final


/* Types for initiating channel */
public enum ChannelType {
NETTY, HTTP_SERVER, HTTP_CLIENT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is NETTY? Is it a tcp or udp socket channel? The naming is unclear to me because HTTP server and client also uses Netty.

import java.util.logging.Logger;

/**
* A Netty event listener for server.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

server -> client?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, my mistake! Thank you!

this.httpRequest = request;

if (!headers.isEmpty()) {
for (final Map.Entry<String, String> h: headers) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h (space):

}
buf.append("\r\n");
}

Copy link
Contributor

@taegeonum taegeonum Aug 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Don't we have to create a new StringBuillder here?

if (listener != null) {
future.addListener(new NettyChannelFutureListener<>(message, listener));

if (this.uri != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think creating a NettyHttpLink would be better instead of fixing this class.
We have to check whenever .write is called whether the uri is null or not. This doesn't look good to me.

this.clientEventListener = new NettyClientEventListener(this.addrToLinkRefMap, clientStage);
this.serverEventListener = new NettyServerEventListener(this.addrToLinkRefMap, serverStage);
if (protocolType.equals(PROTOCOL_NETTY)) {
this.clientEventListener = new NettyClientEventListener(this.addrToLinkRefMap, clientStage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about receiving client and server event listener from the constructor?
We can remove if ... else if we inject them in the constructor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've discussed it with @nhne in offline, and we decided not to refactor the constructor because there is a little benefit of refactoring it.

@nhne
Copy link
Contributor Author

nhne commented Aug 23, 2017

@taegeonum Thanks for sharing detailed review! I'll check all you mentioned above. Thank you.

Copy link
Contributor

@taegeonum taegeonum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhne I did my another pass. Thanks!

/**
* Factory that creates a NettyLink.
*/
public final class NettyDefaultLinkFactory<T> implements NettyLinkFactory {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you create HttpLinkFactory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created NettyHttpLinkFactory. Thank you!

* @param listener the listener
*/
Link<T> newInstance(final Channel channel,
final Encoder<? super T> encoder,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pleas align the lines


@Override
public String toString() {
return "NettyLink: " + channel; // Channel has good .toString() implementation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a StringBuffer

* If you set a {@code LinkListener<T>}, it keeps message until writeAndFlush operation completes
* and notifies whether the sent message transferred successfully through the listener.
*/
public class NettyHttpLink<T> implements Link<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

final

buf.setLength(0); // clearing the buffer
}

if (message.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain when does the message length is zero? and don't we send the message if the length is zero?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By currrent implementation, Server does not send any response to client. Actually NettyHttpEventListener does not receive any response now. But if server return the response to client, there can be HttpResponse with empty message.

We can choose to clear the channelRead method to do nothing or leave it for latter usage.

*/
public static final String PROTOCOL_TCP = ProtocolTypes.TCP.name();
public static final String PROTOCOL_HTTP = ProtocolTypes.HTTP.name();
public static final String PROTOCOL_HTTPS = ProtocolTypes.HTTPS.name();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we handle supporting https in this PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I Think features about HTTPS should be handled in another PR. Thank you!

@nhne
Copy link
Contributor Author

nhne commented Nov 6, 2017

Thanks for your review! @taegeonum. I'll reconsider the structure of Http Channels considering your review.

@nhne
Copy link
Contributor Author

nhne commented Nov 23, 2017

@taegeonum Sorry for very late commit! I have addressed the review. Would you please have a look?

Copy link
Contributor

@taegeonum taegeonum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did another pass. Thanks for the work @nhne !

if(isServer) {
pipeline
.addLast("codec", new HttpServerCodec())
.addLast("requestDecoder", new HttpRequestDecoder())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need both HttpServerCodec and HttpRequestDecoder/Encoder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed example in the Netty Http server. But by reference document, I think we do need additional codec since HttpServerCodec is combination of them. I'll remove and test about it.

default:
throw new IllegalArgumentException("Invalid type of channel");
}
// every channel's pipeline have a same inbound handler.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

every channel pipeline has the same inbound handler

this.stage.onNext(this.getTransportEvent(message, channel));
}
} else {
LOG.log(Level.SEVERE, "Unknown type of message received: {0}", msg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throw exception?


content.readBytes(message);
if (LOG.isLoggable(Level.FINEST)) {
buf.append("CONTENT: ").append(content.toString(CharsetUtil.UTF_8)).append("\r\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you define buf as a local variable? It doesn't look like this should be a member variable.

.set(HttpHeaders.Names.CONTENT_LENGTH, buf.readableBytes());
request.content().clear().writeBytes(buf);
final ChannelFuture future = channel.writeAndFlush(request);
future.sync();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why sync here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to throw exception when the result of future is failure by sync(). but i found its order is weird because listener must be added before its sync!

*/
final class NettyHttpServerEventListener extends AbstractNettyEventListener {

private final StringBuilder buf = new StringBuilder();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Do we have to define it as a member variable?

@nhne
Copy link
Contributor Author

nhne commented Nov 24, 2017

My former implementation need buf as global variable, but now we don't have to keep it global, so I converted it into local.
Also I fixed misusing of codec in NettyChannelInitializer and sync in NettyHttpLink.
@taegeonum Thank you for your review!

Copy link
Contributor

@taegeonum taegeonum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhne I left some comments. Thanks!

final ByteBuf content = httpContent.content();
final Channel channel = ctx.channel();
final byte[] message = new byte[content.readableBytes()];
final StringBuilder buf = new StringBuilder();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please put this variable inside the following if block (line 62)

}

@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about the following code?

public void channelRead(final ChannelHandlerContext ctx, final FullHttpResponse response) {

	byte[] content = null;
	ByteBuf byteBuf = response.content();
	if (byteBuf.hasArray()) {
		content = byteBuf.array();
	} else {
		content = new byte[byteBuf.readableBytes()];
		byteBuf.readBytes(content);
	}
        .... 
}

Copy link
Contributor Author

@nhne nhne Dec 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry that as method channelRead is overriding method, I cannot change type of parameter.
But i'll adapt the name change and other things. Thank you!

}

@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the ClientEventListener codes

logging buffer's behavior has changed, content variable also changed
@nhne
Copy link
Contributor Author

nhne commented Dec 5, 2017

Sorry for late check. I have committed about your review. Thank you very much! @taegeonum

Copy link
Contributor

@taegeonum taegeonum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhne I left minor comments :)

channel.localAddress(), channel.remoteAddress(), buf});
}

if (content.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this check necessary?

channel.localAddress(), channel.remoteAddress(), byteBuf});
}

if (content.length > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this check necessary?

@nhne
Copy link
Contributor Author

nhne commented Dec 6, 2017

I thought about this somewhile... If any listener expect any response without any parameter, intetionally empty request can be sent. Then, this check would be erroneous. So I removed the if statements.

Thank you! @taegeonum

Copy link
Contributor

@taegeonum taegeonum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhne I also left some comments :) Could you please take a look at them?

if (listener != null) {
future.addListener(new NettyChannelFutureListener<>(message, listener));
}
future.sync();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you sync here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is because sync() will throw an Exception when sending request is Interrupted. To catch a failure on sending request, sync was used here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, why do we need sync? you already registered the future listener and it doesn't look we need sync()

Copy link
Contributor Author

@nhne nhne Dec 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

listener can be null in constructor. If there is no listener attached, there would be no warning about failure on sending request. In my opinion, if default listener for failure detection is provided, we don't have to use sync().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Future and listener is to asynchronously write the requests, but if you do sync() immediately, I think there is no benefit of the asynchronous write.

Copy link
Contributor Author

@nhne nhne Dec 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I strongly agree with you. Then what about change the implmentation to adopt default listener for detect failure on complete? or just delete sync()? Can I ask which would be better choice?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't fully understand your question. You've already registered the future listener in line 104.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@taegeonum the listener can be null. The constructor of NettyHttpLink at line59 makes listener null. So There can be no listener for catching failure if sync() is not performed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhne I see. I think it is okay to me. If we want to ignore the message futures, we can skip the listener. Otherwise, we provide the listener and handle the message futures. So, how about just removing sync()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'll remove sync(). User may provide listener if they need any failure detection. Thank you for sharing your opinion!

try {
final FullHttpRequest request =
new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uri.getRawPath());
final ByteBuf buf = Unpooled.copiedBuffer(encoder.encode(message));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you use wrappedBuffer? copiedBuffer performs additional byte copy.

@nhne
Copy link
Contributor Author

nhne commented Dec 7, 2017

@taegeonum I have changed copiedBuffer into wrappedBuffer. Also I commented about sync upper.
Thank you for your review!

@nhne
Copy link
Contributor Author

nhne commented Jan 4, 2018

@taegeonum Thank you for sharing your idea for sync(). I have removed it from NettyHttpLink. Thank you!

*/
@Override
public void write(final T message) {
LOG.log(Level.FINEST, "write {0} :: {1}", new Object[] {channel, message});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add the following code?

if (LOG.isLoggable(Level.FINEST)) {

@nhne
Copy link
Contributor Author

nhne commented Jan 5, 2018

@taegeonum fixed the LOG check. Thank you!


// for HTTP and default Netty
if (protocolType == ProtocolType.HTTP) {
this.uri = URI.create("http://" + hostAddress);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nhne hostAddress -> host
I've got an exception message when I tested it on my local machine, even though the test passed

Caused by: java.lang.IllegalArgumentException: Illegal character in fragment at index 8: http://##UNKNOWN##
	at java.net.URI.create(URI.java:852)
	at org.apache.reef.wake.remote.transport.netty.NettyMessagingTransport.<init>(NettyMessagingTransport.java:139)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
	at org.apache.reef.tang.implementation.java.InjectorImpl.injectFromPlan(InjectorImpl.java:637)
	... 41 more

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for late check. I had to reconfigure my environment to reproduce the error. I'll fix it and push a commit now!

@nhne
Copy link
Contributor Author

nhne commented Feb 11, 2018

@taegeonum I have fixed hostAddress into host. also I found URI.create can cause an IllegalArgumentException on invalid address, so I added RemoteRuntimeException about this invalid URI.
Thank you for finding this error!

@@ -139,7 +139,7 @@ private NettyMessagingTransport(
try{
this.uri = URI.create("http://" + host);
} catch (IllegalArgumentException e){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add final ?

@taegeonum
Copy link
Contributor

@nhne LGTM except for the last comment :)

@nhne
Copy link
Contributor Author

nhne commented Apr 1, 2018

@taegeonum I have pushed a commit reflecting your review. Thank you!

@bgchun
Copy link
Contributor

bgchun commented Apr 1, 2018

@nhne @taegeonum Thanks for working on this issue. Could you also make sure that this PR works correctly in distributed environments?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants