Package org.apache.solr.core

Source Code of org.apache.solr.core.JmxMonitoredMap$SolrDynamicMBean

/**
* 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.solr.core;

import org.apache.solr.common.SolrException;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrConfig.JmxConfiguration;

import javax.management.*;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* <p>
* Responsible for finding (or creating) a MBeanServer from given configuration
* and registering all SolrInfoMBean objects with JMX.
* </p>
* <p/>
* <p>
* Please see http://wiki.apache.org/solr/SolrJmx for instructions on usage and configuration
* </p>
*
* @version $Id: JmxMonitoredMap.java 1148683 2011-07-20 10:14:12Z shalin $
* @see org.apache.solr.core.SolrConfig.JmxConfiguration
* @since solr 1.3
*/
public class JmxMonitoredMap<K, V> extends
        ConcurrentHashMap<String, SolrInfoMBean> {
  private static final Logger LOG = LoggerFactory.getLogger(JmxMonitoredMap.class
          .getName());

  private MBeanServer server = null;

  private String jmxRootName;

  private String coreHashCode;

  public JmxMonitoredMap(String coreName, String coreHashCode,
                          final JmxConfiguration jmxConfig) {
    this.coreHashCode = coreHashCode;
    jmxRootName = "solr" + (coreName == null ? "" : "/" + coreName);

    if (jmxConfig.agentId != null && jmxConfig.serviceUrl != null) {
      throw new SolrException(
              SolrException.ErrorCode.SERVER_ERROR,
              "Incorrect JMX Configuration in solrconfig.xml, both agentId and serviceUrl cannot be specified at the same time");
    }

    if (jmxConfig.serviceUrl == null) {
      List<MBeanServer> servers = null;

      if (jmxConfig.agentId == null) {
        // Try to find the first MBeanServer
        servers = MBeanServerFactory.findMBeanServer(null);
      } else if (jmxConfig.agentId != null) {
        // Try to find the first MBean server with the given agentId
        servers = MBeanServerFactory.findMBeanServer(jmxConfig.agentId);
        // throw Exception if no servers were found with the given agentId
        if (servers == null || servers.isEmpty())
          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
                  "No JMX Servers found with agentId: " + jmxConfig.agentId);
      }

      if (servers == null || servers.isEmpty()) {
        LOG
                .info("No JMX servers found, not exposing Solr information with JMX.");
        return;
      }
      server = servers.get(0);
      LOG.info("JMX monitoring is enabled. Adding Solr mbeans to JMX Server: "
              + server);
    } else {
      try {
        // Create a new MBeanServer with the given serviceUrl
        server = MBeanServerFactory.newMBeanServer();
        JMXConnectorServer connector = JMXConnectorServerFactory
                .newJMXConnectorServer(new JMXServiceURL(jmxConfig.serviceUrl),
                        null, server);
        connector.start();
        LOG.info("JMX monitoring is enabled at " + jmxConfig.serviceUrl);
      } catch (Exception e) {
        // Release the reference
        server = null;
        throw new RuntimeException("Could not start JMX monitoring ", e);
      }
    }
  }

  /**
   * Clears the map and unregisters all SolrInfoMBeans in the map from
   * MBeanServer
   */
  @Override
  public void clear() {
    if (server != null) {
      for (Map.Entry<String, SolrInfoMBean> entry : entrySet()) {
        unregister(entry.getKey(), entry.getValue());
      }
    }

    super.clear();
  }

  /**
   * Adds the SolrInfoMBean to the map and registers the given SolrInfoMBean
   * instance with the MBeanServer defined for this core. If a SolrInfoMBean is
   * already registered with the MBeanServer then it is unregistered and then
   * re-registered.
   *
   * @param key      the JMX type name for this SolrInfoMBean
   * @param infoBean the SolrInfoMBean instance to be registered
   */
  @Override
  public SolrInfoMBean put(String key, SolrInfoMBean infoBean) {
    if (server != null && infoBean != null) {
      try {
        ObjectName name = getObjectName(key, infoBean);
        if (server.isRegistered(name))
          server.unregisterMBean(name);
        SolrDynamicMBean mbean = new SolrDynamicMBean(coreHashCode, infoBean);
        server.registerMBean(mbean, name);
      } catch (Exception e) {
        LOG.warn( "Failed to register info bean: " + key, e);
      }
    }

    return super.put(key, infoBean);
  }

  /**
   * Removes the SolrInfoMBean object at the given key and unregisters it from
   * MBeanServer
   *
   * @param key the JMX type name for this SolrInfoMBean
   */
  @Override
  public SolrInfoMBean remove(Object key) {
    SolrInfoMBean infoBean = get(key);
    if (infoBean != null) {
      try {
        unregister((String) key, infoBean);
      } catch (RuntimeException e) {
        LOG.warn( "Failed to unregister info bean: " + key, e);
      }
    }
    return super.remove(key);
  }

  private void unregister(String key, SolrInfoMBean infoBean) {
    if (server == null)
      return;

    try {
      ObjectName name = getObjectName(key, infoBean);
      if (server.isRegistered(name)) {
        server.unregisterMBean(name);
      } else {
        LOG.info("Failed to unregister mbean: " + key
                + " because it was not registered");
      }
    } catch (Exception e) {
      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
              "Failed to unregister info bean: " + key, e);
    }
  }

  private ObjectName getObjectName(String key, SolrInfoMBean infoBean)
          throws MalformedObjectNameException {
    Hashtable<String, String> map = new Hashtable<String, String>();
    map.put("type", key);
    if (infoBean.getName() != null && !"".equals(infoBean.getName())) {
      map.put("id", infoBean.getName());
    }
    return ObjectName.getInstance(jmxRootName, map);
  }

  /**
   * DynamicMBean is used to dynamically expose all SolrInfoMBean
   * getStatistics() NameList keys as String getters.
   */
  static class SolrDynamicMBean implements DynamicMBean {
    private SolrInfoMBean infoBean;

    private HashSet<String> staticStats;

    private String coreHashCode;

    public SolrDynamicMBean(String coreHashCode, SolrInfoMBean managedResource) {
      this.infoBean = managedResource;
      staticStats = new HashSet<String>();

      // For which getters are already available in SolrInfoMBean
      staticStats.add("name");
      staticStats.add("version");
      staticStats.add("description");
      staticStats.add("category");
      staticStats.add("sourceId");
      staticStats.add("source");
      this.coreHashCode = coreHashCode;
    }

    public MBeanInfo getMBeanInfo() {
      ArrayList<MBeanAttributeInfo> attrInfoList = new ArrayList<MBeanAttributeInfo>();

      for (String stat : staticStats) {
        attrInfoList.add(new MBeanAttributeInfo(stat, String.class.getName(),
                null, true, false, false));
      }

      // add core's hashcode
      attrInfoList.add(new MBeanAttributeInfo("coreHashCode", String.class.getName(),
                null, true, false, false));

      try {
        NamedList dynamicStats = infoBean.getStatistics();
        if (dynamicStats != null) {
          for (int i = 0; i < dynamicStats.size(); i++) {
            String name = dynamicStats.getName(i);
            if (!staticStats.contains(name))
              attrInfoList.add(new MBeanAttributeInfo(dynamicStats.getName(i),
                      String.class.getName(), null, true, false, false));
          }
        }
      } catch (Exception e) {
        LOG.warn( "Could not getStatistics on info bean "
                + infoBean.getName(), e);
      }

      MBeanAttributeInfo[] attrInfoArr = attrInfoList
              .toArray(new MBeanAttributeInfo[attrInfoList.size()]);
      return new MBeanInfo(getClass().getName(), infoBean
              .getDescription(), attrInfoArr, null, null, null);
    }

    public Object getAttribute(String attribute)
            throws AttributeNotFoundException, MBeanException, ReflectionException {
      Object val;
      if ("coreHashCode".equals(attribute)) {
        val = coreHashCode;
      } else if (staticStats.contains(attribute) && attribute != null
              && attribute.length() > 0) {
        try {
          String getter = "get" + attribute.substring(0, 1).toUpperCase(Locale.ENGLISH)
                  + attribute.substring(1);
          Method meth = infoBean.getClass().getMethod(getter);
          val = meth.invoke(infoBean);
        } catch (Exception e) {
          throw new AttributeNotFoundException(attribute);
        }
      } else {
        NamedList list = infoBean.getStatistics();
        val = list.get(attribute);
      }

      if (val != null)
        return val.toString();
      else
        return val;

    }

    public AttributeList getAttributes(String[] attributes) {
      AttributeList list = new AttributeList();
      for (String attribute : attributes) {
        try {
          list.add(new Attribute(attribute, getAttribute(attribute)));
        } catch (Exception e) {
          LOG.warn("Could not get attribute " + attribute);
        }
      }

      return list;
    }

    public void setAttribute(Attribute attribute)
            throws AttributeNotFoundException, InvalidAttributeValueException,
            MBeanException, ReflectionException {
      throw new UnsupportedOperationException("Operation not Supported");
    }

    public AttributeList setAttributes(AttributeList attributes) {
      throw new UnsupportedOperationException("Operation not Supported");
    }

    public Object invoke(String actionName, Object[] params, String[] signature)
            throws MBeanException, ReflectionException {
      throw new UnsupportedOperationException("Operation not Supported");
    }
  }
}
TOP

Related Classes of org.apache.solr.core.JmxMonitoredMap$SolrDynamicMBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.