KUDU-2191 (6/n): Fixups to the C++ HMS client

These are changes necessary for subsequent patches in the series, but
they are easier to review in isolation.

Change-Id: I86a8d984e67fe6b4c004725828b4296476c2389e
Reviewed-on: http://gerrit.cloudera.org:8080/9861
Reviewed-by: Adar Dembo <a...@cloudera.com>
Tested-by: Kudu Jenkins


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/fff4185e
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/fff4185e
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/fff4185e

Branch: refs/heads/master
Commit: fff4185e0f88954c67841a13b0924db4eab4c761
Parents: 4db748f
Author: Dan Burkert <danburk...@apache.org>
Authored: Wed Mar 28 16:35:45 2018 -0700
Committer: Dan Burkert <danburk...@apache.org>
Committed: Mon Apr 2 21:39:49 2018 +0000

----------------------------------------------------------------------
 .../hive/metastore/TestKuduMetastorePlugin.java |  3 +-
 src/kudu/hms/hms_client-test.cc                 | 15 +++++--
 src/kudu/hms/hms_client.cc                      | 44 ++++++++++++++++++--
 src/kudu/hms/hms_client.h                       | 18 +++++++-
 src/kudu/hms/mini_hms.cc                        | 10 ++++-
 5 files changed, 79 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/fff4185e/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
----------------------------------------------------------------------
diff --git 
a/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
 
b/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
index 8eb6927..1abcd6a 100644
--- 
a/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
+++ 
b/java/kudu-hive/src/test/java/org/apache/kudu/hive/metastore/TestKuduMetastorePlugin.java
@@ -28,6 +28,7 @@ import org.apache.hadoop.hive.metastore.HiveMetaStoreClient;
 import org.apache.hadoop.hive.metastore.MetaStoreUtils;
 import org.apache.hadoop.hive.metastore.MockPartitionExpressionForMetastore;
 import org.apache.hadoop.hive.metastore.PartitionExpressionProxy;
+import org.apache.hadoop.hive.metastore.TableType;
 import org.apache.hadoop.hive.metastore.api.EnvironmentContext;
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.metastore.api.SerDeInfo;
@@ -77,7 +78,7 @@ public class TestKuduMetastorePlugin {
     Table table = new Table();
     table.setDbName("default");
     table.setTableName(name);
-    table.setTableType("MANAGED_TABLE");
+    table.setTableType(TableType.MANAGED_TABLE.toString());
     table.putToParameters(hive_metastoreConstants.META_TABLE_STORAGE,
                           KuduMetastorePlugin.KUDU_STORAGE_HANDLER);
     table.putToParameters(KuduMetastorePlugin.KUDU_TABLE_ID_KEY,

http://git-wip-us.apache.org/repos/asf/kudu/blob/fff4185e/src/kudu/hms/hms_client-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/hms/hms_client-test.cc b/src/kudu/hms/hms_client-test.cc
index 87601eb..a4a6ffe 100644
--- a/src/kudu/hms/hms_client-test.cc
+++ b/src/kudu/hms/hms_client-test.cc
@@ -17,11 +17,16 @@
 
 #include "kudu/hms/hms_client.h"
 
+#include <algorithm> // IWYU pragma: keep
 #include <cstdint>
+#include <map> // IWYU pragma: keep
+#include <memory> // IWYU pragma: keep
 #include <string>
+#include <type_traits> // IWYU pragma: keep
 #include <utility>
 #include <vector>
 
+#include <boost/none_t.hpp> // IWYU pragma: keep
 #include <boost/optional/optional.hpp>
 #include <glog/stl_logging.h> // IWYU pragma: keep
 #include <gtest/gtest.h>
@@ -59,7 +64,7 @@ class HmsClientTest : public KuduTest,
     hive::Table table;
     table.dbName = database_name;
     table.tableName = table_name;
-    table.tableType = "MANAGED_TABLE";
+    table.tableType = HmsClient::kManagedTable;
 
     table.__set_parameters({
         make_pair(HmsClient::kKuduTableIdKey, table_id),
@@ -122,7 +127,9 @@ TEST_P(HmsClientTest, TestHmsOperations) {
   ASSERT_OK(hms.Start());
 
   HmsClient client(hms.address(), hms_client_opts);
+  ASSERT_FALSE(client.IsConnected());
   ASSERT_OK(client.Start());
+  ASSERT_TRUE(client.IsConnected());
 
   // Create a database.
   string database_name = "my_db";
@@ -161,7 +168,7 @@ TEST_P(HmsClientTest, TestHmsOperations) {
   EXPECT_EQ(table_id, my_table.parameters[HmsClient::kKuduTableIdKey]);
   EXPECT_EQ(HmsClient::kKuduStorageHandler,
             
my_table.parameters[hive::g_hive_metastore_constants.META_TABLE_STORAGE]);
-  EXPECT_EQ("MANAGED_TABLE", my_table.tableType);
+  EXPECT_EQ(HmsClient::kManagedTable, my_table.tableType);
 
   string new_table_name = "my_altered_table";
 
@@ -186,7 +193,7 @@ TEST_P(HmsClientTest, TestHmsOperations) {
   EXPECT_EQ(table_id, renamed_table.parameters[HmsClient::kKuduTableIdKey]);
   EXPECT_EQ(HmsClient::kKuduStorageHandler,
             
renamed_table.parameters[hive::g_hive_metastore_constants.META_TABLE_STORAGE]);
-  EXPECT_EQ("MANAGED_TABLE", renamed_table.tableType);
+  EXPECT_EQ(HmsClient::kManagedTable, renamed_table.tableType);
 
   // Create a table with an uppercase name.
   string uppercase_table_name = "my_UPPERCASE_Table";
@@ -279,7 +286,7 @@ TEST_P(HmsClientTest, TestLargeObjects) {
   hive::Table table;
   table.dbName = database_name;
   table.tableName = table_name;
-  table.tableType = "MANAGED_TABLE";
+  table.tableType = HmsClient::kManagedTable;
   hive::FieldSchema partition_key;
   partition_key.name = "c1";
   partition_key.type = "int";

http://git-wip-us.apache.org/repos/asf/kudu/blob/fff4185e/src/kudu/hms/hms_client.cc
----------------------------------------------------------------------
diff --git a/src/kudu/hms/hms_client.cc b/src/kudu/hms/hms_client.cc
index 6e2f4c6..1e889ad 100644
--- a/src/kudu/hms/hms_client.cc
+++ b/src/kudu/hms/hms_client.cc
@@ -25,6 +25,7 @@
 #include <utility>
 #include <vector>
 
+#include <boost/algorithm/string/predicate.hpp>
 #include <glog/logging.h>
 #include <thrift/Thrift.h>
 #include <thrift/protocol/TBinaryProtocol.h>
@@ -65,6 +66,7 @@ using std::make_shared;
 using std::shared_ptr;
 using std::string;
 using std::vector;
+using strings::Substitute;
 
 namespace kudu {
 namespace hms {
@@ -110,11 +112,17 @@ const char* const HmsClient::kKuduStorageHandler = 
"org.apache.kudu.hive.KuduSto
 
 const char* const HmsClient::kTransactionalEventListeners =
   "hive.metastore.transactional.event.listeners";
+const char* const HmsClient::kDisallowIncompatibleColTypeChanges =
+  "hive.metastore.disallow.incompatible.col.type.changes";
 const char* const HmsClient::kDbNotificationListener =
   "org.apache.hive.hcatalog.listener.DbNotificationListener";
 const char* const HmsClient::kKuduMetastorePlugin =
   "org.apache.kudu.hive.metastore.KuduMetastorePlugin";
 
+const char* const HmsClient::kManagedTable = "MANAGED_TABLE";
+
+const uint16_t HmsClient::kDefaultHmsPort = 9083;
+
 const int kSlowExecutionWarningThresholdMs = 1000;
 
 namespace {
@@ -166,7 +174,8 @@ Status HmsClient::Start() {
   // the required event listeners.
   string event_listener_config;
   HMS_RET_NOT_OK(client_.get_config_value(event_listener_config, 
kTransactionalEventListeners, ""),
-                 "failed to get Hive MetaStore transactional event listener 
configuration");
+                 Substitute("failed to get Hive MetaStore $0 configuration",
+                            kTransactionalEventListeners));
 
   // Parse the set of listeners from the configuration string.
   vector<string> listeners = strings::Split(event_listener_config, ",", 
strings::SkipWhitespace());
@@ -177,12 +186,35 @@ Status HmsClient::Start() {
   for (const auto& required_listener : { kDbNotificationListener, 
kKuduMetastorePlugin }) {
     if (std::find(listeners.begin(), listeners.end(), required_listener) == 
listeners.end()) {
       return Status::IllegalState(
-          strings::Substitute("Hive Metastore configuration is missing 
required "
-                              "transactional event listener ($0): $1",
-                              kTransactionalEventListeners, 
required_listener));
+          Substitute("Hive Metastore configuration is missing required "
+                     "transactional event listener ($0): $1",
+                     kTransactionalEventListeners, required_listener));
     }
   }
 
+  // Also check that the HMS is configured to allow changing the type of
+  // columns, which is required to support dropping columns. File-based Hive
+  // tables handle columns by offset, and removing a column simply shifts all
+  // remaining columns down by one. The actual data is not changed, but instead
+  // reassigned to the next column. If the HMS is configured to check column
+  // type changes it will validate that the existing data matches the shifted
+  // column layout. This is overly strict for Kudu, since we handle DDL
+  // operations properly.
+  //
+  // See 
org.apache.hadoop.hive.metastore.MetaStoreUtils.throwExceptionIfIncompatibleColTypeChange.
+  string disallow_incompatible_column_type_changes;
+  
HMS_RET_NOT_OK(client_.get_config_value(disallow_incompatible_column_type_changes,
+                                          kDisallowIncompatibleColTypeChanges,
+                                          "false"),
+                 Substitute("failed to get Hive MetaStore $0 configuration",
+                            kDisallowIncompatibleColTypeChanges));
+
+  if (boost::iequals(disallow_incompatible_column_type_changes, "true")) {
+    return Status::IllegalState(Substitute(
+          "Hive Metastore configuration is invalid: $0 must be set to false",
+          kDisallowIncompatibleColTypeChanges));
+  }
+
   return Status::OK();
 }
 
@@ -193,6 +225,10 @@ Status HmsClient::Stop() {
   return Status::OK();
 }
 
+bool HmsClient::IsConnected() {
+  return client_.getInputProtocol()->getTransport()->isOpen();
+}
+
 Status HmsClient::CreateDatabase(const hive::Database& database) {
   SCOPED_LOG_SLOW_EXECUTION(WARNING, kSlowExecutionWarningThresholdMs, "create 
HMS database");
   HMS_RET_NOT_OK(client_.create_database(database), "failed to create Hive 
MetaStore database");

http://git-wip-us.apache.org/repos/asf/kudu/blob/fff4185e/src/kudu/hms/hms_client.h
----------------------------------------------------------------------
diff --git a/src/kudu/hms/hms_client.h b/src/kudu/hms/hms_client.h
index 21f18f9..cafa417 100644
--- a/src/kudu/hms/hms_client.h
+++ b/src/kudu/hms/hms_client.h
@@ -23,11 +23,18 @@
 
 #include "kudu/gutil/port.h"
 #include "kudu/hms/ThriftHiveMetastore.h"
-#include "kudu/hms/hive_metastore_types.h"
 #include "kudu/util/monotime.h"
 #include "kudu/util/slice.h"
 #include "kudu/util/status.h"
 
+namespace hive {
+class Database;
+class EnvironmentContext;
+class NotificationEvent; // IWYU pragma: keep
+class Partition; // IWYU pragma: keep
+class Table;
+}
+
 namespace kudu {
 
 class HostPort;
@@ -85,9 +92,15 @@ class HmsClient {
   static const char* const kKuduStorageHandler;
 
   static const char* const kTransactionalEventListeners;
+  static const char* const kDisallowIncompatibleColTypeChanges;
   static const char* const kDbNotificationListener;
   static const char* const kKuduMetastorePlugin;
 
+  // See org.apache.hadoop.hive.metastore.TableType.
+  static const char* const kManagedTable;
+
+  static const uint16_t kDefaultHmsPort;
+
   // Create an HmsClient connection to the proided HMS Thrift RPC address.
   //
   // The individual timeouts may be set to enforce per-operation
@@ -109,6 +122,9 @@ class HmsClient {
   // This is optional; if not called the destructor will stop the client.
   Status Stop() WARN_UNUSED_RESULT;
 
+  // Returns 'true' if the client is connected to the remote server.
+  bool IsConnected() WARN_UNUSED_RESULT;
+
   // Creates a new database in the HMS.
   //
   // If a database already exists by the same name an AlreadyPresent status is

http://git-wip-us.apache.org/repos/asf/kudu/blob/fff4185e/src/kudu/hms/mini_hms.cc
----------------------------------------------------------------------
diff --git a/src/kudu/hms/mini_hms.cc b/src/kudu/hms/mini_hms.cc
index 078341d..f571b6c 100644
--- a/src/kudu/hms/mini_hms.cc
+++ b/src/kudu/hms/mini_hms.cc
@@ -181,6 +181,9 @@ Status MiniHms::CreateHiveSite(const string& tmp_dir) const 
{
   // - hive.metastore.kerberos.keytab.file
   // - hive.metastore.kerberos.principal
   //     Configures the HMS to use Kerberos for its Thrift RPC interface.
+  //
+  // - hive.metastore.disallow.incompatible.col.type.changes
+  //     Configures the HMS to allow altering and dropping columns.
   static const string kFileTemplate = R"(
 <configuration>
   <property>
@@ -208,7 +211,7 @@ Status MiniHms::CreateHiveSite(const string& tmp_dir) const 
{
 
   <property>
     <name>javax.jdo.option.ConnectionURL</name>
-    <value>jdbc:derby:memory:$1/metadb;create=true</value>
+    <value>jdbc:derby:$1/metadb;create=true</value>
   </property>
 
   <property>
@@ -235,6 +238,11 @@ Status MiniHms::CreateHiveSite(const string& tmp_dir) 
const {
     <name>hadoop.rpc.protection</name>
     <value>$5</value>
   </property>
+
+  <property>
+    <name>hive.metastore.disallow.incompatible.col.type.changes</name>
+    <value>false</value>
+  </property>
 </configuration>
   )";
 

Reply via email to