public void open(String service_name) throws ServiceDownException, VNSException {
this.serviceName = service_name;
ResolveResult response = null;
Transportable query = null;
boolean connectFailed = false;
VinciContext myContext = getContext();
boolean usedCache = false;
ArrayList alreadyTried = null;
String vnsHost = myContext.getVNSHost();
int vnsPort = myContext.getVNSPort();
// Check to see if default host/port are being overridden by vns "@" specification in service
// name
int atIndex = service_name.indexOf('@');
if (atIndex != -1) {
vnsHost = service_name.substring(atIndex + 1);
int colonIndex = vnsHost.indexOf(':');
if (colonIndex != -1) {
try {
vnsPort = Integer.parseInt(vnsHost.substring(colonIndex + 1));
} catch (NumberFormatException e) {
throw new VNSException("Bad vns port specification in service name: " + service_name);
}
vnsHost = vnsHost.substring(0, colonIndex);
}
}
// ^^ A list of service locations that have already been determined to be
// unavailable.
for (;;) {
try {
response = myContext.getCachedResolveResult(serviceName);
if (response == null) {
usedCache = false;
if (query == null) {
query = ResolveResult.composeQuery(serviceName);
}
response = (ResolveResult) BaseClient.sendAndReceive(query, vnsHost, vnsPort,
ResolveResult.factory, myContext.getVNSResolveTimeout());
myContext.cacheResolveResult(serviceName, response);
} else {
usedCache = true;
Debug.p("Using cached VNS entry.");
}
} catch (IOException e) {
// VNS is inaccessible. See if there is a (stale) cached entry we can use.
if (myContext.areStaleLookupsAllowed()) {
response = myContext.getStaleCachedResolveResult(serviceName);
if (response == null) {
throw new ServiceDownException("VNS inaccessible: " + e);
} else {
Debug.reportException(e);
Debug.p("VNS is not accessible, using STALE cached resolve result.");
}
}
} catch (ServiceException e) {
if (connectFailed) {
throw new ServiceDownException("Could not connect to service: " + serviceName);
}
throw new VNSException(e.getMessage());
}
// Iterate over all available service locations until we find one that
// accepts our connection request.
response.initializeIterator();
while (response.hasMore()) {
ResolveResult.ServiceLocator locator = response.getNext();
if (alreadyTried == null || !alreadyTried.contains(locator.host + ":" + locator.port)) {
try {
open(locator.host, locator.port);
this.instance = locator.instance;
this.level = response.priority;
Debug.p("Resolved " + serviceName + " to: " + locator.host + ":" + locator.port);
return;
} catch (IOException e) {
Debug.p("WARNING: Failed to connect to service at (" + locator.host + ":"
+ locator.port + "):" + e.getMessage());
connectFailed = true;
if (alreadyTried == null) {
alreadyTried = new ArrayList();
}
alreadyTried.add(locator.host + ":" + locator.port);
}
}
}
if (usedCache) {
// It's possible that the cache entry is no longer up to date due
// to sudden service restart. Flush the entry and try again.
myContext.flushFromCache(serviceName);
Debug.p("Retrying service resolution without using cache.");
} else if (response.priority != 0 && !ResolveResult.isQualified(serviceName)) {
// If a service name was specified without qualifications, then
// we allow fail-over to lower-priority services.
Debug.p("VinciClient.open(String)", "Resolving with lower priority than: "
+ response.priority);
myContext.flushFromCache(serviceName);
int next_level = response.priority;
if (next_level == -1) {
next_level = Integer.MAX_VALUE;
} else {
next_level--;