Skip to content

Commit 09ebdbd

Browse files
author
Venu Reddy
committed
HIVE-29520: Add configuration to enable/disable ACID functionality in Hive Metastore
1 parent 13f3208 commit 09ebdbd

8 files changed

Lines changed: 197 additions & 18 deletions

File tree

ql/src/java/org/apache/hadoop/hive/ql/txn/compactor/Initiator.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,10 @@ public void init(AtomicBoolean stop) throws Exception {
213213
checkInterval = conf.getTimeVar(HiveConf.ConfVars.HIVE_COMPACTOR_CHECK_INTERVAL, TimeUnit.MILLISECONDS);
214214
metricsEnabled = MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.METRICS_ENABLED) &&
215215
MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.METASTORE_ACIDMETRICS_EXT_ON);
216+
boolean isSupportAcid = MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.METASTORE_SUPPORT_ACID);
216217
optimizers = Arrays.stream(MetastoreConf.getTrimmedStringsVar(conf,
217218
MetastoreConf.ConfVars.COMPACTOR_INITIATOR_TABLE_OPTIMIZERS))
219+
.filter(e -> isSupportAcid || !e.equalsIgnoreCase(MetastoreConf.ACID_TABLE_OPTIMIZER_CLASS))
218220
.map(this::instantiateTableOptimizer).toList();
219221
}
220222

standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public class MetastoreConf {
7373
static final String HIVE_ALTER_HANDLE_CLASS =
7474
"org.apache.hadoop.hive.metastore.HiveAlterHandler";
7575
@VisibleForTesting
76-
static final String MATERIALZIATIONS_REBUILD_LOCK_CLEANER_TASK_CLASS =
76+
public static final String MATERIALZIATIONS_REBUILD_LOCK_CLEANER_TASK_CLASS =
7777
"org.apache.hadoop.hive.metastore.MaterializationsRebuildLockCleanerTask";
7878
@VisibleForTesting
7979
static final String METASTORE_TASK_THREAD_CLASS =
@@ -86,24 +86,24 @@ public class MetastoreConf {
8686
@VisibleForTesting
8787
static final String EVENT_CLEANER_TASK_CLASS =
8888
"org.apache.hadoop.hive.metastore.events.EventCleanerTask";
89-
static final String ACID_METRICS_TASK_CLASS =
89+
public static final String ACID_METRICS_TASK_CLASS =
9090
"org.apache.hadoop.hive.metastore.metrics.AcidMetricService";
91-
static final String ACID_METRICS_LOGGER_CLASS =
91+
public static final String ACID_METRICS_LOGGER_CLASS =
9292
"org.apache.hadoop.hive.metastore.metrics.AcidMetricLogger";
9393
@VisibleForTesting
9494
static final String METASTORE_DELEGATION_MANAGER_CLASS =
9595
"org.apache.hadoop.hive.metastore.security.MetastoreDelegationTokenManager";
9696
@VisibleForTesting
97-
static final String ACID_HOUSEKEEPER_SERVICE_CLASS =
97+
public static final String ACID_HOUSEKEEPER_SERVICE_CLASS =
9898
"org.apache.hadoop.hive.metastore.txn.service.AcidHouseKeeperService";
9999
@VisibleForTesting
100100
static final String COMPACTION_HOUSEKEEPER_SERVICE_CLASS =
101101
"org.apache.hadoop.hive.metastore.txn.service.CompactionHouseKeeperService";
102102
@VisibleForTesting
103-
static final String ACID_TXN_CLEANER_SERVICE_CLASS =
103+
public static final String ACID_TXN_CLEANER_SERVICE_CLASS =
104104
"org.apache.hadoop.hive.metastore.txn.service.AcidTxnCleanerService";
105105
@VisibleForTesting
106-
static final String ACID_OPEN_TXNS_COUNTER_SERVICE_CLASS =
106+
public static final String ACID_OPEN_TXNS_COUNTER_SERVICE_CLASS =
107107
"org.apache.hadoop.hive.metastore.txn.service.AcidOpenTxnsCounterService";
108108
@VisibleForTesting
109109
static final String ICEBERG_TABLE_SNAPSHOT_EXPIRY_SERVICE_CLASS =
@@ -112,6 +112,10 @@ public class MetastoreConf {
112112
"metastore.authentication.ldap.userMembershipKey";
113113
public static final String METASTORE_RETRYING_HANDLER_CLASS =
114114
"org.apache.hadoop.hive.metastore.RetryingHMSHandler";
115+
public static final String ACID_TABLE_OPTIMIZER_CLASS =
116+
"org.apache.hadoop.hive.ql.txn.compactor.AcidTableOptimizer";
117+
public static final String ICEBERG_TABLE_OPTIMIZER_CLASS =
118+
"org.apache.iceberg.mr.hive.compaction.IcebergTableOptimizer";
115119

116120
private static final Map<String, ConfVars> metaConfs = new HashMap<>();
117121
private static volatile URL hiveSiteURL = null;
@@ -662,8 +666,7 @@ public enum ConfVars {
662666
"Enable table caching in the initiator. Currently the cache is cleaned after each cycle."),
663667
COMPACTOR_INITIATOR_TABLE_OPTIMIZERS("compactor.table.optimizers",
664668
"hive.compactor.table.optimizers",
665-
"org.apache.hadoop.hive.ql.txn.compactor.AcidTableOptimizer," +
666-
"org.apache.iceberg.mr.hive.compaction.IcebergTableOptimizer",
669+
ACID_TABLE_OPTIMIZER_CLASS + "," + ICEBERG_TABLE_OPTIMIZER_CLASS,
667670
"Comma separated list of table optimizers executed by compaction Initiator."),
668671
COMPACTOR_WORKER_THREADS("metastore.compactor.worker.threads",
669672
"hive.compactor.worker.threads", 0,
@@ -1987,6 +1990,8 @@ public enum ConfVars {
19871990
"The maximum non-native tables allowed per table type during collecting the summary."),
19881991
METADATA_SUMMARY_NONNATIVE_THREADS("hive.metatool.summary.nonnative.threads", "hive.metatool.summary.nonnative.threads", 20,
19891992
"Number of threads to be allocated for MetaToolTaskMetadataSummary for collecting the non-native table's summary."),
1993+
METASTORE_SUPPORT_ACID("metastore.support.acid", "hive.metastore.support.acid", true,
1994+
"Whether to support acid functionality in Hive metastore server."),
19901995

19911996
// These are all values that we put here just for testing
19921997
STR_TEST_ENTRY("test.str", "hive.test.str", "defaultval", "comment"),

standalone-metastore/metastore-server/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@
385385
<artifactId>junit</artifactId>
386386
<scope>test</scope>
387387
</dependency>
388+
<dependency>
389+
<groupId>org.junit.jupiter</groupId>
390+
<artifactId>junit-jupiter</artifactId>
391+
<scope>test</scope>
392+
</dependency>
388393
<dependency>
389394
<groupId>org.apache.directory.server</groupId>
390395
<artifactId>apacheds-server-integ</artifactId>

standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,15 @@ public static void startMetaStore(int port, HadoopThriftAuthBridge bridge,
700700
boolean directSqlEnabled = MetastoreConf.getBoolVar(conf, ConfVars.TRY_DIRECT_SQL);
701701
LOG.info("Direct SQL optimization = {}", directSqlEnabled);
702702

703+
if (!MetastoreConf.getBoolVar(conf, ConfVars.METASTORE_SUPPORT_ACID)) {
704+
if (MetastoreConf.getBoolVar(conf, MetastoreConf.ConfVars.COMPACTOR_CLEANER_ON)) {
705+
LOG.warn("Compactor Cleaner is turned On. But, automatic compaction cleaner will not be triggered " +
706+
"when the {} property is set to false. Hence, Cleaner is turned Off",
707+
ConfVars.METASTORE_SUPPORT_ACID.getHiveName());
708+
MetastoreConf.setBoolVar(conf, MetastoreConf.ConfVars.COMPACTOR_CLEANER_ON,false);
709+
}
710+
}
711+
703712
if (startMetaStoreThreads) {
704713
Lock metaStoreThreadsLock = new ReentrantLock();
705714
Condition startCondition = metaStoreThreadsLock.newCondition();

standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/MetastoreDefaultTransformer.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,26 @@ private static final Path getDefaultPath(IHMSHandler hmsHandler, Database db, St
615615

616616
}
617617

618+
private void transformToExternalIfAcidNotSupported(Table table) throws MetaException {
619+
Map<String, String> params = table.getParameters();
620+
boolean isSupportAcid = MetastoreConf.getBoolVar(hmsHandler.getConf(),
621+
ConfVars.METASTORE_SUPPORT_ACID);
622+
if (!isSupportAcid) {
623+
if (Boolean.parseBoolean(params.get(TABLE_IS_TRANSACTIONAL))) {
624+
throw new MetaException("ACID tables are not permitted when the "
625+
+ ConfVars.METASTORE_SUPPORT_ACID.getHiveName() + " property is set to false");
626+
}
627+
if (TableType.MANAGED_TABLE.name().equals(table.getTableType())) {
628+
table.setTableType(TableType.EXTERNAL_TABLE.toString());
629+
}
630+
if (TableType.EXTERNAL_TABLE.name().equals(table.getTableType())) {
631+
params.put(HiveMetaHook.EXTERNAL, "TRUE");
632+
}
633+
params.remove(TABLE_IS_TRANSACTIONAL);
634+
params.remove(TABLE_TRANSACTIONAL_PROPERTIES);
635+
}
636+
}
637+
618638
@Override
619639
public Table transformCreateTable(Table table, List<String> processorCapabilities, String processorId) throws MetaException {
620640
if (!defaultCatalog.equalsIgnoreCase(table.getCatName())) {
@@ -629,6 +649,7 @@ public Table transformCreateTable(Table table, List<String> processorCapabilitie
629649
if (params == null) {
630650
params = new HashMap<>();
631651
}
652+
transformToExternalIfAcidNotSupported(newTable);
632653
String tableType = newTable.getTableType();
633654
String txnal = null;
634655
String txn_properties = null;
@@ -682,8 +703,7 @@ public Table transformCreateTable(Table table, List<String> processorCapabilitie
682703
throw new MetaException("Processor has no capabilities, cannot create an ACID table.");
683704
}
684705

685-
686-
newTable = validateTablePaths(table);
706+
validateTablePaths(newTable);
687707
if (isInsertAcid) { // MICRO_MANAGED Tables
688708
if (processorCapabilities.contains(HIVEMANAGEDINSERTWRITE)) {
689709
LOG.debug("Processor has required capabilities to be able to create INSERT-only tables");
@@ -704,7 +724,7 @@ public Table transformCreateTable(Table table, List<String> processorCapabilitie
704724
}
705725
} else if (TableType.EXTERNAL_TABLE.name().equals(tableType)) {
706726
LOG.debug("Table to be created is of type " + tableType);
707-
newTable = validateTablePaths(table);
727+
validateTablePaths(newTable);
708728
}
709729
LOG.info("Transformer returning table:" + newTable.toString());
710730
return newTable;
@@ -744,7 +764,7 @@ public Table transformAlterTable(Table oldTable, Table newTable, List<String> pr
744764
LOG.info("Starting translation for Alter table for processor " + processorId + " with " + processorCapabilities
745765
+ " on table " + newTable.getTableName());
746766

747-
767+
transformToExternalIfAcidNotSupported(newTable);
748768
if (tableLocationChanged(oldTable, newTable)) {
749769
validateTablePaths(newTable);
750770
}

standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/leader/HouseKeepingTasks.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
import com.cronutils.utils.VisibleForTesting;
2222
import com.google.common.util.concurrent.ThreadFactoryBuilder;
23-
23+
import com.google.common.collect.ImmutableSet;
2424
import org.apache.hadoop.conf.Configuration;
2525
import org.apache.hadoop.hive.metastore.HiveMetaStore;
2626
import org.apache.hadoop.hive.metastore.MetastoreTaskThread;
@@ -69,6 +69,12 @@ public List<MetastoreTaskThread> getRemoteOnlyTasks() throws Exception {
6969

7070
Collection<String> taskNames =
7171
MetastoreConf.getStringCollection(configuration, MetastoreConf.ConfVars.TASK_THREADS_REMOTE_ONLY);
72+
if (!MetastoreConf.getBoolVar(configuration, MetastoreConf.ConfVars.METASTORE_SUPPORT_ACID)) {
73+
taskNames.removeAll(ImmutableSet.of(MetastoreConf.ACID_OPEN_TXNS_COUNTER_SERVICE_CLASS,
74+
MetastoreConf.ACID_HOUSEKEEPER_SERVICE_CLASS,
75+
MetastoreConf.ACID_TXN_CLEANER_SERVICE_CLASS,
76+
MetastoreConf.MATERIALZIATIONS_REBUILD_LOCK_CLEANER_TASK_CLASS));
77+
}
7278
for (String taskName : taskNames) {
7379
if (CompactionHouseKeeperService.class.getName().equals(taskName) && !isCompactorEnabled) {
7480
continue;
@@ -85,6 +91,10 @@ public List<MetastoreTaskThread> getAlwaysTasks() throws Exception {
8591
List<MetastoreTaskThread> alwaysTasks = new ArrayList<>();
8692
Collection<String> taskNames =
8793
MetastoreConf.getStringCollection(configuration, MetastoreConf.ConfVars.TASK_THREADS_ALWAYS);
94+
if (!MetastoreConf.getBoolVar(configuration, MetastoreConf.ConfVars.METASTORE_SUPPORT_ACID)) {
95+
taskNames.removeAll(ImmutableSet.of(MetastoreConf.ACID_METRICS_TASK_CLASS,
96+
MetastoreConf.ACID_METRICS_LOGGER_CLASS));
97+
}
8898
for (String taskName : taskNames) {
8999
MetastoreTaskThread task =
90100
JavaUtils.newInstance(JavaUtils.getClass(taskName, MetastoreTaskThread.class));

standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/txn/service/CompactionHouseKeeperService.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,14 @@ public CompactionHouseKeeperService() {
3636

3737
@Override
3838
protected void initTasks(){
39-
tasks = ImmutableMap.<FailableRunnable<MetaException>, String>builder()
40-
.put(txnHandler::removeDuplicateCompletedTxnComponents,
41-
"Cleaning duplicate COMPLETED_TXN_COMPONENTS entries")
42-
.put(txnHandler::purgeCompactionHistory, "Cleaning obsolete compaction history entries")
43-
.build();
39+
ImmutableMap.Builder<FailableRunnable<MetaException>, String> taskBuilder =
40+
ImmutableMap.<FailableRunnable<MetaException>, String>builder()
41+
.put(txnHandler::purgeCompactionHistory, "Cleaning obsolete compaction history entries");
42+
if (MetastoreConf.getBoolVar(getConf(), MetastoreConf.ConfVars.METASTORE_SUPPORT_ACID)) {
43+
taskBuilder.put(txnHandler::removeDuplicateCompletedTxnComponents,
44+
"Cleaning duplicate COMPLETED_TXN_COMPONENTS entries");
45+
}
46+
tasks = taskBuilder.build();
4447
}
4548

4649
@Override
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hive.metastore;
19+
20+
import org.apache.hadoop.conf.Configuration;
21+
import org.apache.hadoop.hive.metastore.annotation.MetastoreUnitTest;
22+
import org.apache.hadoop.hive.metastore.api.MetaException;
23+
import org.apache.hadoop.hive.metastore.api.Table;
24+
import org.apache.hadoop.hive.metastore.client.builder.DatabaseBuilder;
25+
import org.apache.hadoop.hive.metastore.client.builder.TableBuilder;
26+
import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
27+
import org.apache.hadoop.hive.metastore.conf.MetastoreConf.ConfVars;
28+
import org.apache.hadoop.util.StringUtils;
29+
import org.apache.thrift.TException;
30+
import org.junit.After;
31+
import org.junit.AfterClass;
32+
import org.junit.BeforeClass;
33+
import org.junit.Test;
34+
import org.junit.experimental.categories.Category;
35+
import org.junit.jupiter.api.Assertions;
36+
37+
import static org.apache.hadoop.hive.metastore.api.hive_metastoreConstants.TABLE_IS_TRANSACTIONAL;
38+
39+
/**
40+
* Tests to verify metastore without acid support
41+
*/
42+
@Category(MetastoreUnitTest.class)
43+
public class TestNoAcidSupport {
44+
private static Configuration conf;
45+
private static HiveMetaStoreClient client;
46+
private static final String dbName = "TestNoAcidSupport";
47+
private String tableName = "t1";
48+
49+
@BeforeClass
50+
public static void beforeTests() throws Exception {
51+
conf = MetastoreConf.newMetastoreConf();
52+
MetastoreConf.setBoolVar(conf, ConfVars.METASTORE_SUPPORT_ACID, false);
53+
client = new HiveMetaStoreClient(conf);
54+
client.dropDatabase(dbName, true, true, true);
55+
new DatabaseBuilder().setName(dbName).create(client, conf);
56+
}
57+
58+
@AfterClass
59+
public static void afterTests() throws Exception {
60+
try {
61+
client.dropDatabase(dbName, true, true, true);
62+
client.close();
63+
} catch (Throwable e) {
64+
System.err.println(StringUtils.stringifyException(e));
65+
throw e;
66+
}
67+
}
68+
69+
@After
70+
public void afterTest() throws TException {
71+
client.dropTable(dbName, tableName);
72+
}
73+
74+
@Test
75+
public void testCreateAcidTable() {
76+
Exception exception = Assertions.assertThrows(MetaException.class, () -> {
77+
new TableBuilder().setDbName(dbName).setTableName(tableName)
78+
.addCol("i", ColumnType.INT_TYPE_NAME)
79+
.setType(TableType.MANAGED_TABLE.name())
80+
.addTableParam(TABLE_IS_TRANSACTIONAL, "true")
81+
.create(client, conf);
82+
});
83+
Assertions.assertTrue(exception.getMessage().contains("ACID tables are not permitted when the " +
84+
ConfVars.METASTORE_SUPPORT_ACID.getHiveName() + " property is set to false"));
85+
}
86+
87+
@Test
88+
public void testCreateManagedTableChangeToExternal() throws Exception {
89+
new TableBuilder().setDbName(dbName).setTableName(tableName)
90+
.addCol("i", ColumnType.INT_TYPE_NAME)
91+
.setType(TableType.MANAGED_TABLE.name())
92+
.create(client, conf);
93+
Table t1 = client.getTable(dbName, tableName);
94+
Assertions.assertEquals(TableType.EXTERNAL_TABLE.name(), t1.getTableType());
95+
Assertions.assertTrue(Boolean.parseBoolean(t1.getParameters().get(HiveMetaHook.EXTERNAL)));
96+
}
97+
98+
@Test
99+
public void testCreateExternalTable() throws Exception {
100+
new TableBuilder().setDbName(dbName).setTableName(tableName)
101+
.addCol("i", ColumnType.INT_TYPE_NAME)
102+
.setType(TableType.EXTERNAL_TABLE.name())
103+
.create(client, conf);
104+
Table t1 = client.getTable(dbName, tableName);
105+
Assertions.assertEquals( TableType.EXTERNAL_TABLE.name(), t1.getTableType());
106+
Assertions.assertTrue(Boolean.parseBoolean(t1.getParameters().get(HiveMetaHook.EXTERNAL)));
107+
}
108+
109+
@Test
110+
public void testAlterToManagedTable() throws Exception {
111+
new TableBuilder().setDbName(dbName).setTableName(tableName)
112+
.addCol("i", ColumnType.INT_TYPE_NAME)
113+
.setType(TableType.EXTERNAL_TABLE.name())
114+
.create(client, conf);
115+
Table t1 = client.getTable(dbName, tableName);
116+
Assertions.assertEquals( TableType.EXTERNAL_TABLE.name(), t1.getTableType());
117+
t1.setTableType(TableType.MANAGED_TABLE.name());
118+
t1.getParameters().put(TABLE_IS_TRANSACTIONAL, "true");
119+
Exception exception = Assertions.assertThrows(MetaException.class, () -> {
120+
client.alter_table(dbName, tableName, t1);
121+
});
122+
Assertions.assertTrue(exception.getMessage()
123+
.contains("ACID tables are not permitted when the \"hive.metastore.support.acid\" property is set to false"));
124+
}
125+
}

0 commit comments

Comments
 (0)