Package org.apache.hadoop.hbase.index.coprocessor.regionserver

Source Code of org.apache.hadoop.hbase.index.coprocessor.regionserver.TestIndexRegionObserverForScan

/**
* Copyright 2011 The Apache Software Foundation
*
* 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.index.coprocessor.regionserver;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.LargeTests;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.UnknownRegionException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
import org.apache.hadoop.hbase.filter.BinaryComparator;
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.FilterList;
import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
import org.apache.hadoop.hbase.filter.RowFilter;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.index.ColumnQualifier.ValueType;
import org.apache.hadoop.hbase.index.Constants;
import org.apache.hadoop.hbase.index.IndexSpecification;
import org.apache.hadoop.hbase.index.IndexedHTableDescriptor;
import org.apache.hadoop.hbase.index.coprocessor.master.IndexMasterObserver;
import org.apache.hadoop.hbase.index.coprocessor.wal.IndexWALObserver;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
import org.apache.hadoop.hbase.zookeeper.ZKAssign;
import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
import org.apache.zookeeper.KeeperException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

@Category(LargeTests.class)
public class TestIndexRegionObserverForScan {

  private static HBaseTestingUtility UTIL = new HBaseTestingUtility();

  @BeforeClass
  public static void setupBeforeClass() throws Exception {
    Configuration conf = UTIL.getConfiguration();
    conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, IndexMasterObserver.class.getName());
    conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, IndexRegionObserver.class.getName());
    conf.set(CoprocessorHost.WAL_COPROCESSOR_CONF_KEY, IndexWALObserver.class.getName());
    conf.setBoolean("hbase.use.secondary.index", true);
    UTIL.startMiniCluster(1);
  }

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

  @Before
  public void setUp() throws Exception {
    IndexRegionObserver.setIndexedFlowUsed(false);
    IndexRegionObserver.setSeekpointAdded(false);
    IndexRegionObserver.setSeekPoints(null);
    IndexRegionObserver.setIsTestingEnabled(true);
  }

  @After
  public void tearDown() throws Exception {
    IndexRegionObserver.setIsTestingEnabled(false);
  }

  @Test(timeout = 180000)
  public void testScanIndexedColumnWithOnePutShouldRetreiveOneRowSuccessfully() throws IOException,
      KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    String userTableName = "testPutOnIndexedScanColumnWithOnePut";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexf");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);

    // test put with the indexed column
    Put p = new Put("row1".getBytes());
    p.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p);
    int i = countNumberOfRowsWithFilter(userTableName, "Val", true, false, 0);
    Assert.assertEquals("Should match for 1 row successfully ", 1, i);
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());

  }

  @Test(timeout = 180000)
  public void testScanIndexedColumnWithOnePutAndSplitKeyatBorderShouldRetreiveOneRowSuccessfully()
      throws IOException, KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    String userTableName = "testScanOnIndexedScanSplitColumnWithOnePut";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexf");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    byte[][] split =
        new byte[][] { "row1".getBytes(), "row21".getBytes(), "row41".getBytes(),
            "row61".getBytes(), "row81".getBytes(), "row101".getBytes(), "row121".getBytes(),
            "row141".getBytes(), };

    // create table with splits this will create 9 regions
    admin.createTable(ihtd, split);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);

    // test put with the indexed column
    Put p = new Put("row1".getBytes());
    p.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p);

    Put p1 = new Put("row01".getBytes());
    p1.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p1);

    Put p2 = new Put("row010".getBytes());
    p2.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p2);

    Put p3 = new Put("row001".getBytes());
    p3.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p3);

    validateCountOfMainTableIndIndexedTable(conf, userTableName, table);

    int i = countNumberOfRowsWithFilter(userTableName, "Val", true, false, 0);
    Assert.assertEquals("Should match for 1 row successfully ", 4, i);
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());

  }

  @Test(timeout = 180000)
  public
      void
      testScanIndexedColumnWithOnePutAndSplitKeyAndStartKeyRegionEmptyShouldRetreiveOneRowSuccessfully()
          throws IOException, KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    String userTableName = "testScanOnIndexedSplitStRegExmptyColumnWithOnePut";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexf");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);

    byte[][] split = new byte[][] { "A".getBytes(), "B".getBytes(), "C".getBytes() };

    // create table with splits this will create 9 regions
    admin.createTable(ihtd, split);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);
    Put p = new Put("00row1".getBytes());
    p.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p);

    Put p1 = new Put("0row1".getBytes());
    p1.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p1);

    Put p2 = new Put("000row1".getBytes());
    p2.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p2);

    Put p3 = new Put("0000row1".getBytes());
    p3.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p3);

    // Check for verification of number of rows in main table and user table
    validateCountOfMainTableIndIndexedTable(conf, userTableName, table);

    // test put with the indexed column

    int i = countNumberOfRowsWithFilter(userTableName, "Val", true, false, 0);
    Assert.assertEquals("Should match for 1 row successfully ", 4, i);
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());

  }

  @Test(timeout = 180000)
  public void
      testScanIndexedColumnWithOnePutAndSplitKeyHavingSpaceShouldRetreiveOneRowSuccessfully()
          throws IOException, KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    String userTableName = "testScanOnIndexedSplitSpacedColumnWithOnePut";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexf");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);

    byte[][] split =
        new byte[][] { " row1".getBytes(), "row21".getBytes(), "row41".getBytes(),
            "row61".getBytes(), "row81".getBytes(), "row101 ".getBytes(), "row121".getBytes(),
            "row141".getBytes(), };

    // create table with splits this will create 9 regions
    admin.createTable(ihtd, split);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);

    // test put with the indexed column
    Put p = new Put("row1".getBytes());
    p.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p);
    validateCountOfMainTableIndIndexedTable(conf, userTableName, table);
    int i = countNumberOfRowsWithFilter(userTableName, "Val", true, false, 0);
    Assert.assertEquals("Should match for 1 row successfully ", 1, i);
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());

  }

  @Test(timeout = 180000)
  public void testScanIndexedColumnShouldNotRetreiveRowIfThereIsNoMatch() throws IOException,
      KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    String userTableName = "testPutOnIndexedScanColumnWith2Puts";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexq");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);

    // test put with the indexed column
    Put p = new Put("row1".getBytes());
    p.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p);

    Put p1 = new Put("row2".getBytes());
    p1.add("col".getBytes(), "ql".getBytes(), "Val1".getBytes());
    table.put(p1);
    int i = countNumberOfRowsWithFilter(userTableName, "unmatch", true, false, 0);
    Assert.assertEquals("Should not match any rows ", 0, i);
    Assert.assertFalse("Seek points should not be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testScanIndexedColumnWith5PutsAnd3EqualPutValuesShouldRetreive3RowsSuccessfully()
      throws IOException, KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();

    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    String userTableName = "test5PutsWithIndexedScanColumn";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexe");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);
    Put p1 = new Put("row1".getBytes());
    p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p1);

    Put p4 = new Put("row3".getBytes());
    p4.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p4);

    Put p5 = new Put("row2".getBytes());
    p5.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p5);

    Put p2 = new Put("row4".getBytes());
    p2.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p2);

    Put p3 = new Put("row5".getBytes());
    p3.add("col".getBytes(), "ql".getBytes(), "dogs".getBytes());
    table.put(p3);

    int i = countNumberOfRowsWithFilter(userTableName, "cat", true, false, 0);

    Assert.assertEquals("Should match for exactly 3 rows ", 3, i);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testPerformanceOfScanOnIndexedColumnShouldBeMoreWith1LakhRowsIfFlushIsNotMade()
      throws Exception {

    long withIndex = doPerformanceTest(true, "tableWithIndexAndWithoutFlush", false);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    IndexRegionObserver.setSeekpointAdded(false);
    IndexRegionObserver.setIndexedFlowUsed(false);
    long withoutIndex = doPerformanceTest(false, "tableWithoutIndexAndWithoutFlush", false);
    Assert.assertTrue(
      "Without flush time taken for Indexed scan should be less than without index ",
      withIndex < withoutIndex);

    Assert.assertFalse("Seek points should not be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertFalse("Indexed table should not be used ",
      IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testShouldSuccessfullyReturn3RowsIfOnly3RowsMatchesIn1LakhRowsWithParallelPuts()
      throws Exception {
    String userTableName = "tableToCheck3Rows";
    doBulkParallelPuts(true, userTableName, false);
    int i = countNumberOfRowsWithFilter(userTableName, "cat", true, false, 0);
    Assert.assertEquals("Should match for exactly 3 rows in 1 lakh rows ", 3, i);
    Assert.assertTrue("Indexed table should  be used ", IndexRegionObserver.getSeekpointAdded());
  }

  @Test(timeout = 180000)
  public void testPerformanceOfScanOnIndexedColumnShouldBeMoreWith1LakhRowsIfFlushIsMade()
      throws Exception {
    long withIndex = doPerformanceTest(true, "tableWithIndexAndWithFlush", true);

    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    IndexRegionObserver.setSeekpointAdded(false);
    IndexRegionObserver.setIndexedFlowUsed(false);
    long withoutIndex = doPerformanceTest(false, "tableWithoutIndexAndWithFlush", true);
    Assert.assertTrue("With flush time taken for Indexed scan should be less than without index ",
      withIndex < withoutIndex);
    Assert.assertFalse("Seek points should not be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertFalse("Indexed table should not be used ",
      IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testParallelScansShouldRetreiveRowsCorrectlyForIndexedColumn() throws Exception {
    String userTableName = "testParallelScansOnIndexedColumn";
    doParallelScanPuts(userTableName);
    ParallelScanThread p1 = new ParallelScanThread(userTableName, "cat", false, 0);
    p1.start();

    ParallelScanThread p2 = new ParallelScanThread(userTableName, "dog", false, 0);
    p2.start();

    ParallelScanThread p3 = new ParallelScanThread(userTableName, "pup", false, 0);
    p3.start();

    // wait for scan to complete
    p1.join();
    p2.join();
    p3.join();
    Assert.assertEquals("Should match for exactly 700 cats ", 700, p1.count);
    Assert.assertEquals("Should match for exactly 500 dogs ", 500, p2.count);
    Assert.assertEquals("Should match for exactly 300 pups ", 300, p3.count);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testParallelScansWithCacheShouldRetreiveRowsCorrectlyForIndexedColumn()
      throws Exception {
    String userTableName = "testParallelScansWithCacheOnIndexedColumn";
    doParallelScanPuts(userTableName);
    // In parallel scan setting the cache
    ParallelScanThread p1 = new ParallelScanThread(userTableName, "cat", true, 200);
    p1.start();

    ParallelScanThread p2 = new ParallelScanThread(userTableName, "dog", true, 200);
    p2.start();

    ParallelScanThread p3 = new ParallelScanThread(userTableName, "pup", true, 200);
    p3.start();

    // wait for scan to complete
    p1.join();
    p2.join();
    p3.join();
    Assert.assertEquals("Should match for exactly 700 cats ", 700, p1.count);
    Assert.assertEquals("Should match for exactly 500 dogs ", 500, p2.count);
    Assert.assertEquals("Should match for exactly 300 pups ", 300, p3.count);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testScanShouldBeSuccessfulEvenIfExceptionIsThrownFromPostScannerOpen()
      throws Exception {

    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    String userTableName = "testgenerateExceptionInPostScannerOpen";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexf");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);

    // test put with the indexed column
    Put p = new Put("row1".getBytes());
    p.add("col".getBytes(), "ql".getBytes(), "Val".getBytes());
    table.put(p);
    Scan s = new Scan();
    Filter filter = new ExceptionFilter();
    s.setFilter(filter);
    int i = 0;
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }

    Assert.assertEquals("Should match for 1 row successfully ", 1, i);
    Assert.assertFalse("Seek points should not be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertFalse("Indexed table should not be used ",
      IndexRegionObserver.getIndexedFlowUsed());

  }

  private String doParallelScanPuts(String userTableName) throws IOException,
      ZooKeeperConnectionException, KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);

    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndex");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);
    List<Put> puts = new ArrayList<Put>();

    for (int i = 1; i <= 500; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    for (int i = 501; i <= 1000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    for (int i = 1001; i <= 1300; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "pup".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    for (int i = 1301; i <= 1500; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);
    return userTableName;
  }

  @Test(timeout = 180000)
  public void testScanShouldNotRetreiveRowsIfRowsArePresentOnlyInIndexedTableAndNotInMainTable()
      throws Exception {

    HBaseAdmin admin = UTIL.getHBaseAdmin();
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    final String userTableName = "testScanOnIndexedColumnForFalsePositve";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndex");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);

    HTable table = new HTable(conf, userTableName);

    List<Put> puts = new ArrayList<Put>();

    for (int i = 1; i <= 100; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 101; i <= 200; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 201; i <= 300; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "pup".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    // Doing one extra put explicilty into indexed table
    HTable indexTable = new HTable(conf, userTableName + Constants.INDEX_TABLE_SUFFIX);

    List<HRegionInfo> regionsOfTable =
        UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
            .getRegionsOfTable((userTableName + Constants.INDEX_TABLE_SUFFIX).getBytes());

    byte[] startRow = generateStartKey(regionsOfTable);

    Put p1 = new Put(startRow);
    p1.add("d".getBytes(), "ql".getBytes(), "idxCat".getBytes());
    indexTable.put(p1);

    int i = countNumberOfRowsWithFilter(userTableName, "idxCat", true, false, 0);
    Assert.assertEquals("Should not match any rows in main table ", 0, i);
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertFalse("Seek points should not be added ", IndexRegionObserver.getSeekpointAdded());

  }

  @Test(timeout = 180000)
  public void testScanWithPutsAndCacheSetShouldRetreiveMatchingRows() throws Exception {
    HBaseAdmin admin = UTIL.getHBaseAdmin();

    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    String userTableName = "testcachedColumn";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndexe");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);
    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);
    int i = singleIndexPutAndCache(conf, userTableName);
    Assert.assertEquals("Should match for exactly 5 rows ", 5, i);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertEquals("Remaining rows in cache should be 2  ", 2, IndexRegionObserver
        .getSeekpoints().size());

  }

  @Test(timeout = 180000)
  public void testScanMultipleIdxWithSameColFamilyAndDifferentQualifierShouldBeSuccessful()
      throws Exception {

    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    String userTableName = "testScanWithMultIndexedSameColFamilyColumn";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);

    HColumnDescriptor hcd1 = new HColumnDescriptor("col1");
    ihtd.addFamily(hcd1);
    IndexSpecification idx1 = new IndexSpecification("ScanMulIndex");
    idx1.addIndexColumn(hcd1, "ql", ValueType.String, 10);
    idx1.addIndexColumn(hcd1, "q2", ValueType.String, 10);
    ihtd.addIndex(idx1);

    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);
    HTable table = new HTable(conf, userTableName);

    // test put with the indexed column
    Put p1 = new Put("row1".getBytes());
    p1.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p1.add("col1".getBytes(), "q2".getBytes(), "dog".getBytes());
    table.put(p1);

    Put p2 = new Put("row2".getBytes());
    p2.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p2.add("col1".getBytes(), "q2".getBytes(), "cat".getBytes());
    table.put(p2);

    Put p3 = new Put("row3".getBytes());
    p3.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p3.add("col1".getBytes(), "q2".getBytes(), "dog".getBytes());
    table.put(p3);

    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q2
    SingleColumnValueFilter filter1 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    filter1.setFilterIfMissing(true);
    SingleColumnValueFilter filter2 =
        new SingleColumnValueFilter("col1".getBytes(), "q2".getBytes(), CompareOp.EQUAL,
            "dog".getBytes());
    filter2.setFilterIfMissing(true);
    filterList.addFilter(filter1);

    filterList.addFilter(filter2);
    s.setFilter(filterList);

    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }

    Assert.assertEquals("Should match for 2 rows in multiple index successfully ", 2, i);
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());

  }

  @Test(timeout = 180000)
  public void testScanMultipleIdxWithDifferentColFamilyShouldBeSuccessful() throws Exception {
    Configuration conf = UTIL.getConfiguration();
    String userTableName = "testScanWithMultIndexedDiffColFamilyColumn";
    putMulIndex(userTableName);
    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q1
    SingleColumnValueFilter filter1 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    filter1.setFilterIfMissing(true);
    SingleColumnValueFilter filter2 =
        new SingleColumnValueFilter("col2".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "dog".getBytes());
    filter2.setFilterIfMissing(true);
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    s.setFilter(filterList);
    HTable table = new HTable(conf, userTableName);
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 5 rows in multiple index with diff column family successfully ", 5, i);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testScanMultipleIdxWithDifferentColFamilyAndCacheShouldBeSuccessful()
      throws Exception {
    Configuration conf = UTIL.getConfiguration();
    String userTableName = "testScanWithMultIndexedCacheDiffColFamilyColumn";
    putMulIndex(userTableName);
    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q1
    SingleColumnValueFilter filter1 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    filter1.setFilterIfMissing(true);
    SingleColumnValueFilter filter2 =
        new SingleColumnValueFilter("col2".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "dog".getBytes());
    filter2.setFilterIfMissing(true);
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    s.setCaching(4);
    s.setFilter(filterList);
    HTable table = new HTable(conf, userTableName);
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 5 rows in multiple index with diff column family successfully ", 5, i);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
    Assert.assertEquals("Remaining rows in cache should be 1  ", 1, IndexRegionObserver
        .getSeekpoints().size());
  }

  @Test(timeout = 180000)
  public void
      testScanMultipleIdxWithDifferentFiltersShouldBeSuccessfulAndShouldNotGoWithIndexedFlow()
          throws Exception {

    Configuration conf = UTIL.getConfiguration();
    String userTableName = "testScanWithMultIndexedDiffFilters";
    putMulIndex(userTableName);
    HTable table = new HTable(conf, userTableName);
    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q1
    Filter filter1 =
        new RowFilter(CompareOp.LESS_OR_EQUAL, new BinaryComparator("row5".getBytes()));
    Filter filter2 = new FirstKeyOnlyFilter();
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    s.setFilter(filterList);
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 5 rows in multiple index with diff column family successfully ", 5, i);
    Assert.assertFalse("Seek points should not be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertFalse("Indexed table should not be used ",
      IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public void testScanWithIndexOn2ColumnsAndFiltersOn2ColumnsInReverseWayShouldBeSuccessful()
      throws Exception {
    Configuration conf = UTIL.getConfiguration();
    String userTableName = "testScan2Indexed2ReversedFilters";
    putMulIndex(userTableName);
    HTable table = new HTable(conf, userTableName);
    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q1
    SingleColumnValueFilter filter1 =
        new SingleColumnValueFilter("col2".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "dog".getBytes());
    filter1.setFilterIfMissing(true);
    SingleColumnValueFilter filter2 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    filter2.setFilterIfMissing(true);
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    s.setFilter(filterList);

    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 5 rows in multiple index with diff column family successfully ", 5, i);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  @Test(timeout = 180000)
  public
      void
      testScanMultipleIdxWithDifferentColumnsInFiltersShouldBeSuccessfulAndShouldNotGoWithIndexedFlow()
          throws Exception {

    Configuration conf = UTIL.getConfiguration();
    String userTableName = "test11ScanWithMultIndexedDiff11Filters";
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);

    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);

    HColumnDescriptor hcd1 = new HColumnDescriptor("col1");
    HColumnDescriptor hcd2 = new HColumnDescriptor("col2");
    HColumnDescriptor hcd3 = new HColumnDescriptor("col3");
    ihtd.addFamily(hcd1);
    ihtd.addFamily(hcd2);
    ihtd.addFamily(hcd3);
    IndexSpecification idx1 = new IndexSpecification("ScanMulIndex");
    idx1.addIndexColumn(hcd1, "ql", ValueType.String, 10);
    idx1.addIndexColumn(hcd2, "ql", ValueType.String, 10);
    ihtd.addIndex(idx1);

    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);
    HTable table = new HTable(conf, userTableName);

    // test put with the multiple indexed column in diffrent column families
    Put p1 = new Put("row1".getBytes());
    p1.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p1.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p1);

    Put p2 = new Put("row2".getBytes());
    p2.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p2.add("col2".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p2);

    Put p3 = new Put("row3".getBytes());
    p3.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p3.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p3);

    Put p4 = new Put("row4".getBytes());
    p4.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p4.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p4);

    Put p5 = new Put("row5".getBytes());
    p5.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p5.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p5);

    Put p6 = new Put("row6".getBytes());
    p6.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p6.add("col2".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p6);

    Put p7 = new Put("row7".getBytes());
    p7.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p7.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p7);

    Put p9 = new Put("row8".getBytes());
    p9.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p9.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p9);

    Put p8 = new Put("row9".getBytes());
    p8.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p8.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p8);
    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q1
    SingleColumnValueFilter filter1 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    filter1.setFilterIfMissing(true);
    SingleColumnValueFilter filter2 =
        new SingleColumnValueFilter("col3".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "dog".getBytes());
    filter2.setFilterIfMissing(true);
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    s.setFilter(filterList);
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 1 rows in multiple index with diff column family successfully ", 1, i);
    Assert.assertTrue("Seek points should  be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());

    // Different values in column family should not retreive the rows.. Below
    // ensures the same
    Scan s1 = new Scan();
    FilterList filterList1 = new FilterList();
    // check for combination of cat in q1 and dog in q1
    SingleColumnValueFilter filter11 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    filter11.setFilterIfMissing(true);
    SingleColumnValueFilter filter12 =
        new SingleColumnValueFilter("col3".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "dog1".getBytes());
    filter12.setFilterIfMissing(true);
    filterList1.addFilter(filter11);
    filterList1.addFilter(filter12);
    s1.setFilter(filterList1);
    i = 0;
    ResultScanner scanner1 = table.getScanner(s1);
    for (Result result : scanner1) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 0 rows in multiple index with diff column family successfully ", 0, i);
    Assert.assertTrue("Seek points should  be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());

  }

  @Test(timeout = 180000)
  public void testScanWith4IdxAnd2ColumnsInFiltersShouldBeSuccessful() throws Exception {
    HTable table = put4ColumnIndex();
    int i = 0;
    Scan s = new Scan();
    FilterList filterList = new FilterList();
    // check for combination of cat in q1 and dog in q1
    Filter filter1 =
        new SingleColumnValueFilter("col1".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());
    Filter filter2 =
        new SingleColumnValueFilter("col2".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "dog".getBytes());
    filterList.addFilter(filter1);
    filterList.addFilter(filter2);
    s.setFilter(filterList);

    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    Assert.assertEquals(
      "Should match for 5 rows in multiple index with diff column family successfully ", 5, i);
    Assert.assertTrue("Seek points should be added ", IndexRegionObserver.getSeekpointAdded());
    Assert.assertTrue("Indexed table should be used ", IndexRegionObserver.getIndexedFlowUsed());
  }

  // @Test(timeout = 180000)
  public void testShouldBESuccessfulEvenOfSeparatorIsNegative() throws Exception {

    UTIL.getMiniHBaseCluster().startRegionServer();
    // UTIL.getMiniHBaseCluster().startRegionServer();
    List<RegionServerThread> liveRegionServerThreads =
        UTIL.getMiniHBaseCluster().getLiveRegionServerThreads();
    Assert.assertEquals("2 Region Servers should be started ", 2, liveRegionServerThreads.size());

    HBaseAdmin admin = UTIL.getHBaseAdmin();

    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    final String userTableName = "testCollocationExplicitScansOnIndexedColumn";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndex");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);

    admin.createTable(ihtd);

    String anotherTable = "newTable";
    HTableDescriptor ihtd1 = new HTableDescriptor(anotherTable);
    HColumnDescriptor hcd1 = new HColumnDescriptor("col1");
    ihtd1.addFamily(hcd1);

    admin.createTable(ihtd1);
    ZKAssign.blockUntilNoRIT(zkw);
    HTable table = new HTable(conf, userTableName);

    List<HRegionInfo> regionsOfTable =
        UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
            .getRegionsOfTable(userTableName.getBytes());
    List<HRegionInfo> regionsOfIndexTable =
        UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
            .getRegionsOfTable((userTableName + "_idx").getBytes());

    List<HRegionInfo> rs1 = new ArrayList<HRegionInfo>();
    List<HRegionInfo> rs2 = new ArrayList<HRegionInfo>();

    rs1.add(regionsOfIndexTable.get(0));
    rs1.add(regionsOfTable.get(0));

    HRegionServer regionServer1 = UTIL.getMiniHBaseCluster().getRegionServer(0);
    HRegionServer regionServer2 = UTIL.getMiniHBaseCluster().getRegionServer(1);

    for (HRegionInfo hRegionInfo : rs1) {
      admin.move(hRegionInfo.getEncodedNameAsBytes(),
        Bytes.toBytes(regionServer2.getServerName().getServerName()));
    }

    // for (HRegionInfo hRegionInfo : rs2) {
    // admin.move(hRegionInfo.getEncodedNameAsBytes(), Bytes
    // .toBytes(regionServer2.getServerName().getServerName()));
    // }

    UTIL.getMiniHBaseCluster().getMaster().balanceSwitch(false);
    HTable table1 = new HTable(conf, anotherTable);
    List<Put> puts = new ArrayList<Put>();

    for (int i = 1; i <= 10; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);
    puts = new ArrayList<Put>();

    for (int i = 11; i <= 20; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
      puts.add(p1);
    }
    table1.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 21; i <= 30; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "pup".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    List<HRegionInfo> regionsOfIndexTable1 =
        UTIL.getMiniHBaseCluster().getMaster().getAssignmentManager()
            .getRegionsOfTable((userTableName + "_idx").getBytes());

    for (HRegionInfo hRegionInfo : regionsOfIndexTable1) {

      int originServerNum = UTIL.getMiniHBaseCluster().getServerWith(hRegionInfo.getRegionName());
      int targetServerNum = 2 - 1 - originServerNum;
      HRegionServer targetServer = UTIL.getMiniHBaseCluster().getRegionServer(targetServerNum);
      admin.move(hRegionInfo.getEncodedNameAsBytes(),
        Bytes.toBytes(targetServer.getServerName().getServerName()));

    }

    // Scan should be successful
    int i = countNumberOfRowsWithFilter(userTableName, "cat", true, false, 0);
    Assert.assertEquals("Should match for exactly 10 rows ", 10, i);

  }

  @Test(timeout = 180000)
  public void testScanShouldBeSuccessfulEvenIfUserRegionAndIndexRegionAreNotCollocated()
      throws Exception {

    // starting 3 RS
    UTIL.getMiniHBaseCluster().startRegionServer();
    UTIL.getMiniHBaseCluster().startRegionServer();
    List<RegionServerThread> liveRegionServerThreads =
        UTIL.getMiniHBaseCluster().getLiveRegionServerThreads();
    Assert.assertEquals("3 Region Servers should be started ", 3, liveRegionServerThreads.size());

    HBaseAdmin admin = UTIL.getHBaseAdmin();

    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    Configuration conf = UTIL.getConfiguration();
    final String userTableName =
        "testScanShouldBeSuccessfulEvenIfUserRegionAndIndexRegionAreNotCollocated";
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd = new HColumnDescriptor("col");
    IndexSpecification iSpec = new IndexSpecification("ScanIndex");
    iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
    ihtd.addFamily(hcd);
    ihtd.addIndex(iSpec);

    byte[][] split =
        new byte[][] { "row1".getBytes(), "row21".getBytes(), "row41".getBytes(),
            "row61".getBytes(), "row81".getBytes(), "row101".getBytes(), "row121".getBytes(),
            "row141".getBytes(), };

    // create table with splits this will create 9 regions
    admin.createTable(ihtd, split);
    ZKAssign.blockUntilNoRIT(zkw);
    HTable table = new HTable(conf, userTableName);

    UTIL.getMiniHBaseCluster().getMaster().balanceSwitch(false);

    // Now collocation between the RS's is done so put the rows
    doPuts(conf, userTableName);

    // Now move the 3 rows that has the string "cat" to different RS

    collocateRowToDifferentRS(admin, table, "row1001");
    collocateRowToDifferentRS(admin, table, "row11004");
    collocateRowToDifferentRS(admin, table, "row11007");

    // Scan should be successful
    int i = countNumberOfRowsWithFilter(userTableName, "cat", true, false, 0);
    Assert.assertEquals("Should match for exactly 6000 rows ", 6000, i);

    UTIL.getMiniHBaseCluster().abortRegionServer(1);
    UTIL.getMiniHBaseCluster().abortRegionServer(2);
    UTIL.getMiniHBaseCluster().abortRegionServer(0);
  }

  private void putMulIndex(String userTableName) throws IOException, KeeperException,
      InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    Configuration conf = UTIL.getConfiguration();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);

    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);

    HColumnDescriptor hcd1 = new HColumnDescriptor("col1");
    HColumnDescriptor hcd2 = new HColumnDescriptor("col2");
    ihtd.addFamily(hcd1);
    ihtd.addFamily(hcd2);
    IndexSpecification idx1 = new IndexSpecification("ScanMulIndex");
    idx1.addIndexColumn(hcd1, "ql", ValueType.String, 10);
    idx1.addIndexColumn(hcd2, "ql", ValueType.String, 10);
    ihtd.addIndex(idx1);

    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);
    HTable table = new HTable(conf, userTableName);

    // test put with the multiple indexed column in diffrent column families
    Put p1 = new Put("row1".getBytes());
    p1.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p1.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p1);

    Put p2 = new Put("row2".getBytes());
    p2.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p2.add("col2".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p2);

    Put p3 = new Put("row3".getBytes());
    p3.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p3.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p3);

    Put p4 = new Put("row4".getBytes());
    p4.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p4.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p4);

    Put p5 = new Put("row5".getBytes());
    p5.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p5.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p5);

    Put p6 = new Put("row6".getBytes());
    p6.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p6.add("col2".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p6);

    Put p7 = new Put("row7".getBytes());
    p7.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p7.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p7);

    Put p8 = new Put("row8".getBytes());
    p8.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p8.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p8);

  }

  private void collocateRowToDifferentRS(HBaseAdmin admin, HTable table, String rowKey)
      throws IOException, UnknownRegionException, MasterNotRunningException,
      ZooKeeperConnectionException {

    HRegionInfo regionInfo = table.getRegionLocation(rowKey).getRegionInfo();
    int originServerNum = UTIL.getMiniHBaseCluster().getServerWith(regionInfo.getRegionName());
    int targetServerNum = 3 - 1 - originServerNum;
    HRegionServer targetServer = UTIL.getMiniHBaseCluster().getRegionServer(targetServerNum);
    admin.move(regionInfo.getEncodedNameAsBytes(),
      Bytes.toBytes(targetServer.getServerName().getServerName()));
  }

  private void doPuts(Configuration conf, String userTableName) throws IOException {

    HTable table = new HTable(conf, userTableName);
    List<Put> puts = new ArrayList<Put>();

    for (int i = 1; i <= 2000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);
    puts = new ArrayList<Put>();

    for (int i = 2001; i <= 4000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 4001; i <= 6000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "pup".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 6001; i <= 8000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cats".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 8001; i <= 10000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "dogs".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 10001; i <= 12000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 12001; i <= 14000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "pup".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 14001; i <= 16000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
      puts.add(p1);
    }
    table.put(puts);

    puts = new ArrayList<Put>();
    for (int i = 16001; i <= 18000; i++) {
      Put p1 = new Put(("row" + i).getBytes());
      p1.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
      puts.add(p1);
    }
    table.put(puts);
    puts = new ArrayList<Put>();

  }

  class ParallelScanThread extends Thread {

    String filterString;
    String userTableName;
    int count;
    int cacheNumber;
    boolean iscached;

    ParallelScanThread(String userTableName, String filterString, boolean iscached, int cacheNumber)
        throws IOException {
      this.filterString = filterString;
      this.userTableName = userTableName;
      this.iscached = iscached;
      this.cacheNumber = cacheNumber;
    }

    public void run() {
      try {
        count =
            countNumberOfRowsWithFilter(userTableName, filterString, true, iscached, cacheNumber);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  class ParallelPutsValueThread extends Thread {

    int start;
    int end;
    String userTableName;
    Configuration conf;
    HTable table;
    String value;
    List<Put> puts;

    ParallelPutsValueThread(int start, Configuration conf, String userTableName, int end,
        String value) throws IOException {
      this.start = start;
      this.end = end;
      this.conf = conf;
      this.userTableName = userTableName;
      this.table = new HTable(this.conf, this.userTableName);
      this.value = value;
      puts = new ArrayList<Put>();
    }

    public void run() {

      for (int i = this.start; i <= this.end; i++) {
        Put p1 = new Put(("row" + i).getBytes());
        p1.add("col".getBytes(), "ql".getBytes(), value.getBytes());
        puts.add(p1);
      }
      try {
        this.table.put(puts);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private void doBulkParallelPuts(boolean toIndex, final String userTableName, boolean toFlush)
      throws IOException, KeeperException, InterruptedException {
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    final Configuration conf = UTIL.getConfiguration();
    HColumnDescriptor hcd = new HColumnDescriptor("col");

    if (toIndex) {
      IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
      IndexSpecification iSpec = new IndexSpecification("ScanIndexe");
      iSpec.addIndexColumn(hcd, "ql", ValueType.String, 10);
      ihtd.addFamily(hcd);
      ihtd.addIndex(iSpec);
      admin.createTable(ihtd);
    } else {
      HTableDescriptor htd = new HTableDescriptor(userTableName);
      htd.addFamily(hcd);
      admin.createTable(htd);
    }

    ZKAssign.blockUntilNoRIT(zkw);
    ParallelPutsValueThread p1 = new ParallelPutsValueThread(1, conf, userTableName, 10000, "dogs");
    p1.start();

    Put a1 = new Put(("row" + 10001).getBytes());
    a1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    HTable table2 = new HTable(conf, userTableName);
    table2.put(a1);
    ParallelPutsValueThread p2 =
        new ParallelPutsValueThread(10002, conf, userTableName, 30000, "dogs");
    p2.start();
    Put a2 = new Put(("row" + 30001).getBytes());
    a2.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    HTable table4 = new HTable(conf, userTableName);
    table4.put(a2);

    ParallelPutsValueThread p3 =
        new ParallelPutsValueThread(30002, conf, userTableName, 60000, "dogs");
    p3.start();

    Put a3 = new Put(("row" + 60001).getBytes());
    a3.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    HTable table6 = new HTable(conf, userTableName);
    table6.put(a3);

    ParallelPutsValueThread p4 =
        new ParallelPutsValueThread(60002, conf, userTableName, 100000, "dogs");
    p4.start();

    p1.join();
    p2.join();
    p3.join();
    p4.join();

    if (toFlush) {
      if (toIndex) {
        admin.flush(userTableName + Constants.INDEX_TABLE_SUFFIX);
        admin.flush(userTableName);
      } else {
        admin.flush(userTableName);
      }
    }
  }

  private long doPerformanceTest(boolean toIndex, final String userTableName, boolean toFlush)
      throws IOException, KeeperException, InterruptedException {
    doBulkParallelPuts(toIndex, userTableName, toFlush);
    long before = System.currentTimeMillis();
    int i = countNumberOfRowsWithFilter(userTableName, "cat", toIndex, false, 0);
    long after = System.currentTimeMillis();
    return (after - before);

  }

  private int countNumberOfRowsWithFilter(String tableName, String filterVal, boolean isIndexed,
      boolean isCached, int cacheNumber) throws IOException {
    Configuration conf = UTIL.getConfiguration();
    HTable table = new HTable(conf, tableName);
    Scan s = new Scan();
    Filter filter = null;
    if (isIndexed) {
      filter =
          new SingleColumnValueFilter("col".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
              filterVal.getBytes());
    } else {
      filter =
          new SingleColumnValueFilter("col".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
              "cat".getBytes());
    }
    s.setFilter(filter);
    if (isCached) {
      s.setCaching(cacheNumber);
    }
    int i = 0;
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    return i;
  }

  private HTable put4ColumnIndex() throws IOException, ZooKeeperConnectionException,
      KeeperException, InterruptedException {
    Configuration conf = UTIL.getConfiguration();
    String userTableName = "testcan4hMultIndexed2DiffFilters";
    HBaseAdmin admin = UTIL.getHBaseAdmin();
    conf.setInt("hbase.regionserver.lease.period", 900000000);
    ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL);
    IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName);
    HColumnDescriptor hcd1 = new HColumnDescriptor("col1");
    HColumnDescriptor hcd2 = new HColumnDescriptor("col2");
    HColumnDescriptor hcd3 = new HColumnDescriptor("col3");
    HColumnDescriptor hcd4 = new HColumnDescriptor("col4");
    ihtd.addFamily(hcd1);
    ihtd.addFamily(hcd2);
    ihtd.addFamily(hcd3);
    ihtd.addFamily(hcd4);
    IndexSpecification idx1 = new IndexSpecification("ScanMulIndex");
    idx1.addIndexColumn(hcd1, "ql", ValueType.String, 10);
    idx1.addIndexColumn(hcd2, "ql", ValueType.String, 10);
    idx1.addIndexColumn(hcd3, "ql", ValueType.String, 10);
    idx1.addIndexColumn(hcd4, "ql", ValueType.String, 10);
    ihtd.addIndex(idx1);

    admin.createTable(ihtd);
    ZKAssign.blockUntilNoRIT(zkw);
    HTable table = new HTable(conf, userTableName);

    // test put with the multiple indexed column in diffrent column families
    Put p1 = new Put("row1".getBytes());
    p1.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p1.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    p1.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p1.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p1);

    Put p2 = new Put("row2".getBytes());
    p2.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p2.add("col2".getBytes(), "ql".getBytes(), "cat".getBytes());
    p2.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p2.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p2);

    Put p3 = new Put("row3".getBytes());
    p3.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p3.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    p3.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p3.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p3);

    Put p4 = new Put("row4".getBytes());
    p4.add("col1".getBytes(), "ql".getBytes(), "dog".getBytes());
    p4.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    p4.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p4.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p4);

    Put p5 = new Put("row5".getBytes());
    p5.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p5.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    p5.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p5.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p5);

    Put p6 = new Put("row8".getBytes());
    p6.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p6.add("col2".getBytes(), "ql".getBytes(), "cat".getBytes());
    p6.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p6.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p6);

    Put p8 = new Put("row6".getBytes());
    p8.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p8.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    p8.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p8.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p8);

    Put p7 = new Put("row7".getBytes());
    p7.add("col1".getBytes(), "ql".getBytes(), "cat".getBytes());
    p7.add("col2".getBytes(), "ql".getBytes(), "dog".getBytes());
    p7.add("col3".getBytes(), "ql".getBytes(), "dog".getBytes());
    p7.add("col4".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p7);
    return table;
  }

  private byte[] generateStartKey(List<HRegionInfo> regionsOfTable) {
    byte[] startKey = regionsOfTable.get(0).getStartKey();

    byte[] startRow =
        new byte[startKey.length + Constants.DEF_MAX_INDEX_NAME_LENGTH + 10
            + "row999".getBytes().length];

    System.arraycopy(startKey, 0, startRow, 0, startKey.length);
    System.arraycopy("ScanIndex".getBytes(), 0, startRow, startKey.length, "ScanIndex".length());

    byte[] arr = new byte[18 - "ScanIndex".length()];
    byte e[] = new byte[10];

    System.arraycopy(arr, 0, startRow, startKey.length + "ScanIndex".length(), arr.length);
    System.arraycopy(e, 0, startRow, startKey.length + Constants.DEF_MAX_INDEX_NAME_LENGTH, 10);

    System.arraycopy("idxCat".getBytes(), 0, startRow, startKey.length
        + Constants.DEF_MAX_INDEX_NAME_LENGTH, "idxCat".getBytes().length);

    System.arraycopy("row99".getBytes(), 0, startRow, startKey.length
        + Constants.DEF_MAX_INDEX_NAME_LENGTH + 10, "row99".getBytes().length);

    System.out.println("constructed rowkey for indexed table " + Bytes.toString(startRow));
    return startRow;
  }

  private int singleIndexPutAndCache(Configuration conf, String userTableName) throws IOException {
    HTable table = new HTable(conf, userTableName);
    Put p1 = new Put("row1".getBytes());
    p1.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p1);

    Put p4 = new Put("row3".getBytes());
    p4.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p4);

    Put p5 = new Put("row2".getBytes());
    p5.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p5);

    Put p2 = new Put("row4".getBytes());
    p2.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p2);

    Put p3 = new Put("row5".getBytes());
    p3.add("col".getBytes(), "ql".getBytes(), "dogs".getBytes());
    table.put(p3);

    Put p6 = new Put("row6".getBytes());
    p6.add("col".getBytes(), "ql".getBytes(), "dog".getBytes());
    table.put(p6);

    Put p7 = new Put("row7".getBytes());
    p7.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p7);

    Put p8 = new Put("row8".getBytes());
    p8.add("col".getBytes(), "ql".getBytes(), "cat".getBytes());
    table.put(p8);

    int i = 0;
    Scan s = new Scan();
    Filter filter = null;
    filter =
        new SingleColumnValueFilter("col".getBytes(), "ql".getBytes(), CompareOp.EQUAL,
            "cat".getBytes());

    s.setFilter(filter);
    s.setCaching(3);
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      i++;
    }
    return i;
  }

  private void validateCountOfMainTableIndIndexedTable(Configuration conf, String userTableName,
      HTable table) throws IOException {
    Scan s = new Scan();
    int j = 0;
    ResultScanner scanner = table.getScanner(s);
    for (Result result : scanner) {
      j++;
    }

    HTable table1 = new HTable(conf, userTableName + Constants.INDEX_TABLE_SUFFIX);
    Scan s1 = new Scan();
    int k = 0;
    ResultScanner scanner1 = table1.getScanner(s1);
    for (Result result : scanner1) {
      k++;
    }

    Assert.assertEquals("COunt of rows in main tbale and indexed table shoudl be same ", j, k);
  }

}

class ExceptionFilter extends FilterList {
  public List<Filter> getFilters() {
    throw new RuntimeException("Exception thrwn from ExceptionFilter ");
  }

}
TOP

Related Classes of org.apache.hadoop.hbase.index.coprocessor.regionserver.TestIndexRegionObserverForScan

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.