Index: hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java =================================================================== --- hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java (revision 1556446) +++ hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java (working copy) @@ -746,6 +746,7 @@ /** Whether nonces are enabled; default is true. */ public static String HBASE_RS_NONCES_ENABLED = "hbase.regionserver.nonces.enabled"; + /** * Configuration key for the size of the block cache */ @@ -973,6 +974,21 @@ /** Configuration key for enabling HLog encryption, a boolean */ public static final String ENABLE_WAL_ENCRYPTION = "hbase.regionserver.wal.encryption"; + /** Configuration key for "rmi registry port" */ + public static final String RMI_REGISTRY_PORT = ".rmi.registry.port"; + + /** Configuration key for "rmi connector port" */ + public static final String RMI_CONNECTOR_PORT = ".rmi.connector.port"; + + /** Configuration key for "rmi registry ip" */ + public static final String RMI_REGISTRY_IP = ".rmi.registry.ip"; + + /** Configuration key for "rmi connector name" */ + public static final String RMI_REGISTRY_CONNECTORNAME = ".rmi.registry.connectorname"; + + /** Default rmi registry ip value */ + public static final String RMI_REGISTRY_IP_DEFAULT = "127.0.0.1"; + private HConstants() { // Can't be instantiated with this ctor. } Index: hbase-common/src/main/java/org/apache/hbase/jmx/JMXServer.java =================================================================== --- hbase-common/src/main/java/org/apache/hbase/jmx/JMXServer.java (revision 0) +++ hbase-common/src/main/java/org/apache/hbase/jmx/JMXServer.java (working copy) @@ -0,0 +1,178 @@ +package org.apache.hbase.jmx; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.Socket; +import java.rmi.registry.LocateRegistry; +import java.rmi.server.RMIServerSocketFactory; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import javax.management.MBeanServer; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; +import javax.management.remote.rmi.RMIConnectorServer; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HConstants; + +public class JMXServer { + + private static final Log LOG = LogFactory.getLog(JMXServer.class); + private String jmxIp = null; + private MBeanServer mBeanServer = null; + private String connectorName = null; + private JMXConnectorServer jmxConnectorServer = null; + private Configuration conf; + private String process = ""; + + public JMXServer(Configuration conf, String process) { + this.conf = conf; + this.process = process; + } + + /** + * Starts the JMX server + * + * @param conf + * configuration to be used to read the ports + * @param process + * process name + * @throws IOException + */ + public void start() throws IOException { + + // Start JMX server only if registry port configured. + String jmxPortString = conf.get(process + + HConstants.RMI_REGISTRY_PORT); + if (jmxPortString == null) { + LOG.warn(process + HConstants.RMI_REGISTRY_PORT + + " is not configured for the process " + process + + ", so not starting the JMX server"); + return; + } + + int jmxPort = validatePort(process + + HConstants.RMI_REGISTRY_PORT, jmxPortString); + + mBeanServer = ManagementFactory.getPlatformMBeanServer(); + + String jmxConnectorServerPortString = conf.get(process + + HConstants.RMI_CONNECTOR_PORT); + int jmxConnectorServerPort; + if(jmxConnectorServerPortString == null){ + jmxConnectorServerPort = jmxPort; + } + else{ + jmxConnectorServerPort = validatePort(process + + HConstants.RMI_REGISTRY_PORT, jmxPortString); + } + connectorName = conf.get(process + + HConstants.RMI_REGISTRY_CONNECTORNAME, process); + jmxIp = conf.get(process + HConstants.RMI_REGISTRY_IP, + HConstants.RMI_REGISTRY_IP_DEFAULT); + + RMIServerSocketFactory ssFactory = + new RMIServerSocketFactoryImpl(InetAddress.getByName(jmxIp)); + LocateRegistry.createRegistry(jmxPort, null, ssFactory); + Map env = new HashMap(2); + env.put(RMIConnectorServer.JNDI_REBIND_ATTRIBUTE, Boolean.TRUE.toString()); + env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssFactory); + + JMXServiceURL url = getJmxUrl(jmxPort, jmxConnectorServerPort, + connectorName); + jmxConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, + env, mBeanServer); + jmxConnectorServer.start(); + LOG.info("JMX service started successfully URL : " + url); + } + + /** + * Stops the JMXServer + * + * @throws IOException + */ + public void stop() throws IOException { + if (null != jmxConnectorServer) { + jmxConnectorServer.stop(); + LOG.info("JMX Server stopped successfully"); + } + } + + private JMXServiceURL getJmxUrl(int p_port, int c_port, String p_serviceName) + throws MalformedURLException { + StringBuilder builder = new StringBuilder(); + builder.append("service:jmx:rmi://"); + + if (c_port != -1) { + builder.append(jmxIp); + builder.append(":"); + builder.append(c_port); + } + + builder.append("/jndi/rmi://"); + builder.append(jmxIp); + builder.append(":"); + builder.append(p_port); + builder.append("/"); + builder.append(p_serviceName); + return new JMXServiceURL(builder.toString()); + } + + + + private int validatePort(String property,String portString) { + int port = -1; + try { + port = Integer.parseInt(portString); + } catch (NumberFormatException ne) { + throw new IllegalArgumentException("Invalid value ("+portString + ") configured for "+"\"" + + property + "\"" + "Allowed range [1024-65535]."); + } + if (port < 1024 || port > 65535) { + throw new IllegalArgumentException("Invalid value ("+portString + ") configured for "+"\"" + + property + "\"" +"Allowed range [1024-65535]."); + } + return port; + } + + + /** + * Custom server socket factory to control the binding of server address to + * one IP address. + */ + public static class RMIServerSocketFactoryImpl implements + RMIServerSocketFactory { + private InetAddress bindAddress = null; + + public RMIServerSocketFactoryImpl() { + } + + public RMIServerSocketFactoryImpl(final InetAddress bindAddress) { + this.bindAddress = bindAddress; + } + + public Socket createSocket(String host, int port) throws IOException { + return new Socket(host, port); + } + + public ServerSocket createServerSocket(int port) throws IOException { + if (null != bindAddress) { + LOG.info("Creating socket " + bindAddress.getHostAddress() + ":" + port + + " for JMX Server"); + return new ServerSocket(port, 50, bindAddress); + } + + return new ServerSocket(port); + } + } + + +}