/** * 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.hive.hbase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl; import org.apache.hadoop.mapred.InputSplit; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * A helper class to isolate newer HBase features from users running against older versions of * HBase that don't provide those features. * * TODO: remove this class when it's okay to drop support for earlier version of HBase. */ public class HBaseTableSnapshotInputFormatUtil { private static final Logger LOG = LoggerFactory.getLogger(HBaseTableSnapshotInputFormatUtil.class); /** The class we look for to determine if hbase snapshots are supported. */ private static final String TABLESNAPSHOTINPUTFORMAT_CLASS = "org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl"; private static final String TABLESNAPSHOTREGIONSPLIT_CLASS = "org.apache.hadoop.hbase.mapred.TableSnapshotInputFormat$TableSnapshotRegionSplit"; /** True when {@link #TABLESNAPSHOTINPUTFORMAT_CLASS} is present. */ private static final boolean SUPPORTS_TABLE_SNAPSHOTS; static { boolean support = false; try { Class<?> clazz = Class.forName(TABLESNAPSHOTINPUTFORMAT_CLASS); support = clazz != null; } catch (ClassNotFoundException e) { // pass } SUPPORTS_TABLE_SNAPSHOTS = support; } /** Return true when the HBase runtime supports {@link HiveHBaseTableSnapshotInputFormat}. */ public static void assertSupportsTableSnapshots() { if (!SUPPORTS_TABLE_SNAPSHOTS) { throw new RuntimeException("This version of HBase does not support Hive over table " + "snapshots. Please upgrade to at least HBase 0.98.3 or later. See HIVE-6584 for details."); } } /** * Configures {@code conf} for the snapshot job. Call only when * {@link #assertSupportsTableSnapshots()} returns true. */ public static void configureJob(Configuration conf, String snapshotName, Path restoreDir) throws IOException { TableSnapshotInputFormatImpl.setInput(conf, snapshotName, restoreDir); } /** * Create a bare TableSnapshotRegionSplit. Needed because Writables require a * default-constructed instance to hydrate from the DataInput. * * TODO: remove once HBASE-11555 is fixed. */ public static InputSplit createTableSnapshotRegionSplit() { try { assertSupportsTableSnapshots(); } catch (RuntimeException e) { LOG.debug("Probably don't support table snapshots. Returning null instance.", e); return null; } try { Class<? extends InputSplit> resultType = (Class<? extends InputSplit>) Class.forName(TABLESNAPSHOTREGIONSPLIT_CLASS); Constructor<? extends InputSplit> cxtor = resultType.getDeclaredConstructor(new Class[]{}); cxtor.setAccessible(true); return cxtor.newInstance(new Object[]{}); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException( "Unable to find " + TABLESNAPSHOTREGIONSPLIT_CLASS, e); } catch (IllegalAccessException e) { throw new UnsupportedOperationException( "Unable to access specified class " + TABLESNAPSHOTREGIONSPLIT_CLASS, e); } catch (InstantiationException e) { throw new UnsupportedOperationException( "Unable to instantiate specified class " + TABLESNAPSHOTREGIONSPLIT_CLASS, e); } catch (InvocationTargetException e) { throw new UnsupportedOperationException( "Constructor threw an exception for " + TABLESNAPSHOTREGIONSPLIT_CLASS, e); } catch (NoSuchMethodException e) { throw new UnsupportedOperationException( "Unable to find suitable constructor for class " + TABLESNAPSHOTREGIONSPLIT_CLASS, e); } } }