package org.mobicents.tools.sip.balancer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import com.sun.jdmk.comm.HtmlAdaptorServer;
/**
* @author jean.deruelle@gmail.com
*
*/
public class BalancerRunner implements BalancerRunnerMBean {
private static final String HOST_PROP = "host";
private static final String RMI_REGISTRY_PORT_PROP = "rmiRegistryPort";
private static final String JMX_HTML_ADAPTER_PORT_PROP = "jmxHtmlAdapterPort";
public static final String SIP_BALANCER_JMX_NAME = "mobicents:type=LoadBalancer,name=LoadBalancer";
public static final String HTML_ADAPTOR_PORT = "8000";
public static final String REGISTRY_PORT = "2000";
public static final String HTML_ADAPTOR_JMX_NAME = "mobicents:name=htmladapter,port="+ HTML_ADAPTOR_PORT;
private static Logger logger = Logger.getLogger(BalancerRunner.class
.getCanonicalName());
protected SIPBalancerForwarder fwd = null;
protected NodeRegisterImpl reg = null;
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
ObjectName adapterName = null;
JMXConnectorServer cs = null;
/**
* @param args
*/
public static void main(String[] args) {
if (args.length < 1) {
logger.severe("Please specify mobicents-balancer-config argument. Usage is : java -jar sip-balancer-jar-with-dependencies.jar -mobicents-balancer-config=lb-configuration.properties");
return;
}
if(!args[0].startsWith("-mobicents-balancer-config=")) {
logger.severe("Impossible to find the configuration file since you didn't specify the mobicents-balancer-config argument. Usage is : java -jar sip-balancer-jar-with-dependencies.jar -mobicents-balancer-config=lb-configuration.properties");
return;
}
// Configuration file Location
String configurationFileLocation = args[0].substring("-mobicents-balancer-config=".length());
BalancerRunner balancerRunner = new BalancerRunner();
balancerRunner.start(configurationFileLocation);
}
/**
* @param configurationFileLocation
*/
public void start(String configurationFileLocation) {
File file = new File(configurationFileLocation);
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
throw new IllegalArgumentException("the configuration file location " + configurationFileLocation + " does not exists !");
}
Properties properties = new Properties(System.getProperties());
try {
properties.load(fileInputStream);
} catch (IOException e) {
throw new IllegalArgumentException("Unable to load the properties configuration file located at " + configurationFileLocation);
}
String ipAddress = properties.getProperty(HOST_PROP);
InetAddress addr = null;
try {
addr = InetAddress.getByName(ipAddress);
} catch (UnknownHostException e) {
logger.log(Level.SEVERE, "Couldn't get the InetAddress from the host " + ipAddress, e);
return;
}
int jmxHtmlPort = -1;
String portAsString = properties.getProperty(JMX_HTML_ADAPTER_PORT_PROP,HTML_ADAPTOR_PORT);
try {
jmxHtmlPort = Integer.parseInt(portAsString);
} catch(NumberFormatException nfe) {
logger.log(Level.SEVERE, "Couldn't convert jmxHtmlAdapterPort to a valid integer", nfe);
return ;
}
int rmiRegistryPort = -1;
portAsString = properties.getProperty(RMI_REGISTRY_PORT_PROP,REGISTRY_PORT);
try {
rmiRegistryPort = Integer.parseInt(portAsString);
} catch(NumberFormatException nfe) {
logger.log(Level.SEVERE, "Couldn't convert rmiRegistryPort to a valid integer", nfe);
return ;
}
try {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
//register the jmx html adapter
adapterName = new ObjectName(HTML_ADAPTOR_JMX_NAME);
adapter.setPort(jmxHtmlPort);
server.registerMBean(adapter, adapterName);
RouterImpl.setRegister(reg);
reg = new NodeRegisterImpl(addr);
reg.startRegistry(rmiRegistryPort);
if(logger.isLoggable(Level.FINEST)) {
logger.finest("adding shutdown hook");
}
fwd = new SIPBalancerForwarder(properties, reg);
fwd.start();
//register the sip balancer
ObjectName on = new ObjectName(SIP_BALANCER_JMX_NAME);
if (server.isRegistered(on)) {
server.unregisterMBean(on);
}
server.registerMBean(this, on);
// Create an RMI connector and start it
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + ipAddress + ":" + rmiRegistryPort + "/server");
cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
cs.start();
adapter.start();
Runtime.getRuntime().addShutdownHook(new SipBalancerShutdownHook(this));
} catch (Exception e) {
logger.log(Level.SEVERE, "An unexpected error occurred while starting the load balancer", e);
return;
}
}
public void stop() {
logger.info("Stopping the sip forwarder");
fwd.stop();
logger.info("Stopping the node registry");
reg.stopRegistry();
logger.info("Unregistering the node registry");
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
try {
ObjectName on = new ObjectName(BalancerRunner.SIP_BALANCER_JMX_NAME);
if (server.isRegistered(on)) {
server.unregisterMBean(on);
}
} catch (Exception e) {
logger.log(Level.SEVERE, "An unexpected error occurred while stopping the load balancer", e);
}
try {
cs.stop();
} catch (Exception e) {
logger.log(Level.SEVERE, "An unexpected error occurred while stopping the load balancer", e);
}
adapter.stop();
}
//JMX
public long getNodeExpiration() {
return reg.getNodeExpiration();
}
public long getNodeExpirationTaskInterval() {
return reg.getNodeExpirationTaskInterval();
}
public long getNumberOfRequestsProcessed() {
return fwd.getNumberOfRequestsProcessed();
}
public long getNumberOfResponsesProcessed() {
return fwd.getNumberOfResponsesProcessed();
}
public void setNodeExpiration(long value) {
reg.setNodeExpiration(value);
}
public void setNodeExpirationTaskInterval(long value) {
reg.setNodeExpirationTaskInterval(value);
}
public List<SIPNode> getNodes() {
return reg.getNodes();
}
public String[] getNodeList() {
List<SIPNode> nodes = getNodes();
String[] nodeList = new String[nodes.size()];
int i = 0;
for (SIPNode node : nodes) {
nodeList[0] = node.toString();
i++;
}
return nodeList;
}
public int getNumberOfGluedSessions() {
return reg.getGluedSessions().size();
}
}
class SipBalancerShutdownHook extends Thread {
private static Logger logger = Logger.getLogger(SipBalancerShutdownHook.class
.getCanonicalName());
BalancerRunner balancerRunner;
public SipBalancerShutdownHook(BalancerRunner balancerRunner) {
this.balancerRunner = balancerRunner;
}
@Override
public void run() {
balancerRunner.stop();
}
}