package edu.washington.escience.myria.parallel;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.Objects;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import edu.washington.escience.myria.proto.ControlProto;
/**
* A simple wrapper that wraps the socket information of both workers and the server (coordinator).
*/
public final class SocketInfo implements Serializable {
/** Class-specific magic number used to generate the hash code. */
private static final int MAGIC_HASHCODE1 = 947;
/** Class-specific magic number used to generate the hash code. */
private static final int MAGIC_HASHCODE2 = 91;
/**
* Create a SocketInfo object from a string in the format host:port.
*
* @param hostPort a string in the format (host:port) that describes a socket.
* @return a SocketInfo corresponding to the given string.
*/
public static SocketInfo valueOf(final String hostPort) {
Objects.requireNonNull(hostPort);
final String[] parts = hostPort.split(":");
if (parts.length != 2) {
throw new IllegalArgumentException("argument is not of format (host:port)");
}
return new SocketInfo(parts[0], Integer.parseInt(parts[1]));
}
/** The hash code of this immutable SocketInfo. */
private Integer myHashCode = null;
/** Required for Java serialization. */
private static final long serialVersionUID = 1L;
/** The host (name or IP) of the network connection. */
private final String host;
/** The port of the connection. */
private final int port;
/** A SocketAddress that holds these info (for connection). */
private transient InetSocketAddress connectAddress;
/** A SocketAddress that holds these info (for binding/listening). */
private transient InetSocketAddress bindAddress;
/** A String host:port. */
private transient String hostPortString;
/**
*
* @param host the name or IPv4 of the network address.
* @param port as usual, 16-bit port.
*/
public SocketInfo(final String host, final int port) {
Objects.requireNonNull(host);
Objects.requireNonNull(port);
this.host = host;
this.port = port;
}
/**
* Local address.
*
* @param port as usual, 16-bit port.
* */
public SocketInfo(final int port) {
Objects.requireNonNull(port);
host = "localhost";
this.port = port;
}
@Override
public boolean equals(final Object other) {
if (this == other) {
return true;
}
if (!(other instanceof SocketInfo)) {
return false;
}
final SocketInfo sockInfo = (SocketInfo) other;
return (sockInfo.host.equals(host)) && (sockInfo.port == port);
}
/**
* @return an InetSocketAddress that describes the given host:port address. Use this when you want a remote address to
* connect to, or for printing.
*/
public InetSocketAddress getConnectAddress() {
if (connectAddress == null) {
connectAddress = new InetSocketAddress(host, port);
}
return connectAddress;
}
/**
* @return an InetSocketAddress that contains the port, but not the host. Use this when you want to bind a server that
* will listen on all interfaces & hostnames.
*/
public InetSocketAddress getBindAddress() {
if (bindAddress == null) {
bindAddress = new InetSocketAddress(port);
}
return bindAddress;
}
/**
* @return the host string.
*/
public String getHost() {
return host;
}
/**
* @return the port.
*/
public int getPort() {
return port;
}
@Override
public int hashCode() {
/* If cached, use the cached version. */
if (myHashCode != null) {
return myHashCode;
}
/* Compute and cache the hash code. */
final HashCodeBuilder hb = new HashCodeBuilder(MAGIC_HASHCODE1, MAGIC_HASHCODE2);
hb.append(host).append(port);
final int hash = hb.toHashCode();
myHashCode = hash;
return hash;
}
@Override
public String toString() {
if (hostPortString == null) {
hostPortString = host + ":" + port;
}
return hostPortString;
}
/**
* @return the protobuf message representation of this class.
* */
public ControlProto.SocketInfo toProtobuf() {
return ControlProto.SocketInfo.newBuilder().setHost(host).setPort(port).build();
}
/**
* @param socketinfo the protobuf version of socket info.
* @return a SocketInfo object translated from protobuf.
* */
public static SocketInfo fromProtobuf(final ControlProto.SocketInfo socketinfo) {
return new SocketInfo(socketinfo.getHost(), socketinfo.getPort());
}
}