/**
 *
 * 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.master.normalizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.MiniHBaseCluster;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.master.HMaster;
import org.apache.hadoop.hbase.master.TableNamespaceManager;
import org.apache.hadoop.hbase.master.normalizer.NormalizationPlan.PlanType;
import org.apache.hadoop.hbase.namespace.TestNamespaceAuditor;
import org.apache.hadoop.hbase.quotas.QuotaUtil;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.Region;
import org.apache.hadoop.hbase.testclassification.MasterTests;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.test.LoadTestKVGenerator;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.TestName;

import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import static org.junit.Assert.assertEquals;

/**
 * Testing {@link SimpleRegionNormalizer} on minicluster.
 */
@Category({MasterTests.class, MediumTests.class})
public class TestSimpleRegionNormalizerOnCluster {
  private static final Log LOG = LogFactory.getLog(TestSimpleRegionNormalizerOnCluster.class);
  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
  private static final byte[] FAMILYNAME = Bytes.toBytes("fam");
  private static Admin admin;

  @Rule
  public TestName name = new TestName();

  @BeforeClass
  public static void beforeAllTests() throws Exception {
    // we will retry operations when PleaseHoldException is thrown
    TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 3);
    TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);

    // Start a cluster of two regionservers.
    TEST_UTIL.startMiniCluster(1);
    TestNamespaceAuditor.waitForQuotaEnabled(TEST_UTIL);
    admin = TEST_UTIL.getAdmin();
  }

  @AfterClass
  public static void afterAllTests() throws Exception {
    TEST_UTIL.shutdownMiniCluster();
  }

  @Test(timeout = 90000)
  @SuppressWarnings("deprecation")
  public void testRegionNormalizationSplitOnCluster() throws Exception {
    testRegionNormalizationSplitOnCluster(false);
    testRegionNormalizationSplitOnCluster(true);
  }

  void testRegionNormalizationSplitOnCluster(boolean limitedByQuota) throws Exception {
    TableName TABLENAME;
    if (limitedByQuota) {
      String nsp = "np2";
      NamespaceDescriptor nspDesc =
          NamespaceDescriptor.create(nsp)
          .addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")
          .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();
      admin.createNamespace(nspDesc);
      TABLENAME = TableName.valueOf(nsp +
        TableName.NAMESPACE_DELIM + name.getMethodName());
    } else {
      TABLENAME = TableName.valueOf(name.getMethodName());
    }
    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
    HMaster m = cluster.getMaster();

    try (Table ht = TEST_UTIL.createMultiRegionTable(TABLENAME, FAMILYNAME, 5)) {
      // Need to get sorted list of regions here
      List<HRegion> generatedRegions = TEST_UTIL.getHBaseCluster().getRegions(TABLENAME);
      Collections.sort(generatedRegions, new Comparator<HRegion>() {
        @Override
        public int compare(HRegion o1, HRegion o2) {
          return o1.getRegionInfo().compareTo(o2.getRegionInfo());
        }
      });

      HRegion region = generatedRegions.get(0);
      generateTestData(region, 1);
      region.flush(true);

      region = generatedRegions.get(1);
      generateTestData(region, 1);
      region.flush(true);

      region = generatedRegions.get(2);
      generateTestData(region, 2);
      region.flush(true);

      region = generatedRegions.get(3);
      generateTestData(region, 2);
      region.flush(true);

      region = generatedRegions.get(4);
      generateTestData(region, 5);
      region.flush(true);
    }

    HTableDescriptor htd = admin.getTableDescriptor(TABLENAME);
    htd.setNormalizationEnabled(true);
    admin.modifyTable(TABLENAME, htd);

    admin.flush(TABLENAME);

    assertEquals(5, MetaTableAccessor.getRegionCount(TEST_UTIL.getConnection(), TABLENAME));

    // Now trigger a split and stop when the split is in progress
    Thread.sleep(5000); // to let region load to update
    m.normalizeRegions();
    if (limitedByQuota) {
      long skippedSplitcnt = 0;
      do {
        skippedSplitcnt = m.getRegionNormalizer().getSkippedCount(PlanType.SPLIT);
        Thread.sleep(100);
      } while (skippedSplitcnt == 0L);
      assert(skippedSplitcnt > 0);
    } else {
      while (true) {
        List<HRegion> regions = TEST_UTIL.getHBaseCluster().getRegions(TABLENAME);
        int cnt = 0;
        for (HRegion region : regions) {
          String regionName = region.getRegionInfo().getRegionNameAsString();
          if (regionName.startsWith("testRegionNormalizationSplitOnCluster,zzzzz")) {
            cnt++;
          }
        }
        if (cnt >= 2) {
          break;
        }
      }
    }

    admin.disableTable(TABLENAME);
    admin.deleteTable(TABLENAME);
  }

  @Test(timeout = 60000)
  @SuppressWarnings("deprecation")
  public void testRegionNormalizationMergeOnCluster() throws Exception {
    final TableName tableName = TableName.valueOf(name.getMethodName());
    MiniHBaseCluster cluster = TEST_UTIL.getHBaseCluster();
    HMaster m = cluster.getMaster();

    // create 5 regions with sizes to trigger merge of small regions
    try (Table ht = TEST_UTIL.createMultiRegionTable(tableName, FAMILYNAME, 5)) {
      // Need to get sorted list of regions here
      List<HRegion> generatedRegions = TEST_UTIL.getHBaseCluster().getRegions(tableName);
      Collections.sort(generatedRegions, new Comparator<HRegion>() {
        @Override
        public int compare(HRegion o1, HRegion o2) {
          return o1.getRegionInfo().compareTo(o2.getRegionInfo());
        }
      });

      HRegion region = generatedRegions.get(0);
      generateTestData(region, 1);
      region.flush(true);

      region = generatedRegions.get(1);
      generateTestData(region, 1);
      region.flush(true);

      region = generatedRegions.get(2);
      generateTestData(region, 3);
      region.flush(true);

      region = generatedRegions.get(3);
      generateTestData(region, 3);
      region.flush(true);

      region = generatedRegions.get(4);
      generateTestData(region, 5);
      region.flush(true);
    }

    HTableDescriptor htd = admin.getTableDescriptor(tableName);
    htd.setNormalizationEnabled(true);
    admin.modifyTable(tableName, htd);

    admin.flush(tableName);

    assertEquals(5, MetaTableAccessor.getRegionCount(TEST_UTIL.getConnection(), tableName));

    // Now trigger a merge and stop when the merge is in progress
    Thread.sleep(5000); // to let region load to update
    m.normalizeRegions();

    while (MetaTableAccessor.getRegionCount(TEST_UTIL.getConnection(), tableName) > 4) {
      LOG.info("Waiting for normalization merge to complete");
      Thread.sleep(100);
    }

    assertEquals(4, MetaTableAccessor.getRegionCount(TEST_UTIL.getConnection(), tableName));

    admin.disableTable(tableName);
    admin.deleteTable(tableName);
  }

  private void generateTestData(Region region, int numRows) throws IOException {
    // generating 1Mb values
    LoadTestKVGenerator dataGenerator = new LoadTestKVGenerator(1024 * 1024, 1024 * 1024);
    for (int i = 0; i < numRows; ++i) {
      byte[] key = Bytes.add(region.getRegionInfo().getStartKey(), Bytes.toBytes(i));
      for (int j = 0; j < 1; ++j) {
        Put put = new Put(key);
        byte[] col = Bytes.toBytes(String.valueOf(j));
        byte[] value = dataGenerator.generateRandomSizeValue(key, col);
        put.addColumn(FAMILYNAME, col, value);
        region.put(put);
      }
    }
  }
}
