Package org.apache.hadoop.hbase.client

Source Code of org.apache.hadoop.hbase.client.TestMetaMigrationRemovingHTD

/**
* Copyright 2010 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.client;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import junit.framework.Assert;
import junit.framework.AssertionFailedError;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.FsShell;
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.catalog.CatalogTracker;
import org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD;
import org.apache.hadoop.hbase.catalog.MetaReader;
import org.apache.hadoop.hbase.migration.HRegionInfo090x;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Writables;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Test migration that removes HTableDescriptor from HRegionInfo moving the
* meta version from no version to {@link MetaReader#META_VERSION}.
*/
public class TestMetaMigrationRemovingHTD {
  static final Log LOG = LogFactory.getLog(TestMetaMigrationRemovingHTD.class);
  private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
  private final static String TESTTABLE = "TestTable";
  private final static int ROWCOUNT = 100;

  @BeforeClass
  public static void setUpBeforeClass() throws Exception {
    // Start up our mini cluster on top of an 0.90 root.dir that has data from
    // a 0.90 hbase run -- it has a table with 100 rows in it  -- and see if
    // we can migrate from 0.90.
    TEST_UTIL.startMiniZKCluster();
    TEST_UTIL.startMiniDFSCluster(1);
    Path testdir = TEST_UTIL.getDataTestDir("TestMetaMigrationRemovingHTD");
    // Untar our test dir.
    File untar = untar(new File(testdir.toString()));
    // Now copy the untar up into hdfs so when we start hbase, we'll run from it.
    Configuration conf = TEST_UTIL.getConfiguration();
    FsShell shell = new FsShell(conf);
    FileSystem fs = FileSystem.get(conf);
    // find where hbase will root itself, so we can copy filesystem there
    Path hbaseRootDir = TEST_UTIL.getDefaultRootDirPath();
    doFsCommand(shell,
      new String [] {"-put", untar.toURI().toString(), hbaseRootDir.toString()});
    // See whats in minihdfs.
    doFsCommand(shell, new String [] {"-lsr", "/"});
    TEST_UTIL.startMiniHBaseCluster(1, 1);
    // Assert we are running against the copied-up filesystem.  The copied-up
    // rootdir should have had a table named 'TestTable' in it.  Assert it
    // present.
    HTable t = new HTable(TEST_UTIL.getConfiguration(), TESTTABLE);
    ResultScanner scanner = t.getScanner(new Scan());
    int count = 0;
    while (scanner.next() != null) {
      count++;
    }
    // Assert that we find all 100 rows that are in the data we loaded.  If
    // so then we must have migrated it from 0.90 to 0.92.
    Assert.assertEquals(ROWCOUNT, count);
  }

  private static File untar(final File testdir) throws IOException {
    // Find the src data under src/test/data
    final String datafile = "hbase-4388-root.dir";
    String srcTarFile =
      System.getProperty("project.build.testSourceDirectory", "src/test") +
      File.separator + "data" + File.separator + datafile + ".tgz";
    File homedir = new File(testdir.toString());
    File tgtUntarDir = new File(homedir, datafile);
    if (tgtUntarDir.exists()) {
      if (!FileUtil.fullyDelete(tgtUntarDir)) {
        throw new IOException("Failed delete of " + tgtUntarDir.toString());
      }
    }
    LOG.info("Untarring " + srcTarFile + " into " + homedir.toString());
    FileUtil.unTar(new File(srcTarFile), homedir);
    Assert.assertTrue(tgtUntarDir.exists());
    return tgtUntarDir;
  }

  private static void doFsCommand(final FsShell shell, final String [] args)
  throws Exception {
    // Run the 'put' command.
    int errcode = shell.run(args);
    if (errcode != 0) throw new IOException("Failed put; errcode=" + errcode);
  }

  /**
   * @throws java.lang.Exception
   */
  @AfterClass
  public static void tearDownAfterClass() throws Exception {
    TEST_UTIL.shutdownMiniCluster();
  }

  @Test
  public void testMetaUpdatedFlagInROOT() throws Exception {
    boolean metaUpdated = MetaMigrationRemovingHTD.
      isMetaHRIUpdated(TEST_UTIL.getMiniHBaseCluster().getMaster());
    assertEquals(true, metaUpdated);
  }

  @Test
  public void testMetaMigration() throws Exception {
    LOG.info("Starting testMetaWithLegacyHRI");
    final byte [] FAMILY = Bytes.toBytes("family");
    HTableDescriptor htd = new HTableDescriptor("testMetaMigration");
    HColumnDescriptor hcd = new HColumnDescriptor(FAMILY);
      htd.addFamily(hcd);
    Configuration conf = TEST_UTIL.getConfiguration();
    createMultiRegionsWithLegacyHRI(conf, htd, FAMILY,
        new byte[][]{
            HConstants.EMPTY_START_ROW,
            Bytes.toBytes("region_a"),
            Bytes.toBytes("region_b")});
    CatalogTracker ct =
      TEST_UTIL.getMiniHBaseCluster().getMaster().getCatalogTracker();
    // Erase the current version of root meta for this test.
    undoVersionInMeta();
    MetaReader.fullScanMetaAndPrint(ct);
    LOG.info("Meta Print completed.testUpdatesOnMetaWithLegacyHRI");

    Set<HTableDescriptor> htds =
      MetaMigrationRemovingHTD.updateMetaWithNewRegionInfo(
        TEST_UTIL.getHBaseCluster().getMaster());
    MetaReader.fullScanMetaAndPrint(ct);
    // Should be one entry only and it should be for the table we just added.
    assertEquals(1, htds.size());
    assertTrue(htds.contains(htd));
    // Assert that the flag in ROOT is updated to reflect the correct status
    boolean metaUpdated =
      MetaMigrationRemovingHTD.isMetaHRIUpdated(
        TEST_UTIL.getMiniHBaseCluster().getMaster());
    assertEquals(true, metaUpdated);
  }

  /**
   * This test assumes a master crash/failure during the meta migration process
   * and attempts to continue the meta migration process when a new master takes over.
   * When a master dies during the meta migration we will have some rows of
   * META.CatalogFamily updated with new HRI, (i.e HRI with out HTD) and some
   * still hanging with legacy HRI. (i.e HRI with HTD). When the backup master/ or
   * fresh start of master attempts the migration it will encouter some rows of META
   * already updated with new HRI and some still legacy. This test will simulate this
   * scenario and validates that the migration process can safely skip the updated
   * rows and migrate any pending rows at startup.
   * @throws Exception
   */
  @Test
  public void testMasterCrashDuringMetaMigration() throws Exception {
    final byte[] FAMILY = Bytes.toBytes("family");
    HTableDescriptor htd = new HTableDescriptor("testMasterCrashDuringMetaMigration");
    HColumnDescriptor hcd = new HColumnDescriptor(FAMILY);
      htd.addFamily(hcd);
    Configuration conf = TEST_UTIL.getConfiguration();
    // Create 10 New regions.
    createMultiRegionsWithNewHRI(conf, htd, FAMILY, 10);
    // Create 10 Legacy regions.
    createMultiRegionsWithLegacyHRI(conf, htd, FAMILY, 10);
    CatalogTracker ct =
      TEST_UTIL.getMiniHBaseCluster().getMaster().getCatalogTracker();
    // Erase the current version of root meta for this test.
    undoVersionInMeta();
    MetaMigrationRemovingHTD.updateRootWithMetaMigrationStatus(ct);
    //MetaReader.fullScanMetaAndPrint(ct);
    LOG.info("Meta Print completed.testUpdatesOnMetaWithLegacyHRI");

    Set<HTableDescriptor> htds =
      MetaMigrationRemovingHTD.updateMetaWithNewRegionInfo(
        TEST_UTIL.getHBaseCluster().getMaster());
    assertEquals(1, htds.size());
    assertTrue(htds.contains(htd));
    // Assert that the flag in ROOT is updated to reflect the correct status
    boolean metaUpdated = MetaMigrationRemovingHTD.
      isMetaHRIUpdated(TEST_UTIL.getMiniHBaseCluster().getMaster());
    assertEquals(true, metaUpdated);
    LOG.info("END testMetaWithLegacyHRI");
  }

  private void undoVersionInMeta() throws IOException {
    Delete d = new Delete(HRegionInfo.ROOT_REGIONINFO.getRegionName());
    // Erase the current version of root meta for this test.
    d.deleteColumn(HConstants.CATALOG_FAMILY, HConstants.META_VERSION_QUALIFIER);
    HTable rootTable =
      new HTable(TEST_UTIL.getConfiguration(), HConstants.ROOT_TABLE_NAME);
    try {
      rootTable.delete(d);
    } finally {
      rootTable.close();
    }
  }

  public static void assertEquals(int expected, int actual) {
    if (expected != actual) {
      throw new AssertionFailedError("expected:<" +
      expected + "> but was:<" +
      actual + ">");
    }
  }

  public static void assertEquals(boolean expected, boolean actual) {
    if (expected != actual) {
      throw new AssertionFailedError("expected:<" +
      expected + "> but was:<" +
      actual + ">");
    }
  }


  /**
   * @param c
   * @param htd
   * @param family
   * @param numRegions
   * @return
   * @throws IOException
   * @deprecated Just for testing migration of meta from 0.90 to 0.92... will be
   * removed thereafter
   */
  public int createMultiRegionsWithLegacyHRI(final Configuration c,
      final HTableDescriptor htd, final byte [] family, int numRegions)
  throws IOException {
    if (numRegions < 3) throw new IOException("Must create at least 3 regions");
    byte [] startKey = Bytes.toBytes("aaaaa");
    byte [] endKey = Bytes.toBytes("zzzzz");
    byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
    byte [][] regionStartKeys = new byte[splitKeys.length+1][];
    for (int i=0;i<splitKeys.length;i++) {
      regionStartKeys[i+1] = splitKeys[i];
    }
    regionStartKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
    return createMultiRegionsWithLegacyHRI(c, htd, family, regionStartKeys);
  }

  /**
   * @param c
   * @param htd
   * @param columnFamily
   * @param startKeys
   * @return
   * @throws IOException
   * @deprecated Just for testing migration of meta from 0.90 to 0.92... will be
   * removed thereafter
   */
  public int createMultiRegionsWithLegacyHRI(final Configuration c,
      final HTableDescriptor htd, final byte[] columnFamily, byte [][] startKeys)
  throws IOException {
    Arrays.sort(startKeys, Bytes.BYTES_COMPARATOR);
    HTable meta = new HTable(c, HConstants.META_TABLE_NAME);
    if(!htd.hasFamily(columnFamily)) {
      HColumnDescriptor hcd = new HColumnDescriptor(columnFamily);
      htd.addFamily(hcd);
    }
    List<HRegionInfo090x> newRegions
        = new ArrayList<HRegionInfo090x>(startKeys.length);
    int count = 0;
    for (int i = 0; i < startKeys.length; i++) {
      int j = (i + 1) % startKeys.length;
      HRegionInfo090x hri = new HRegionInfo090x(htd,
        startKeys[i], startKeys[j]);
      Put put = new Put(hri.getRegionName());
      put.setWriteToWAL(false);
      put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
        Writables.getBytes(hri));
      meta.put(put);
      LOG.info("createMultiRegions: PUT inserted " + hri.toString());

      newRegions.add(hri);
      count++;
    }
    return count;
  }

  int createMultiRegionsWithNewHRI(final Configuration c,
      final HTableDescriptor htd, final byte [] family, int numRegions)
  throws IOException {
    if (numRegions < 3) throw new IOException("Must create at least 3 regions");
    byte [] startKey = Bytes.toBytes("aaaaa");
    byte [] endKey = Bytes.toBytes("zzzzz");
    byte [][] splitKeys = Bytes.split(startKey, endKey, numRegions - 3);
    byte [][] regionStartKeys = new byte[splitKeys.length+1][];
    for (int i=0;i<splitKeys.length;i++) {
      regionStartKeys[i+1] = splitKeys[i];
    }
    regionStartKeys[0] = HConstants.EMPTY_BYTE_ARRAY;
    return createMultiRegionsWithNewHRI(c, htd, family, regionStartKeys);
  }

  int createMultiRegionsWithNewHRI(final Configuration c, final HTableDescriptor htd,
      final byte[] columnFamily, byte [][] startKeys)
  throws IOException {
    Arrays.sort(startKeys, Bytes.BYTES_COMPARATOR);
    HTable meta = new HTable(c, HConstants.META_TABLE_NAME);
    if(!htd.hasFamily(columnFamily)) {
      HColumnDescriptor hcd = new HColumnDescriptor(columnFamily);
      htd.addFamily(hcd);
    }
    List<HRegionInfo> newRegions
        = new ArrayList<HRegionInfo>(startKeys.length);
    int count = 0;
    for (int i = 0; i < startKeys.length; i++) {
      int j = (i + 1) % startKeys.length;
      HRegionInfo hri = new HRegionInfo(htd.getName(),
        startKeys[i], startKeys[j]);
      Put put = new Put(hri.getRegionName());
      put.setWriteToWAL(false);
      put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
        Writables.getBytes(hri));
      meta.put(put);
      LOG.info("createMultiRegions: PUT inserted " + hri.toString());

      newRegions.add(hri);
      count++;
    }
    return count;
  }
}
TOP

Related Classes of org.apache.hadoop.hbase.client.TestMetaMigrationRemovingHTD

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.