/**
* 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.metastore.hbase;
import co.cask.tephra.TransactionAware;
import co.cask.tephra.TransactionContext;
import co.cask.tephra.TransactionFailureException;
import co.cask.tephra.TransactionManager;
import co.cask.tephra.TransactionSystemClient;
import co.cask.tephra.distributed.ThreadLocalClientProvider;
import co.cask.tephra.distributed.TransactionServiceClient;
import co.cask.tephra.hbase10.TransactionAwareHTable;
import co.cask.tephra.hbase10.coprocessor.TransactionProcessor;
import co.cask.tephra.inmemory.InMemoryTxSystemClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.client.HTableInterface;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.twill.discovery.InMemoryDiscoveryService;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A class that uses Tephra for transaction management.
*/
public class TephraHBaseConnection extends VanillaHBaseConnection {
static final private Logger LOG = LoggerFactory.getLogger(TephraHBaseConnection.class.getName());
private Map<String, TransactionAware> txnTables;
private TransactionContext txn;
private TransactionSystemClient txnClient;
TephraHBaseConnection() {
super();
txnTables = new HashMap<String, TransactionAware>();
}
@Override
public void connect() throws IOException {
super.connect();
if (HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_IN_TEST)) {
LOG.debug("Using an in memory client transaction system for testing");
TransactionManager txnMgr = new TransactionManager(conf);
txnMgr.startAndWait();
txnClient = new InMemoryTxSystemClient(txnMgr);
} else {
// TODO should enable use of ZKDiscoveryService if users want it
LOG.debug("Using real client transaction system for production");
txnClient = new TransactionServiceClient(conf,
new ThreadLocalClientProvider(conf, new InMemoryDiscoveryService()));
}
for (String tableName : HBaseReadWrite.tableNames) {
txnTables.put(tableName, new TransactionAwareHTable(super.getHBaseTable(tableName, true)));
}
txn = new TransactionContext(txnClient, txnTables.values());
}
@Override
public void beginTransaction() throws IOException {
try {
txn.start();
LOG.debug("Started txn in tephra");
} catch (TransactionFailureException e) {
throw new IOException(e);
}
}
@Override
public void commitTransaction() throws IOException {
try {
txn.finish();
LOG.debug("Finished txn in tephra");
} catch (TransactionFailureException e) {
throw new IOException(e);
}
}
@Override
public void rollbackTransaction() throws IOException {
try {
txn.abort();
LOG.debug("Aborted txn in tephra");
} catch (TransactionFailureException e) {
throw new IOException(e);
}
}
@Override
public void flush(HTableInterface htab) throws IOException {
// NO-OP as we want to flush at commit time
}
@Override
protected HTableDescriptor buildDescriptor(String tableName, List<byte[]> columnFamilies)
throws IOException {
HTableDescriptor tableDesc = super.buildDescriptor(tableName, columnFamilies);
tableDesc.addCoprocessor(TransactionProcessor.class.getName());
return tableDesc;
}
@Override
public HTableInterface getHBaseTable(String tableName, boolean force) throws IOException {
// Ignore force, it will mess up our previous creation of the tables.
return (TransactionAwareHTable)txnTables.get(tableName);
}
}