use of io.cdap.cdap.spi.hbase.HBaseDDLExecutor in project cdap by caskdata.
the class HBaseTableFactory method upgradeCoProcessor.
private void upgradeCoProcessor(TableId tableId, Class<? extends Coprocessor> coprocessor) throws IOException {
try (HBaseDDLExecutor ddlExecutor = ddlExecutorFactory.get()) {
HTableDescriptor tableDescriptor;
try (HBaseAdmin admin = new HBaseAdmin(hConf)) {
// If table doesn't exist, then skip upgrading coprocessor
if (!tableUtil.tableExists(admin, tableId)) {
LOG.debug("TMS Table {} was not found. Skip upgrading coprocessor.", tableId);
return;
}
tableDescriptor = tableUtil.getHTableDescriptor(admin, tableId);
}
// Get cdap version from the table
ProjectInfo.Version version = HBaseTableUtil.getVersion(tableDescriptor);
String hbaseVersion = HBaseTableUtil.getHBaseVersion(tableDescriptor);
if (hbaseVersion != null && hbaseVersion.equals(HBaseVersion.getVersionString()) && version.compareTo(ProjectInfo.getVersion()) >= 0) {
// If cdap has version has not changed or is greater, no need to update. Just enable it, in case
// it has been disabled by the upgrade tool, and return
LOG.info("Table '{}' has not changed and its version '{}' is same or greater than current CDAP version '{}'." + " The underlying HBase version {} has also not changed.", tableId, version, ProjectInfo.getVersion(), hbaseVersion);
enableTable(ddlExecutor, tableId);
return;
}
// create a new descriptor for the table update
HTableDescriptorBuilder newDescriptor = tableUtil.buildHTableDescriptor(tableDescriptor);
// Remove old coprocessor
Map<String, HBaseTableUtil.CoprocessorInfo> coprocessorInfo = HBaseTableUtil.getCoprocessorInfo(tableDescriptor);
for (Map.Entry<String, HBaseTableUtil.CoprocessorInfo> coprocessorEntry : coprocessorInfo.entrySet()) {
newDescriptor.removeCoprocessor(coprocessorEntry.getValue().getClassName());
}
// Add new coprocessor
CoprocessorDescriptor coprocessorDescriptor = coprocessorManager.getCoprocessorDescriptor(coprocessor, Coprocessor.PRIORITY_USER);
Path path = coprocessorDescriptor.getPath() == null ? null : new Path(coprocessorDescriptor.getPath());
newDescriptor.addCoprocessor(coprocessorDescriptor.getClassName(), path, coprocessorDescriptor.getPriority(), coprocessorDescriptor.getProperties());
// Update CDAP version, table prefix
HBaseTableUtil.setVersion(newDescriptor);
HBaseTableUtil.setHBaseVersion(newDescriptor);
HBaseTableUtil.setTablePrefix(newDescriptor, cConf);
// Disable auto-splitting
newDescriptor.setValue(HTableDescriptor.SPLIT_POLICY, cConf.get(Constants.MessagingSystem.TABLE_HBASE_SPLIT_POLICY));
// Disable Table
disableTable(ddlExecutor, tableId);
tableUtil.modifyTable(ddlExecutor, newDescriptor.build());
LOG.debug("Enabling table '{}'...", tableId);
enableTable(ddlExecutor, tableId);
}
LOG.info("Table '{}' update completed.", tableId);
}
use of io.cdap.cdap.spi.hbase.HBaseDDLExecutor in project cdap by caskdata.
the class HBaseTableFactory method createTable.
/**
* Creates a new instance of {@link Table} for the given {@link TableId}. If the hbase table doesn't
* exist, a new one will be created with the given number of splits.
*/
private HTableWithRowKeyDistributor createTable(TableId tableId, int splits, Class<? extends Coprocessor> coprocessor) throws IOException {
// Lookup the table descriptor from the cache first. If it is there, we assume the HBase table exists
// Otherwise, attempt to create it.
Table table = null;
HTableDescriptor htd = tableDescriptors.get(tableId);
if (htd == null) {
synchronized (this) {
htd = tableDescriptors.get(tableId);
if (htd == null) {
boolean tableExists;
try (HBaseAdmin admin = new HBaseAdmin(hConf)) {
tableExists = tableUtil.tableExists(admin, tableId);
}
// Create the table if the table doesn't exist
try (HBaseDDLExecutor ddlExecutor = ddlExecutorFactory.get()) {
// If table exists, then skip creating coprocessor etc
if (!tableExists) {
TableId metadataTableId = tableUtil.createHTableId(NamespaceId.SYSTEM, cConf.get(Constants.MessagingSystem.METADATA_TABLE_NAME));
ColumnFamilyDescriptorBuilder cfdBuilder = HBaseTableUtil.getColumnFamilyDescriptorBuilder(Bytes.toString(COLUMN_FAMILY), hConf);
TableDescriptorBuilder tdBuilder = HBaseTableUtil.getTableDescriptorBuilder(tableId, cConf).addColumnFamily(cfdBuilder.build()).addProperty(Constants.MessagingSystem.HBASE_MESSAGING_TABLE_PREFIX_NUM_BYTES, Integer.toString(1)).addProperty(Constants.MessagingSystem.KEY_DISTRIBUTOR_BUCKETS_ATTR, Integer.toString(splits)).addProperty(Constants.MessagingSystem.HBASE_METADATA_TABLE_NAMESPACE, metadataTableId.getNamespace()).addProperty(HTableDescriptor.SPLIT_POLICY, cConf.get(Constants.MessagingSystem.TABLE_HBASE_SPLIT_POLICY)).addCoprocessor(coprocessorManager.getCoprocessorDescriptor(coprocessor, Coprocessor.PRIORITY_USER));
// Set the key distributor size the same as the initial number of splits,
// essentially one bucket per split.
byte[][] splitKeys = HBaseTableUtil.getSplitKeys(splits, splits, new RowKeyDistributorByHashPrefix(new OneByteSimpleHash(splits)));
ddlExecutor.createTableIfNotExists(tdBuilder.build(), splitKeys);
table = tableUtil.createTable(hConf, tableId);
htd = table.getTableDescriptor();
tableDescriptors.put(tableId, htd);
} else {
table = tableUtil.createTable(hConf, tableId);
htd = table.getTableDescriptor();
tableDescriptors.put(tableId, htd);
}
}
}
}
}
if (table == null) {
table = tableUtil.createTable(hConf, tableId);
}
return new HTableWithRowKeyDistributor(table, new RowKeyDistributorByHashPrefix(new OneByteSimpleHash(getKeyDistributorBuckets(tableId, htd))));
}
use of io.cdap.cdap.spi.hbase.HBaseDDLExecutor in project cdap by caskdata.
the class DatasetUpgrader method upgradeUserTables.
private void upgradeUserTables(final ExecutorService executor) throws Exception {
final Map<String, Future<?>> allFutures = new HashMap<>();
final List<Closeable> toClose = new ArrayList<>();
for (final NamespaceMeta namespaceMeta : namespaceQueryAdmin.list()) {
impersonator.doAs(namespaceMeta.getNamespaceId(), new Callable<Void>() {
@Override
public Void call() throws Exception {
HBaseDDLExecutor ddlExecutor = ddlExecutorFactory.get();
// register it for close, after all Futures are complete
toClose.add(ddlExecutor);
Map<String, Future<?>> futures = upgradeUserTables(namespaceMeta, executor, ddlExecutor);
allFutures.putAll(futures);
return null;
}
});
}
// Wait for the user dataset upgrades to complete
try {
Map<String, Throwable> failed = waitForUpgrade(allFutures);
if (!failed.isEmpty()) {
for (Map.Entry<String, Throwable> entry : failed.entrySet()) {
LOG.error("Failed to upgrade user table {}", entry.getKey(), entry.getValue());
}
throw new Exception(String.format("Error upgrading user tables. %s of %s failed", failed.size(), allFutures.size()));
}
} finally {
for (Closeable closeable : toClose) {
Closeables.closeQuietly(closeable);
}
}
}
use of io.cdap.cdap.spi.hbase.HBaseDDLExecutor in project cdap by cdapio.
the class AbstractHBaseDataSetAdmin method updateTable.
/**
* Performs update on a given HBase table. It will be updated if either its spec has
* changed since the HBase table was created or updated, or if the CDAP version recorded
* in the HTable descriptor is less than the current CDAP version.
*
* @param force forces update regardless of whether the table needs it.
* @throws IOException If update failed.
*/
public void updateTable(boolean force) throws IOException {
try (HBaseDDLExecutor ddlExecutor = ddlExecutorFactory.get()) {
HTableDescriptor tableDescriptor;
HTableDescriptorBuilder newDescriptor;
try (HBaseAdmin admin = new HBaseAdmin(hConf)) {
tableDescriptor = tableUtil.getHTableDescriptor(admin, tableId);
// create a new descriptor for the table update
newDescriptor = tableUtil.buildHTableDescriptor(tableDescriptor);
}
// update any table properties if necessary
boolean needUpdate = needsUpdate(tableDescriptor, newDescriptor) || force;
// Get the cdap version from the table
ProjectInfo.Version version = HBaseTableUtil.getVersion(tableDescriptor);
String hbaseVersion = HBaseTableUtil.getHBaseVersion(tableDescriptor);
if (!needUpdate && hbaseVersion != null && hbaseVersion.equals(HBaseVersion.getVersionString()) && version.compareTo(ProjectInfo.getVersion()) >= 0) {
// If neither the table spec nor the cdap version have changed, no need to update
LOG.info("Table '{}' has not changed and its version '{}' is same or greater " + "than current CDAP version '{}'. The underlying HBase version {} has also not changed.", tableId, version, ProjectInfo.getVersion(), hbaseVersion);
return;
}
// Generate the coprocessor jar
CoprocessorJar coprocessorJar = createCoprocessorJar();
Location jarLocation = coprocessorJar.getJarLocation();
// Check if coprocessor upgrade is needed
Map<String, HBaseTableUtil.CoprocessorInfo> coprocessorInfo = HBaseTableUtil.getCoprocessorInfo(tableDescriptor);
// For all required coprocessors, check if they've need to be upgraded.
for (Class<? extends Coprocessor> coprocessor : coprocessorJar.getCoprocessors()) {
HBaseTableUtil.CoprocessorInfo info = coprocessorInfo.get(coprocessor.getName());
if (info != null) {
// The same coprocessor has been configured, check by the file name to see if they are the same.
if (!jarLocation.getName().equals(info.getPath().getName())) {
// Remove old one and add the new one.
newDescriptor.removeCoprocessor(info.getClassName());
addCoprocessor(newDescriptor, coprocessor, coprocessorJar.getPriority(coprocessor));
}
} else {
// The coprocessor is missing from the table, add it.
addCoprocessor(newDescriptor, coprocessor, coprocessorJar.getPriority(coprocessor));
}
}
// Removes all old coprocessors
Set<String> coprocessorNames = ImmutableSet.copyOf(Iterables.transform(coprocessorJar.coprocessors, CLASS_TO_NAME));
for (String remove : Sets.difference(coprocessorInfo.keySet(), coprocessorNames)) {
newDescriptor.removeCoprocessor(remove);
}
HBaseTableUtil.setVersion(newDescriptor);
HBaseTableUtil.setHBaseVersion(newDescriptor);
HBaseTableUtil.setTablePrefix(newDescriptor, cConf);
LOG.info("Updating table '{}'...", tableId);
TableName tableName = HTableNameConverter.toTableName(cConf.get(Constants.Dataset.TABLE_PREFIX), tableId);
boolean enableTable = false;
try {
ddlExecutor.disableTableIfEnabled(tableName.getNamespaceAsString(), tableName.getQualifierAsString());
enableTable = true;
} catch (TableNotEnabledException e) {
// If the table is in cdap_system namespace enable it regardless so that they can be used later. See CDAP-7324
if (isSystemTable()) {
enableTable = true;
} else {
LOG.debug("Table '{}' was not enabled before update and will not be enabled after update.", tableId);
}
}
tableUtil.modifyTable(ddlExecutor, newDescriptor.build());
if (enableTable) {
LOG.debug("Enabling table '{}'...", tableId);
ddlExecutor.enableTableIfDisabled(tableName.getNamespaceAsString(), tableName.getQualifierAsString());
}
}
LOG.info("Table '{}' update completed.", tableId);
}
use of io.cdap.cdap.spi.hbase.HBaseDDLExecutor in project cdap by cdapio.
the class DatasetUpgrader method upgradeUserTables.
private void upgradeUserTables(final ExecutorService executor) throws Exception {
final Map<String, Future<?>> allFutures = new HashMap<>();
final List<Closeable> toClose = new ArrayList<>();
for (final NamespaceMeta namespaceMeta : namespaceQueryAdmin.list()) {
impersonator.doAs(namespaceMeta.getNamespaceId(), new Callable<Void>() {
@Override
public Void call() throws Exception {
HBaseDDLExecutor ddlExecutor = ddlExecutorFactory.get();
// register it for close, after all Futures are complete
toClose.add(ddlExecutor);
Map<String, Future<?>> futures = upgradeUserTables(namespaceMeta, executor, ddlExecutor);
allFutures.putAll(futures);
return null;
}
});
}
// Wait for the user dataset upgrades to complete
try {
Map<String, Throwable> failed = waitForUpgrade(allFutures);
if (!failed.isEmpty()) {
for (Map.Entry<String, Throwable> entry : failed.entrySet()) {
LOG.error("Failed to upgrade user table {}", entry.getKey(), entry.getValue());
}
throw new Exception(String.format("Error upgrading user tables. %s of %s failed", failed.size(), allFutures.size()));
}
} finally {
for (Closeable closeable : toClose) {
Closeables.closeQuietly(closeable);
}
}
}
Aggregations