com.microsoft.reef.io.network.naming.NameLookupClient Maven / Gradle / Ivy
/**
* Copyright (C) 2013 Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.microsoft.reef.io.network.naming;
import com.microsoft.reef.io.naming.NameAssignment;
import com.microsoft.reef.io.naming.NamingLookup;
import com.microsoft.reef.io.network.Cache;
import com.microsoft.reef.io.network.naming.exception.NamingException;
import com.microsoft.reef.io.network.naming.serialization.NamingLookupRequest;
import com.microsoft.reef.io.network.naming.serialization.NamingLookupResponse;
import com.microsoft.reef.io.network.naming.serialization.NamingMessage;
import com.microsoft.tang.annotations.Name;
import com.microsoft.tang.annotations.NamedParameter;
import com.microsoft.wake.EventHandler;
import com.microsoft.wake.Identifier;
import com.microsoft.wake.IdentifierFactory;
import com.microsoft.wake.Stage;
import com.microsoft.wake.impl.SyncStage;
import com.microsoft.wake.remote.Codec;
import com.microsoft.wake.remote.NetUtils;
import com.microsoft.wake.remote.impl.TransportEvent;
import com.microsoft.wake.remote.transport.Link;
import com.microsoft.wake.remote.transport.Transport;
import com.microsoft.wake.remote.transport.netty.LoggingLinkListener;
import com.microsoft.wake.remote.transport.netty.NettyMessagingTransport;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Naming lookup client
*/
public class NameLookupClient implements Stage, NamingLookup {
private static final Logger LOG = Logger.getLogger(NameLookupClient.class.getName());
@NamedParameter(doc="When should a retry timeout(msec)?", short_name="retryTimeout", default_value="100")
public static class RetryTimeout implements Name {}
@NamedParameter(doc="How many times should I retry?", short_name="retryCount", default_value="10")
public static class RetryCount implements Name {}
private final SocketAddress serverSocketAddr;
private final Transport transport;
private final Codec codec;
private final BlockingQueue replyQueue;
private final long timeout;
private final Cache cache;
private final int retryCount;
private final int retryTimeout;
/**
* Constructs a naming lookup client
*
* @param serverAddr a server address
* @param serverPort a server port number
* @param factory an identifier factory
* @param cache an cache
*/
public NameLookupClient(String serverAddr, int serverPort,
IdentifierFactory factory, int retryCount, int retryTimeout,
Cache cache) {
this(serverAddr, serverPort, 10000, factory, retryCount, retryTimeout, cache);
}
/**
* Constructs a naming lookup client
*
* @param serverAddr a server address
* @param serverPort a server port number
* @param timeout request timeout in ms
* @param factory an identifier factory
* @param cache an cache
*/
public NameLookupClient(String serverAddr, int serverPort, long timeout,
IdentifierFactory factory, int retryCount, int retryTimeout,
Cache cache) {
serverSocketAddr = new InetSocketAddress(serverAddr, serverPort);
this.timeout = timeout;
this.cache = cache;
replyQueue = new LinkedBlockingQueue();
codec = NamingCodecFactory.createLookupCodec(factory);
transport = new NettyMessagingTransport(NetUtils.getLocalAddress(), 0,
new SyncStage(new NamingLookupClientHandler(
new NamingLookupResponseHandler(replyQueue), codec)), null);
this.retryCount = retryCount;
this.retryTimeout = retryTimeout;
}
NameLookupClient(String serverAddr, int serverPort, long timeout,
IdentifierFactory factory, int retryCount, int retryTimeout,
BlockingQueue replyQueue, Transport transport,
Cache cache) {
serverSocketAddr = new InetSocketAddress(serverAddr, serverPort);
this.timeout = timeout;
this.cache = cache;
codec = NamingCodecFactory.createFullCodec(factory);
this.replyQueue = replyQueue;
this.transport = transport;
this.retryCount = retryCount;
this.retryTimeout = retryTimeout;
}
/**
* Finds an address for an identifier
*
* @param id an identifier
* @return an Internet socket address
*/
@Override
public InetSocketAddress lookup(final Identifier id) throws Exception {
return cache.get(id, new Callable() {
@Override
public InetSocketAddress call() throws Exception {
int retryCount = NameLookupClient.this.retryCount;
int retryTimeout = NameLookupClient.this.retryTimeout;
while(true){
try {
return remoteLookup(id);
} catch (NamingException e) {
if(retryCount<=0)
throw e;
else{
LOG.log(Level.WARNING,
"Caught Naming Exception while looking up " + id
+ " with Name Server. Will retry " + retryCount
+ " time(s) after waiting for " + retryTimeout + " msec.");
Thread.sleep(retryTimeout);
--retryCount;
}
}
}
}
});
}
/**
* Retrieves an address for an identifier remotely
*
* @param id an identifier
* @return an Internet socket address
* @throws Exception
*/
public InetSocketAddress remoteLookup(Identifier id) throws Exception {
// the lookup is not thread-safe, because concurrent replies may
// be read by the wrong thread.
// TODO: better fix uses a map of id's after REEF-198
synchronized (this) {
LOG.log(Level.INFO, "Looking up " + id.toString() + " on NameServer " + serverSocketAddr.toString());
List ids = Arrays.asList(id);
Link link = transport.open(serverSocketAddr, codec,
new LoggingLinkListener());
link.write(new NamingLookupRequest(ids));
NamingLookupResponse resp;
while(true) {
try {
resp = replyQueue.poll(timeout, TimeUnit.MILLISECONDS);
break;
} catch (InterruptedException e) {
e.printStackTrace();
throw new NamingException(e);
}
}
List list = resp.getNameAssignments();
if (list.size() <= 0)
throw new NamingException("Cannot find " + id + " from the name server");
else
return list.get(0).getAddress();
}
}
/**
* Closes resources
*/
@Override
public void close() throws Exception {
// Should not close transport as we did not
// create it
}
}
/**
* Naming lookup client transport event handler
*/
class NamingLookupClientHandler implements EventHandler {
private final EventHandler handler;
private final Codec codec;
NamingLookupClientHandler(EventHandler handler, Codec codec) {
this.handler = handler;
this.codec = codec;
}
@Override
public void onNext(TransportEvent value) {
handler.onNext((NamingLookupResponse)codec.decode(value.getData()));
}
}
/**
* Naming lookup response handler
*/
class NamingLookupResponseHandler implements EventHandler {
private final BlockingQueue replyQueue;
NamingLookupResponseHandler(BlockingQueue replyQueue) {
this.replyQueue = replyQueue;
}
@Override
public void onNext(NamingLookupResponse value) {
replyQueue.offer(value);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy