/**
 * 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.hadoop.hbase;

import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
import org.apache.hadoop.hbase.master.balancer.BalancerTestBase;
import org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.MiscTests;
import org.apache.hadoop.hbase.util.Threads;
import org.apache.hadoop.net.DNSToSwitchMapping;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runners.MethodSorters;

@Category({ MiscTests.class, MediumTests.class })
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Ignore
public class TestStochasticBalancerJmxMetrics extends BalancerTestBase {
  private static final Log LOG = LogFactory.getLog(TestStochasticBalancerJmxMetrics.class);
  private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
  private static int connectorPort = 61120;
  private static StochasticLoadBalancer loadBalancer;
  /**
   * a simple cluster for testing JMX.
   */
  private static int[] mockCluster_ensemble = new int[] { 0, 1, 2, 3 };
  private static int[] mockCluster_pertable_1 = new int[] { 0, 1, 2 };
  private static int[] mockCluster_pertable_2 = new int[] { 3, 1, 1 };
  private static int[] mockCluster_pertable_namespace = new int[] { 1, 3, 1 };

  private static final String TABLE_NAME_1 = "Table1";
  private static final String TABLE_NAME_2 = "Table2";
  private static final String TABLE_NAME_NAMESPACE = "hbase:namespace";

  private static Configuration conf = null;

  /**
   * Setup the environment for the test.
   */
  @BeforeClass
  public static void setupBeforeClass() throws Exception {

    conf = UTIL.getConfiguration();

    conf.setClass("hbase.util.ip.to.rack.determiner", MockMapping.class, DNSToSwitchMapping.class);
    conf.setFloat("hbase.master.balancer.stochastic.maxMovePercent", 0.75f);
    conf.setFloat("hbase.regions.slop", 0.0f);
    conf.set(CoprocessorHost.REGIONSERVER_COPROCESSOR_CONF_KEY, JMXListener.class.getName());
    Random rand = new Random();
    for (int i = 0; i < 10; i++) {
      do {
        int sign = i % 2 == 0 ? 1 : -1;
        connectorPort += sign * rand.nextInt(100);
      } while (!HBaseTestingUtility.available(connectorPort));
      try {
        conf.setInt("regionserver.rmi.registry.port", connectorPort);

        UTIL.startMiniCluster();
        break;
      } catch (Exception e) {
        LOG.debug("Encountered exception when starting cluster. Trying port " + connectorPort, e);
        try {
          // this is to avoid "IllegalStateException: A mini-cluster is already running"
          UTIL.shutdownMiniCluster();
        } catch (Exception ex) {
          LOG.debug("Encountered exception shutting down cluster", ex);
        }
      }
    }
  }

  @AfterClass
  public static void tearDownAfterClass() throws Exception {
    UTIL.shutdownMiniCluster();
  }

  /**
   * In Ensemble mode, there should be only one ensemble table
   */
  @Test (timeout=60000)
  public void testJmxMetrics_EnsembleMode() throws Exception {
    loadBalancer = new StochasticLoadBalancer();

    conf.setBoolean(HConstants.HBASE_MASTER_LOADBALANCE_BYTABLE, false);
    loadBalancer.setConf(conf);

    TableName tableName = TableName.valueOf(HConstants.ENSEMBLE_TABLE_NAME);
    Map<ServerName, List<HRegionInfo>> clusterState = mockClusterServers(mockCluster_ensemble);
    loadBalancer.balanceCluster(tableName, clusterState);

    String[] tableNames = new String[] { tableName.getNameAsString() };
    String[] functionNames = loadBalancer.getCostFunctionNames();
    Set<String> jmxMetrics = readJmxMetricsWithRetry();
    Set<String> expectedMetrics = getExpectedJmxMetrics(tableNames, functionNames);

    // printMetrics(jmxMetrics, "existing metrics in ensemble mode");
    // printMetrics(expectedMetrics, "expected metrics in ensemble mode");

    // assert that every expected is in the JMX
    for (String expected : expectedMetrics) {
      assertTrue("Metric " + expected + " can not be found in JMX in ensemble mode.",
        jmxMetrics.contains(expected));
    }
  }

  /**
   * In per-table mode, each table has a set of metrics
   */
  @Test (timeout=60000)
  public void testJmxMetrics_PerTableMode() throws Exception {
    loadBalancer = new StochasticLoadBalancer();

    conf.setBoolean(HConstants.HBASE_MASTER_LOADBALANCE_BYTABLE, true);
    loadBalancer.setConf(conf);

    // NOTE the size is normally set in setClusterStatus, for test purpose, we set it manually
    // Tables: hbase:namespace, table1, table2
    // Functions: costFunctions, overall
    String[] functionNames = loadBalancer.getCostFunctionNames();
    loadBalancer.updateMetricsSize(3 * (functionNames.length + 1));

    // table 1
    TableName tableName = TableName.valueOf(TABLE_NAME_1);
    Map<ServerName, List<HRegionInfo>> clusterState = mockClusterServers(mockCluster_pertable_1);
    loadBalancer.balanceCluster(tableName, clusterState);

    // table 2
    tableName = TableName.valueOf(TABLE_NAME_2);
    clusterState = mockClusterServers(mockCluster_pertable_2);
    loadBalancer.balanceCluster(tableName, clusterState);

    // table hbase:namespace
    tableName = TableName.valueOf(TABLE_NAME_NAMESPACE);
    clusterState = mockClusterServers(mockCluster_pertable_namespace);
    loadBalancer.balanceCluster(tableName, clusterState);

    String[] tableNames = new String[] { TABLE_NAME_1, TABLE_NAME_2, TABLE_NAME_NAMESPACE };
    Set<String> jmxMetrics = readJmxMetricsWithRetry();
    Set<String> expectedMetrics = getExpectedJmxMetrics(tableNames, functionNames);

    // printMetrics(jmxMetrics, "existing metrics in per-table mode");
    // printMetrics(expectedMetrics, "expected metrics in per-table mode");

    // assert that every expected is in the JMX
    for (String expected : expectedMetrics) {
      assertTrue("Metric " + expected + " can not be found in JMX in per-table mode.",
        jmxMetrics.contains(expected));
    }
  }

  private Set<String> readJmxMetricsWithRetry() throws IOException {
    final int count = 0;
    for (int i = 0; i < 10; i++) {
      Set<String> metrics = readJmxMetrics();
      if (metrics != null) return metrics;
      LOG.warn("Failed to get jmxmetrics... sleeping, retrying; " + i + " of " + count + " times");
      Threads.sleep(1000);
    }
    return null;
  }

  /**
   * Read the attributes from Hadoop->HBase->Master->Balancer in JMX
   * @throws IOException 
   */
  private Set<String> readJmxMetrics() throws IOException {
    JMXConnector connector = null;
    ObjectName target = null;
    MBeanServerConnection mb = null;
    try {
      connector =
          JMXConnectorFactory.connect(JMXListener.buildJMXServiceURL(connectorPort, connectorPort));
      mb = connector.getMBeanServerConnection();

      Hashtable<String, String> pairs = new Hashtable<>();
      pairs.put("service", "HBase");
      pairs.put("name", "Master");
      pairs.put("sub", "Balancer");
      target = new ObjectName("Hadoop", pairs);
      MBeanInfo beanInfo = mb.getMBeanInfo(target);

      Set<String> existingAttrs = new HashSet<String>();
      for (MBeanAttributeInfo attrInfo : beanInfo.getAttributes()) {
        existingAttrs.add(attrInfo.getName());
      }
      return existingAttrs;
    } catch (Exception e) {
      LOG.warn("Failed to get bean!!! " + target, e);
      if (mb != null) {
        Set<ObjectInstance> instances = mb.queryMBeans(null, null);
        Iterator<ObjectInstance> iterator = instances.iterator();
        System.out.println("MBean Found:");
        while (iterator.hasNext()) {
          ObjectInstance instance = iterator.next();
          System.out.println("Class Name: " + instance.getClassName());
          System.out.println("Object Name: " + instance.getObjectName());
        }
      }
    } finally {
      if (connector != null) {
        try {
          connector.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    return null;
  }

  /**
   * Given the tables and functions, return metrics names that should exist in JMX
   */
  private Set<String> getExpectedJmxMetrics(String[] tableNames, String[] functionNames) {
    Set<String> ret = new HashSet<String>();

    for (String tableName : tableNames) {
      ret.add(StochasticLoadBalancer.composeAttributeName(tableName, "Overall"));
      for (String functionName : functionNames) {
        String metricsName = StochasticLoadBalancer.composeAttributeName(tableName, functionName);
        ret.add(metricsName);
      }
    }

    return ret;
  }

  private static void printMetrics(Set<String> metrics, String info) {
    if (null != info) LOG.info("++++ ------ " + info + " ------");

    LOG.info("++++ metrics count = " + metrics.size());
    for (String str : metrics) {
      LOG.info(" ++++ " + str);
    }
  }
}
