/** * 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.utils; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import junit.framework.Assert; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HBaseTestingUtility; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.LargeTests; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.catalog.MetaEditor; import org.apache.hadoop.hbase.client.HBaseAdmin; import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; import org.apache.hadoop.hbase.index.ColumnQualifier.ValueType; 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.regionserver.IndexRegionObserver; import org.apache.hadoop.hbase.index.coprocessor.wal.IndexWALObserver; import org.apache.hadoop.hbase.index.util.SecondaryIndexColocator; import org.apache.hadoop.hbase.master.HMaster; import org.apache.hadoop.hbase.regionserver.HRegion; import org.apache.hadoop.hbase.regionserver.HRegionServer; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.FSTableDescriptors; import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread; import org.apache.hadoop.hbase.zookeeper.ZKAssign; import org.apache.hadoop.hbase.zookeeper.ZKTableReadOnly; import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; @Category(LargeTests.class) public class TestSecIndexColocator { 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(2); } @AfterClass public static void finishAfterClass() throws Exception { UTIL.shutdownMiniCluster(); } @Test(timeout = 180000) public void testCoLocationFixing() throws Exception { ZooKeeperWatcher zkw = HBaseTestingUtility.getZooKeeperWatcher(UTIL); HBaseAdmin admin = UTIL.getHBaseAdmin(); Configuration config = UTIL.getConfiguration(); String userTableName = "testCoLocationFixing"; IndexedHTableDescriptor ihtd = new IndexedHTableDescriptor(userTableName); HColumnDescriptor hcd = new HColumnDescriptor("cf1"); ihtd.addFamily(hcd); IndexSpecification iSpec = new IndexSpecification("idx"); iSpec.addIndexColumn(hcd, "q", ValueType.String, 10); ihtd.addIndex(iSpec); char c = 'A'; byte[][] splits = new byte[5][]; for (int i = 0; i < 5; i++) { byte[] b = { (byte) c }; c++; splits[i] = b; } admin.createTable(ihtd, splits); String userTableName1 = "testCoLocationFixing1"; ihtd = new IndexedHTableDescriptor(userTableName1); ihtd.addFamily(hcd); iSpec = new IndexSpecification("idx1"); iSpec.addIndexColumn(hcd, "q", ValueType.String, 10); ihtd.addIndex(iSpec); admin.createTable(ihtd, splits); String userTableName2 = "testCoLocationFixing2"; ihtd = new IndexedHTableDescriptor(userTableName2); ihtd.addFamily(hcd); iSpec = new IndexSpecification("idx2"); iSpec.addIndexColumn(hcd, "q", ValueType.String, 10); ihtd.addIndex(iSpec); admin.createTable(ihtd, splits); List<byte[]> regions = UTIL.getMetaTableRows(Bytes.toBytes(userTableName + "_idx")); List<byte[]> regionsEncod = getEncodedNames(regions); List<byte[]> regions1 = UTIL.getMetaTableRows(Bytes.toBytes(userTableName1 + "_idx")); List<byte[]> regionsEncod1 = getEncodedNames(regions1); List<byte[]> regions2 = UTIL.getMetaTableRows(Bytes.toBytes(userTableName2 + "_idx")); List<byte[]> regionsEncod2 = getEncodedNames(regions2); for (int i = 0; i < 2; i++) { admin.move(regionsEncod.get(i), null); admin.move(regionsEncod1.get(i), null); admin.move(regionsEncod2.get(i), null); } ZKAssign.blockUntilNoRIT(zkw); SecondaryIndexColocator colocator = new SecondaryIndexColocator(config); colocator.setUp(); boolean inconsistent = colocator.checkForCoLocationInconsistency(); Assert.assertTrue("Inconsistency should be there before running the tool.", inconsistent); colocator.fixCoLocationInconsistency(); ZKAssign.blockUntilNoRIT(zkw); colocator = new SecondaryIndexColocator(config); colocator.setUp(); inconsistent = colocator.checkForCoLocationInconsistency(); Assert.assertFalse("No inconsistency should be there after running the tool", inconsistent); } private List<byte[]> getEncodedNames(List<byte[]> regions) { List<byte[]> regionsEncod = new ArrayList<byte[]>(); for (byte[] r : regions) { String rs = Bytes.toString(r); int firstOcc = rs.indexOf('.'); int lastOcc = rs.lastIndexOf('.'); regionsEncod.add(Bytes.toBytes(rs.substring(firstOcc + 1, lastOcc))); } return regionsEncod; } @Test(timeout = 180000) public void testWhenUserTableIsDisabledButIndexTableIsInDisablingState() throws Exception { String table = "testWhenUserTableIsDisabledButIndexTableIsInDisablingState"; HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); HTableDescriptor htd = new HTableDescriptor(table); htd.addFamily(new HColumnDescriptor(new String("cf"))); byte[][] splits = new byte[10][]; char c = 'A'; for (int i = 0; i < 10; i++) { byte[] b = { (byte) c }; splits[i] = b; c++; } admin.createTable(htd, splits); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); admin.disableTable(table); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); byte[][] splits2 = new byte[11][]; c = 'A'; splits2[0] = new byte[0]; for (int i = 1; i < 11; i++) { byte[] b = { (byte) c }; splits2[i] = b; c++; } FileSystem filesystem = FileSystem.get(UTIL.getConfiguration()); Path rootdir = filesystem.makeQualified(new Path(UTIL.getConfiguration().get(HConstants.HBASE_DIR))); HMaster master = UTIL.getMiniHBaseCluster().getMasterThreads().get(0).getMaster(); String table2 = "testWhenUserTableIsDisabledButIndexTableIsInDisablingState_idx"; HTableDescriptor htd2 = new HTableDescriptor(table2); htd2.addFamily(new HColumnDescriptor(new String("cf1"))); FSTableDescriptors.createTableDescriptor(htd2, UTIL.getConfiguration()); List<HRegionInfo> regionsInMeta = UTIL.createMultiRegionsInMeta(UTIL.getConfiguration(), htd2, splits2); List<HRegionInfo> newRegions = new ArrayList<HRegionInfo>(); for (HRegionInfo regionInfo : regionsInMeta) { HRegion r = HRegion.createHRegion(regionInfo, rootdir, UTIL.getConfiguration(), htd2); newRegions.add(r.getRegionInfo()); } for (int i = 0; i < newRegions.size() / 2; i++) { admin.assign(newRegions.get(i).getRegionName()); } ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); master.getAssignmentManager().getZKTable().setDisablingTable(table2); SecondaryIndexColocator colocator = new SecondaryIndexColocator(UTIL.getConfiguration()); colocator.setUp(); boolean inconsistent = colocator.checkForCoLocationInconsistency(); List<RegionServerThread> serverThreads = UTIL.getMiniHBaseCluster().getLiveRegionServerThreads(); List<HRegionServer> rs = new ArrayList<HRegionServer>(); for (RegionServerThread regionServerThread : serverThreads) { rs.add(regionServerThread.getRegionServer()); } List<HRegionInfo> onlineregions = new ArrayList<HRegionInfo>(); for (HRegionServer hrs : rs) { onlineregions.addAll(hrs.getOnlineRegions()); } boolean regionOnline = false; for (HRegionInfo hri : onlineregions) { for (HRegionInfo disabledregion : newRegions) { if (hri.equals(disabledregion)) { regionOnline = true; break; } } } Assert.assertFalse("NO region from the disabledTable should be online.", regionOnline); Assert.assertTrue("The disabling table should be now disabled", ZKTableReadOnly.isDisabledTable(HBaseTestingUtility.getZooKeeperWatcher(UTIL), table2)); } @Test(timeout = 180000) public void testWhenUserTableIsDisabledButIndexTableIsInEnabledState() throws Exception { String table = "testWhenUserTableIsDisabledButIndexTableIsInEnabledState"; HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); HTableDescriptor htd = new HTableDescriptor(table); htd.addFamily(new HColumnDescriptor(new String("cf"))); byte[][] splits = new byte[10][]; char c = 'A'; for (int i = 0; i < 10; i++) { byte[] b = { (byte) c }; splits[i] = b; c++; } admin.createTable(htd, splits); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); admin.disableTable(table); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); byte[][] splits2 = new byte[11][]; c = 'A'; splits2[0] = new byte[0]; for (int i = 1; i < 11; i++) { byte[] b = { (byte) c }; splits2[i] = b; c++; } FileSystem filesystem = FileSystem.get(UTIL.getConfiguration()); Path rootdir = filesystem.makeQualified(new Path(UTIL.getConfiguration().get(HConstants.HBASE_DIR))); HMaster master = UTIL.getMiniHBaseCluster().getMasterThreads().get(0).getMaster(); String table2 = "testWhenUserTableIsDisabledButIndexTableIsInEnabledState_idx"; HTableDescriptor htd2 = new HTableDescriptor(table2); htd2.addFamily(new HColumnDescriptor(new String("cf1"))); FSTableDescriptors.createTableDescriptor(htd2, UTIL.getConfiguration()); List<HRegionInfo> regionsInMeta = UTIL.createMultiRegionsInMeta(UTIL.getConfiguration(), htd2, splits2); List<HRegionInfo> newRegions = new ArrayList<HRegionInfo>(); for (HRegionInfo regionInfo : regionsInMeta) { HRegion r = HRegion.createHRegion(regionInfo, rootdir, UTIL.getConfiguration(), htd2); newRegions.add(r.getRegionInfo()); } for (int i = 0; i < newRegions.size() / 2; i++) { admin.assign(newRegions.get(i).getRegionName()); } master.getAssignmentManager().getZKTable().setEnabledTable(table2); SecondaryIndexColocator colocator = new SecondaryIndexColocator(UTIL.getConfiguration()); colocator.setUp(); colocator.checkForCoLocationInconsistency(); List<RegionServerThread> serverThreads = UTIL.getMiniHBaseCluster().getLiveRegionServerThreads(); List<HRegionServer> rs = new ArrayList<HRegionServer>(); for (RegionServerThread regionServerThread : serverThreads) { rs.add(regionServerThread.getRegionServer()); } List<HRegionInfo> onlineregions = new ArrayList<HRegionInfo>(); for (HRegionServer hrs : rs) { onlineregions.addAll(hrs.getOnlineRegions()); } boolean regionOnline = false; for (HRegionInfo hri : onlineregions) { for (HRegionInfo disabledregion : newRegions) { if (hri.equals(disabledregion)) { regionOnline = true; } } } Assert.assertFalse("NO region from the disabledTable should be online.", regionOnline); Assert.assertTrue("The enabled table should be now disabled", ZKTableReadOnly.isDisabledTable(HBaseTestingUtility.getZooKeeperWatcher(UTIL), table2)); } @Test(timeout = 180000) public void testWhenAllUSerRegionsAreAssignedButNotSameForIndex() throws Exception { String table = "testWhenAllUSerRegionsAreAssignedButNotSameForIndex"; HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); HTableDescriptor htd = new HTableDescriptor(table); htd.addFamily(new HColumnDescriptor(new String("cf"))); byte[][] splits = new byte[10][]; char c = 'A'; for (int i = 0; i < 10; i++) { byte[] b = { (byte) c }; splits[i] = b; c++; } admin.createTable(htd, splits); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); byte[][] splits2 = new byte[11][]; c = 'A'; splits2[0] = new byte[0]; for (int i = 1; i < 11; i++) { byte[] b = { (byte) c }; splits2[i] = b; c++; } FileSystem filesystem = FileSystem.get(UTIL.getConfiguration()); Path rootdir = filesystem.makeQualified(new Path(UTIL.getConfiguration().get(HConstants.HBASE_DIR))); HMaster master = UTIL.getMiniHBaseCluster().getMasterThreads().get(0).getMaster(); String table2 = "testWhenAllUSerRegionsAreAssignedButNotSameForIndex_idx"; HTableDescriptor htd2 = new HTableDescriptor(table2); htd2.addFamily(new HColumnDescriptor(new String("cf1"))); FSTableDescriptors.createTableDescriptor(htd2, UTIL.getConfiguration()); List<HRegionInfo> regionsInMeta = UTIL.createMultiRegionsInMeta(UTIL.getConfiguration(), htd2, splits2); List<HRegionInfo> newRegions = new ArrayList<HRegionInfo>(); for (HRegionInfo regionInfo : regionsInMeta) { HRegion r = HRegion.createHRegion(regionInfo, rootdir, UTIL.getConfiguration(), htd2); newRegions.add(r.getRegionInfo()); } for (int i = 0; i < newRegions.size() / 2; i++) { admin.assign(newRegions.get(i).getRegionName()); } master.getAssignmentManager().getZKTable().setEnabledTable(table2); SecondaryIndexColocator colocator = new SecondaryIndexColocator(UTIL.getConfiguration()); colocator.setUp(); colocator.checkForCoLocationInconsistency(); List<RegionServerThread> serverThreads = UTIL.getMiniHBaseCluster().getLiveRegionServerThreads(); List<HRegionServer> rs = new ArrayList<HRegionServer>(); for (RegionServerThread regionServerThread : serverThreads) { rs.add(regionServerThread.getRegionServer()); } Set<HRegionInfo> onlineregions = new HashSet<HRegionInfo>(); for (HRegionServer hrs : rs) { onlineregions.addAll(hrs.getOnlineRegions()); } boolean regionOffline = false; for (HRegionInfo hri : newRegions) { if (!onlineregions.contains(hri)) { regionOffline = true; break; } } Assert.assertFalse("All region from the index Table should be online.", regionOffline); } @Test(timeout = 180000) public void testWhenUserTableIsEabledButIndexTableIsDisabled() throws Exception { String table = "testWhenUserTableIsEabledButIndexTableIsDisabled"; HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); HTableDescriptor htd = new HTableDescriptor(table); htd.addFamily(new HColumnDescriptor(new String("cf"))); byte[][] splits = new byte[10][]; char c = 'A'; for (int i = 0; i < 10; i++) { byte[] b = { (byte) c }; splits[i] = b; c++; } admin.createTable(htd, splits); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); String table2 = "testWhenUserTableIsEabledButIndexTableIsDisabled_idx"; HTableDescriptor htd2 = new HTableDescriptor(table2); htd2.addFamily(new HColumnDescriptor(new String("cf"))); admin.createTable(htd2, splits); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); admin.disableTable(table2); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); List<HRegionInfo> tableRegions = admin.getTableRegions(Bytes.toBytes(table2)); SecondaryIndexColocator colocator = new SecondaryIndexColocator(UTIL.getConfiguration()); colocator.setUp(); boolean inconsistent = colocator.checkForCoLocationInconsistency(); List<RegionServerThread> serverThreads = UTIL.getMiniHBaseCluster().getLiveRegionServerThreads(); List<HRegionServer> rs = new ArrayList<HRegionServer>(); for (RegionServerThread regionServerThread : serverThreads) { rs.add(regionServerThread.getRegionServer()); } Set<HRegionInfo> onlineregions = new HashSet<HRegionInfo>(); for (HRegionServer hrs : rs) { onlineregions.addAll(hrs.getOnlineRegions()); } boolean regionOffline = false; for (HRegionInfo hri : tableRegions) { if (!onlineregions.contains(hri)) { regionOffline = true; break; } } Assert.assertFalse("All region from the disabledTable should be online.", regionOffline); } @Test(timeout = 180000) public void testWhenRegionsAreNotAssignedAccordingToMeta() throws Exception { String table = "testWhenRegionsAreNotAssignedAccordingToMeta"; HBaseAdmin admin = new HBaseAdmin(UTIL.getConfiguration()); HTableDescriptor htd = new HTableDescriptor(table); htd.addFamily(new HColumnDescriptor(new String("cf"))); byte[][] splits = new byte[10][]; char c = 'A'; for (int i = 0; i < 10; i++) { byte[] b = { (byte) c }; splits[i] = b; c++; } admin.createTable(htd, splits); ZKAssign.blockUntilNoRIT(HBaseTestingUtility.getZooKeeperWatcher(UTIL)); ServerName sn = new ServerName("example.org", 1234, 5678); HMaster master = UTIL.getMiniHBaseCluster().getMaster(0); List<HRegionInfo> tableRegions = admin.getTableRegions(Bytes.toBytes(table)); for (int i = 0; i < 5; i++) { MetaEditor.updateRegionLocation(master.getCatalogTracker(), tableRegions.get(i), sn); } SecondaryIndexColocator colocator = new SecondaryIndexColocator(UTIL.getConfiguration()); colocator.setUp(); colocator.checkForCoLocationInconsistency(); List<RegionServerThread> serverThreads = UTIL.getMiniHBaseCluster().getLiveRegionServerThreads(); List<HRegionServer> rs = new ArrayList<HRegionServer>(); for (RegionServerThread regionServerThread : serverThreads) { rs.add(regionServerThread.getRegionServer()); } Set<HRegionInfo> onlineregions = new HashSet<HRegionInfo>(); for (HRegionServer hrs : rs) { onlineregions.addAll(hrs.getOnlineRegions()); } boolean regionOffline = false; for (HRegionInfo hri : tableRegions) { if (!onlineregions.contains(hri)) { regionOffline = true; break; } } Assert.assertFalse( "All the regions with wrong META info should be assiged to some online server.", regionOffline); } }