Package org.apache.hadoop.hbase.catalog

Source Code of org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD

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

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.catalog.MetaReader.Visitor;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.master.MasterServices;
import org.apache.hadoop.hbase.migration.HRegionInfo090x;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Writables;

/**
* Tools to help with migration of meta tables so they no longer host
* instances of HTableDescriptor.
* @deprecated Used migration from 0.90 to 0.92 so will be going away in next
* release
*/
public class MetaMigrationRemovingHTD {
  private static final Log LOG = LogFactory.getLog(MetaMigrationRemovingHTD.class);

  /**
   * Update legacy META rows, removing HTD from HRI.
   * @param masterServices
   * @return List of table descriptors.
   * @throws IOException
   */
  public static Set<HTableDescriptor> updateMetaWithNewRegionInfo(
      final MasterServices masterServices)
  throws IOException {
    MigratingVisitor v = new MigratingVisitor(masterServices);
    MetaReader.fullScan(masterServices.getCatalogTracker(), v);
    updateRootWithMetaMigrationStatus(masterServices.getCatalogTracker());
    return v.htds;
  }

  /**
   * Update the ROOT with new HRI. (HRI with no HTD)
   * @param masterServices
   * @return List of table descriptors
   * @throws IOException
   */
  static Set<HTableDescriptor> updateRootWithNewRegionInfo(
      final MasterServices masterServices)
  throws IOException {
    MigratingVisitor v = new MigratingVisitor(masterServices);
    MetaReader.fullScan(masterServices.getCatalogTracker(), v, null, true);
    return v.htds;
  }

  /**
   * Meta visitor that migrates the info:regioninfo as it visits.
   */
  static class MigratingVisitor implements Visitor {
    private final MasterServices services;
    final Set<HTableDescriptor> htds = new HashSet<HTableDescriptor>();

    MigratingVisitor(final MasterServices services) {
      this.services = services;
    }

    @Override
    public boolean visit(Result r) throws IOException {
      if (r ==  null || r.isEmpty()) return true;
      // Check info:regioninfo, info:splitA, and info:splitB.  Make sure all
      // have migrated HRegionInfos... that there are no leftover 090 version
      // HRegionInfos.
      byte [] hriBytes = getBytes(r, HConstants.REGIONINFO_QUALIFIER);
      // Presumes that an edit updating all three cells either succeeds or
      // doesn't -- that we don't have case of info:regioninfo migrated but not
      // info:splitA.
      if (isMigrated(hriBytes)) return true;
      // OK. Need to migrate this row in meta.
      HRegionInfo090x hri090 = getHRegionInfo090x(hriBytes);
      HTableDescriptor htd = hri090.getTableDesc();
      if (htd == null) {
        LOG.warn("A 090 HRI has null HTD? Continuing; " + hri090.toString());
        return true;
      }
      if (!this.htds.contains(htd)) {
        // If first time we are adding a table, then write it out to fs.
        // Presumes that first region in table has THE table's schema which
        // might not be too bad of a presumption since it'll be first region
        // 'altered'
        this.services.getMasterFileSystem().createTableDescriptor(htd);
        this.htds.add(htd);
      }
      // This will 'migrate' the hregioninfo from 090 version to 092.
      HRegionInfo hri = new HRegionInfo(hri090);
      // Now make a put to write back to meta.
      Put p = new Put(hri.getRegionName());
      p.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
        Writables.getBytes(hri));
      // Now check info:splitA and info:splitB if present.  Migrate these too.
      checkSplit(r, p, HConstants.SPLITA_QUALIFIER);
      checkSplit(r, p, HConstants.SPLITB_QUALIFIER);
      // Below we fake out putToCatalogTable
      MetaEditor.putToCatalogTable(this.services.getCatalogTracker(), p);
      LOG.info("Migrated " + Bytes.toString(p.getRow()));
      return true;
    }
  }

  static void checkSplit(final Result r, final Put p, final byte [] which)
  throws IOException {
    byte [] hriSplitBytes = getBytes(r, which);
    if (!isMigrated(hriSplitBytes)) {
      // This will convert the HRI from 090 to 092 HRI.
      HRegionInfo hri = Writables.getHRegionInfo(hriSplitBytes);
      p.add(HConstants.CATALOG_FAMILY, which, Writables.getBytes(hri));
    }
  }

  /**
   * @param r Result to dig in.
   * @param qualifier Qualifier to look at in the passed <code>r</code>.
   * @return Bytes for an HRegionInfo or null if no bytes or empty bytes found.
   */
  static byte [] getBytes(final Result r, final byte [] qualifier) {
    byte [] hriBytes = r.getValue(HConstants.CATALOG_FAMILY, qualifier);
    if (hriBytes == null || hriBytes.length <= 0) return null;
    return hriBytes;
  }

  /**
   * @param r Result to look in.
   * @param qualifier What to look at in the passed result.
   * @return Either a 090 vintage HRegionInfo OR null if no HRegionInfo or
   * the HRegionInfo is up to date and not in need of migration.
   * @throws IOException
   */
  static HRegionInfo090x get090HRI(final Result r, final byte [] qualifier)
  throws IOException {
    byte [] hriBytes = r.getValue(HConstants.CATALOG_FAMILY, qualifier);
    if (hriBytes == null || hriBytes.length <= 0) return null;
    if (isMigrated(hriBytes)) return null;
    return getHRegionInfo090x(hriBytes);
  }

  static boolean isMigrated(final byte [] hriBytes) {
    if (hriBytes == null || hriBytes.length <= 0) return true;
    // Else, what version this HRegionInfo instance is at.  The first byte
    // is the version byte in a serialized HRegionInfo.  If its same as our
    // current HRI, then nothing to do.
    if (hriBytes[0] == HRegionInfo.VERSION) return true;
    if (hriBytes[0] == HRegionInfo.VERSION_PRE_092) return false;
    // Unknown version.  Return true that its 'migrated' but log warning.
    // Should 'never' happen.
    assert false: "Unexpected version; bytes=" + Bytes.toStringBinary(hriBytes);
    return true;
  }

  /**
   * Migrate root and meta to newer version. This updates the META and ROOT
   * and removes the HTD from HRI.
   * @param masterServices
   * @throws IOException
   */
  public static void migrateRootAndMeta(final MasterServices masterServices)
      throws IOException {
    updateRootWithNewRegionInfo(masterServices);
    updateMetaWithNewRegionInfo(masterServices);
  }

  /**
   * Update the version flag in -ROOT-.
   * @param catalogTracker
   * @throws IOException
   */
  public static void updateRootWithMetaMigrationStatus(final CatalogTracker catalogTracker)
  throws IOException {
    Put p = new Put(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
    MetaEditor.putToRootTable(catalogTracker, setMetaVersion(p));
    LOG.info("Updated -ROOT- meta version=" + HConstants.META_VERSION);
  }

  static Put setMetaVersion(final Put p) {
    p.add(HConstants.CATALOG_FAMILY, HConstants.META_VERSION_QUALIFIER,
      Bytes.toBytes(HConstants.META_VERSION));
    return p;
  }

  /**
   * @return True if the meta table has been migrated.
   * @throws IOException
   */
  // Public because used in tests
  public static boolean isMetaHRIUpdated(final MasterServices services)
      throws IOException {
    List<Result> results = MetaReader.fullScanOfRoot(services.getCatalogTracker());
    if (results == null || results.isEmpty()) {
      LOG.info("Not migrated");
      return false;
    }
    // Presume only the one result because we only support on meta region.
    Result r = results.get(0);
    short version = getMetaVersion(r);
    boolean migrated = version >= HConstants.META_VERSION;
    LOG.info("Meta version=" + version + "; migrated=" + migrated);
    return migrated;
  }

  /**
   * @param r Result to look at
   * @return Current meta table version or -1 if no version found.
   */
  static short getMetaVersion(final Result r) {
    byte [] value = r.getValue(HConstants.CATALOG_FAMILY,
        HConstants.META_VERSION_QUALIFIER);
    return value == null || value.length <= 0? -1: Bytes.toShort(value);
  }

  /**
   * @return True if migrated.
   * @throws IOException
   */
  public static boolean updateMetaWithNewHRI(final MasterServices services)
  throws IOException {
    if (isMetaHRIUpdated(services)) {
      LOG.info("ROOT/Meta already up-to date with new HRI.");
      return true;
    }
    LOG.info("Meta has HRI with HTDs. Updating meta now.");
    try {
      migrateRootAndMeta(services);
      LOG.info("ROOT and Meta updated with new HRI.");
      return true;
    } catch (IOException e) {
      throw new RuntimeException("Update ROOT/Meta with new HRI failed." +
        "Master startup aborted.");
    }
  }

  /**
   * Get HREgionInfoForMigration serialized from bytes.
   * @param bytes serialized bytes
   * @return An instance of a 090 HRI or null if we failed deserialize
   */
  public static HRegionInfo090x getHRegionInfo090x(final byte [] bytes) {
    if (bytes == null || bytes.length == 0) return null;
    HRegionInfo090x hri = null;
    try {
      hri = (HRegionInfo090x)Writables.getWritable(bytes, new HRegionInfo090x());
    } catch (IOException ioe) {
      LOG.warn("Failed deserialize as a 090 HRegionInfo); bytes=" +
        Bytes.toStringBinary(bytes), ioe);
    }
    return hri;
  }
}
TOP

Related Classes of org.apache.hadoop.hbase.catalog.MetaMigrationRemovingHTD

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.