blob: 17eeb0b0e1b8342fe746b7f9a83391245733912b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.uima.collection.impl.cpm.container.deployer.vns;
import java.net.ConnectException;
import java.util.ArrayList;
import org.apache.uima.UIMAFramework;
import org.apache.uima.collection.impl.cpm.utils.CPMUtils;
import org.apache.uima.util.Level;
import org.apache.vinci.transport.BaseClient;
import org.apache.vinci.transport.VinciFrame;
/**
*
* Connects to and querries a given VNS server for a list a services bound to a given name.
*
*/
public class VNSQuery {
private VinciVNSQuery vnsQuery = null;
/**
* Connects to a VNS server identified by host and port
*
* @param aVnsHost -
* VNS host name
* @param aVnsPort -
* VNS port number
*
* @throws Exception -
* when unable to connect to VNS
*/
public VNSQuery(String aVnsHost, int aVnsPort) throws Exception {
vnsQuery = new VinciVNSQuery(aVnsHost, aVnsPort);
}
/**
* Returns a list of services registered in the VNS and bound to a given name.
*
* @param aName -
* name of the service
*
* @return - ArrayList of {@link VinciServiceInfo} instances
*
* @throws Exception -
* unable to get a list
*/
public ArrayList getServices(String aName) throws Exception {
return vnsQuery.getVinciServices(aName);
}
/**
* Returns a list of services that have not yet been assigned to any CPM proxy. It diffs the
* current list and a new list as returned from the VNS.
*
* @param aName -
* name of the service
* @param assignedServices -
* a list of services currently in use
* @return - ArrayList of {@link VinciServiceInfo} instances
*
* @throws Exception -
* unable to get a list
*/
public ArrayList getUnassignedServices(String aName, ArrayList assignedServices) throws Exception {
// Retrieve a new list from the VNS
ArrayList newList = getServices(aName);
// Do a diff between current and new service list
findUnassigned(assignedServices, newList);
return newList;
}
/**
* Diffs two lists of services and returns those that have not yet been assigned
*
* @param oldList -
* current (in-use) list of services
* @param newList -
* new list of services
*
* @return - number of un-assigned services
*/
public static int findUnassigned(ArrayList oldList, ArrayList newList) {
int newServiceCount = 0;
for (int i = 0; i < newList.size(); i++) {
VinciServiceInfo service = (VinciServiceInfo) newList.get(i);
if (!newService(service, oldList)) {
((VinciServiceInfo) newList.get(i)).setAvailable(false);
} else {
newServiceCount++;
}
}
return newServiceCount;
}
/**
* Checks if a service identified by {@link VinciServiceInfo} instance is in use. If a service
* exists in the service list but is not assigned, that means that is available. If the service
* does not exist in the list it is also considered available.
*
* @param aService -
* {@link VinciServiceInfo} instance to locate in the list
* @param oldList -
* list of current (in-use) services
*
* @return - true, if service is available. false, otherwise
*/
private static boolean newService(VinciServiceInfo aService, ArrayList oldList) {
for (int i = 0; i < oldList.size(); i++) {
VinciServiceInfo service = (VinciServiceInfo) oldList.get(i);
if (aService.getHost().equals(service.getHost()) && aService.getPort() == service.getPort()
&& service.isAvailable() == false) {
return false;
}
}
return true;
}
/**
*
* Inner class used for accessing the VNS server.
*
*/
public class VinciVNSQuery {
private String vnsHost;
private int vnsPort;
BaseClient vnsConnection = null;
/**
* Establishes connection to a given VNS server
*
* @param aVnsHost -
* name of the host where the VNS is running
* @param aVnsPort -
* port on which the VNS is listening
* @throws Exception -
* unable to connect to VNS
*/
public VinciVNSQuery(String aVnsHost, int aVnsPort) throws Exception {
vnsHost = aVnsHost;
vnsPort = aVnsPort;
vnsConnection = new BaseClient(vnsHost, vnsPort);
}
/**
* Returns a list of services bound to a given name. It ONLY returns those services that are
* actually running. The VNS may return services that are stale. Those will be filtered out.
*
* @param aVinciServiceName -
* name of the service
* @return - list of services bound to a given name.
*
* @throws Exception -
* error while looking up the service
*/
public ArrayList getVinciServices(String aVinciServiceName) throws Exception {
ArrayList serviceList = new ArrayList();
BaseClient client = null;
// make sure we got a valid connection to VNS
if (vnsConnection != null && vnsConnection.isOpen()) {
// Set up VNS query
VinciFrame queryFrame = new VinciFrame();
queryFrame.fadd("vinci:COMMAND", "getlist");
queryFrame.fadd("PREFIX", aVinciServiceName);
// System.out.println("Query Frame:::"+queryFrame.toXML());
// Query the VNS
VinciFrame response = (VinciFrame) vnsConnection.sendAndReceive(queryFrame);
ArrayList serviceFrames = response.fget("SERVICE");
// Each service is returned in its own SERVICE frame. So cycle through those now
// one at a time
for (int i = 0; i < serviceFrames.size(); i++) {
VinciFrame serviceFrame = (VinciFrame) serviceFrames.get(i);
// Copy data from the frame ( host, port etc)
VinciServiceInfo serviceInfo = getServiceInfo(serviceFrame);
if (serviceInfo != null) {
// Test the service for availability. Use only those services that respond. The list
// may contain stale services that are not running
try {
// Establish a brief connection to test for availability. This test fails gracefully
// Its not an error if the service does not respond. The retry logic is done
// elsewhere.
client = new BaseClient(serviceInfo.getHost(), serviceInfo.getPort());
if (client.isOpen()) {
if (UIMAFramework.getLogger().isLoggable(Level.FINEST)) {
UIMAFramework.getLogger(this.getClass()).logrb(
Level.FINEST,
this.getClass().getName(),
"initialize",
CPMUtils.CPM_LOG_RESOURCE_BUNDLE,
"UIMA_CPM_service_active_on_port__FINEST",
new Object[] { Thread.currentThread().getName(),
serviceInfo.getServiceName(), serviceInfo.getHost(),
String.valueOf(serviceInfo.getPort()) });
}
// Service is ok, so add it to the list
serviceList.add(serviceInfo);
}
} catch (ConnectException ce) {
if (UIMAFramework.getLogger().isLoggable(Level.WARNING)) {
UIMAFramework.getLogger(this.getClass()).logrb(
Level.WARNING,
this.getClass().getName(),
"initialize",
CPMUtils.CPM_LOG_RESOURCE_BUNDLE,
"UIMA_CPM_service_not_active_on_port__WARNING",
new Object[] { Thread.currentThread().getName(),
serviceInfo.getServiceName(), serviceInfo.getHost(),
String.valueOf(serviceInfo.getPort()) });
}
} finally {
// Drop the connection if necessary.
if (client != null) {
try {
client.close();
} catch (Exception ex) {
}
}
}
}
}
}
return serviceList;
}
/**
* Copy service information from Vinci frame.
*
* @param aServiceFrame -
* Vinci frame containing service info
*
* @return- instance of {@link VinciServiceInfo} containing service info
*/
private VinciServiceInfo getServiceInfo(VinciFrame aServiceFrame) {
String serviceName = aServiceFrame.fgetString("NAME");
String service_host_IP = aServiceFrame.fgetString("IP");
int service_port = aServiceFrame.fgetInt("PORT");
VinciServiceInfo serviceInfo = new VinciServiceInfo(serviceName, service_host_IP,
service_port);
return serviceInfo;
}
}
public static void main(String[] args) {
try {
VNSQuery vq = new VNSQuery(args[0], Integer.parseInt(args[1]));
ArrayList list = vq.getServices(args[2]);
System.out.println("Got::" + list.size() + " Services");
BaseClient client = null;
for (int i = 0; i < list.size(); i++) {
Object ob = list.get(i);
if (ob != null) {
System.out.println(((VinciServiceInfo) ob).toString());
VinciServiceInfo serviceInfo = (VinciServiceInfo) ob;
if (serviceInfo != null) {
try {
client = new BaseClient(serviceInfo.getHost(), serviceInfo.getPort());
if (client.isOpen()) {
System.out.println("Service::" + serviceInfo.getServiceName() + " is alive");
}
} catch (ConnectException ce) {
System.out.println("Service::" + serviceInfo.getServiceName() + " is down");
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}