Dan Burkert has posted comments on this change. ( 
http://gerrit.cloudera.org:8080/8312 )

Change subject: KUDU-2191 (6/n): Hive Metastore catalog manager integration
......................................................................


Patch Set 9:

(52 comments)

http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/hms/hms_client.cc
File src/kudu/hms/hms_client.cc:

http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/hms/hms_client.cc@193
PS8, Line 193:   // Also check that the HMS is configured to allow changing the 
type of
             :   // columns, which is required to support dropping columns.
> Could you elaborate on this a bit? It's not intuitive why it needs to be le
Added more elaboration.   tldr; hive is a real :dumpster_fire2:


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/hms/hms_client.cc@202
PS8, Line 202:   if (boost::iequals(disallow_incompatible_column_type_changes, 
"true")) {
> Hmm, is it really possible for the config's value to have a mixed case? Ask
Yes, I believe it's taken directly from the hive-site.xml so it's possible to 
have mixed case.  Line 185 is matching on a class name, and Java is case 
sensitive so it's not a valid configuration to screw that up.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/hms/hms_client.cc@218
PS8, Line 218: bool HmsClient::IsConnected() {
> Maybe add a bit of test coverage for this new method?
Done


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/hms/mini_hms.cc
File src/kudu/hms/mini_hms.cc:

http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/hms/mini_hms.cc@214
PS8, Line 214:     <value>jdbc:derby:$1/metadb;create=true</value>
> Why the change from 'memory' back to 'directory'?
I changed it originally in the hope that it would make things a bit faster if 
derby didn't have to write to disk.  It's being changed back because I've added 
tests that stop and restart the HMS, and if it's not on disk the HMS will come 
back with an empty DB.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/CMakeLists.txt
File src/kudu/integration-tests/CMakeLists.txt:

http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/CMakeLists.txt@87
PS8, Line 87: ADD_KUDU_TEST(master_hms-itest)
> Could you run this new test with KUDU_MEASURE_TEST_CPU_CONSUMPTION=1 (see r
Working on this.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/integration-tests/master-stress-test.cc
File src/kudu/integration-tests/master-stress-test.cc:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/integration-tests/master-stress-test.cc@343
PS9, Line 343:     return Substitute("default.table_$0", oid_generator_.Next());
> Not necessary yet?
No, it's not but it doesn't hurt anything so I figured I may as well.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc
File src/kudu/integration-tests/master_hms-itest.cc:

http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@122
PS8, Line 122:
> Could RETURN_NOT_OK instead.
Done


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@162
PS8, Line 162:   string table_name = Substitute("$0.$1", hms_database_name, 
hms_table_name);
             :
             :   // Attempt to create the table before the database is created.
             :   Status s = CreateTable(hms_database_name, hms_table
> Could be its own test (i.e. TestCreateTableWithoutDatabase)
I've tried to reduce the number of tests cases since spinning up an HMS is very 
expensive (~10 seconds), so having many short tests becomes really expensive.  
If you have an idea for how to fix that, or still feel like they should be 
split up I can go ahead, though.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@190
PS8, Line 190:
             :   // Shutdown the HMS and try to create a table.
             :   ASSERT_OK(StopHms());
             :
             :   s = CreateTable(hms_database_name, "foo");
             :   ASSERT_TRUE(s.IsNetworkError()) << s.ToString();
             :
             :   // Start the HMS and try again.
             :   ASSERT_OK(StartHms());
             :   ASSERT_OK(CreateTable(hms_database_name, "foo"));
> Could break out into a separate test since it only shares HMS database stat
Likewise.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@207
PS8, Line 207:
             :   // Create the database.
             :   hive::Database db;
             :   db.name = hms_database_name;
             :   ASSERT_OK(hms_client_->CreateDatabase(db));
> Every test does this; consider doing it in the test fixture.
Done


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@255
PS8, Line 255:   hive::EnvironmentContext env_ctx;
> Why is it necessary to provide the table's ID here, on L270, and on L371, b
This wasn't really necessary.  If you do provide the table ID when dropping a 
Kudu table, the Kudu HMS plugin will ensure the expected table ID matches the 
actual, but if you don't provide it the drop will still occur.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@268
PS8, Line 268:
             :   // Drop the HMS table entry, then c
> I was confused when I first read this, but now I think I understand: it's l
You may be reading too much into this.  This is just setting up a hypothetical 
scenario in which the Kudu/HMS catalogs may become unsychronized.  In this case 
we have a Kudu table, and an HMS table entry with the same name, but the HMS 
table entry isn't a Kudu table entry.  If we rename the Kudu table, it 
shouldn't attempt to rename the HMS entry (since it's not for the Kudu table 
being renamed).


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@285
PS8, Line 285:       hms_external_table_name,
> It was an external table created on L274

correct.

> but didn't it get renamed to hms_rename_table_name on L276?

No, because the HMS catalog entry wasn't a Kudu table entry matching the Kudu 
table being renamed, Kudu simply created a new HMS entry instead of altering 
the old one.  This is important to support so that Kudu can synchronize the HMS 
and Kudu catalogs by renaming Kudu tables to avoid collisions.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@309
PS8, Line 309:   hms_table.sd.cols.clear();
> After this step could you use CheckCatalogs (or a variant thereof) to asser
I've done a one-off check since I don't think we check anything similar 
elsewhere.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@339
PS8, Line 339:   s = table_alterer->DropColumn("int32_val")->Alter();
> Why does this fail? The non-Kudu HMS table entry has the same database and
No, one of the tenets of this integration is that we should _never_ modify a 
non-Kudu HMS entry.  If we did that it could really really screw things up.  
This situation can be 'resolved' either using a manual tool which will offer to 
delete the HMS entry, or by renaming the Kudu table to avoid the name collision.


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@354
PS8, Line 354:
> Maybe ensure it's gone from Kudu too, just to make sure that the HMS integr
Done


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@374
PS8, Line 374:   ASSERT_TRUE(s.IsNotFound()) << s.ToString();
> Likewise, make sure it was really dropped from Kudu.
Done


http://gerrit.cloudera.org:8080/#/c/8312/8/src/kudu/integration-tests/master_hms-itest.cc@384
PS8, Line 384:   NO_FATALS(CheckCatalogs(hms_database_name, hms_table_name));
> Check that it's gone from both Kudu and HMS?
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/CMakeLists.txt
File src/kudu/master/CMakeLists.txt:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/CMakeLists.txt@76
PS9, Line 76: ADD_KUDU_TEST(hms_catalog-test)
> Likewise, please assess the perf impact of this test and annotate it accord
Ack


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc
File src/kudu/master/catalog_manager.cc:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc@697
PS9, Line 697:     
CHECK_OK(HostPort::ParseStrings(FLAGS_hive_metastore_addresses,
> Since you're inside Init, may as well convert these CHECK_OKs to RETURN_NOT
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc@1548
PS9, Line 1548:   // Create the table in the HMS.
> Can you expand this comment a bit to explain why this should happen before
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc@1743
PS9, Line 1743:   // Drop the HMS table entry.
> As in Create, could you expand this to explain why this should happen here,
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc@1755
PS9, Line 1755:   auto abort_hms = MakeScopedCleanup([&] {
> What does it mean for a ScopedCleanup to return something? It's run on scop
It's a hack that allows using the RETURN_NOT_OK_LOG macro inside the lambda 
body.  The returned value is never actually used.  If you think this too clever 
I can write it out manually.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc@2254
PS9, Line 2254:   if (hms_catalog_ != nullptr && has_metadata_changes) {
> Add a comment explaining why we do this here and not after the catalog writ
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/catalog_manager.cc@2272
PS9, Line 2272:         RETURN_NOT_OK_LOG(SchemaFromPB(l.data().pb.schema(), 
&schema), WARNING,
> See above comment re: returning a value from a ScopedCleanup.
Same thing.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog-test.cc
File src/kudu/master/hms_catalog-test.cc:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog-test.cc@38
PS9, Line 38:
> Even though master_hms-test provides integration testing between CatalogMan
I agree.  Will work on that in future revision.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.h
File src/kudu/master/hms_catalog.h:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.h@61
PS9, Line 61:   // Create a new table entry in the HMS.
> Doc that this method fails if HMS is unreachable?
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.h@66
PS9, Line 66:   // Drops a table entry from the HMS, if it exists.
> Nit: it would be good to use the same tense when describing the functionali
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.h@91
PS9, Line 91:   Status Reconnect();
> Doc this?
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.h@103
PS9, Line 103:   static Status ParseTableName(const std::string& table,
> And this?
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.h@110
PS9, Line 110:   gscoped_ptr<ThreadPool> threadpool_;
> unique_ptr
This doesn't appear to be possible due to the API of ThreadPoolBuilder.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc
File src/kudu/master/hms_catalog.cc:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@52
PS9, Line 52: const int HmsCatalog::kNumRetries = 1;
> Do you think it would it be useful to convert this into an advanced gflag?
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@76
PS9, Line 76:       .set_min_threads(0)
> This is the default; it can be omitted.
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@77
PS9, Line 77:       .set_max_threads(1)
> Doc why capping at one thread is important.
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@95
PS9, Line 95:   return Execute([=] (hms::HmsClient* client) {
> Execute() waits for the provided functor to run, so why not capture variabl
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@162
PS9, Line 162:       if (!s.ok()) {
> I'm going to claim laziness and ask whether all of these edge cases are cov
I believe that all edge-cases are covered by a combination of master_hms-itest 
and hms_catalog-test.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@180
PS9, Line 180:       // Handle all other errors.
> Nit: not really "handling" per se; it's just that all other errors are fata
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@201
PS9, Line 201:  If
             :       // the original table object and the new table object 
match exactly then
             :       // we don't need to alter the table in the HMS.
> Does this short circuit make us vulnerable to a TOCTOU race, where we retur
Well you're right to expect there are TOCTOU races going on all over the place 
here, but this isn't one of them.  Since we're only accessing the HMS once 
during this short-circuit, there's no TOCTOU.

However in the non-short-circuited case there are absolutely TOCTOU issues 
where we can overwrite a table entry in the HMS which has been altered in the 
meantime; the way we mostly kind of solve this is to have the Kudu HMS plugin 
check that the Kudu table ID matches when altering a Kudu table entry.  That 
provides a defense against the master accidentally altering a non-Kudu table 
entry, which would be catastrophic.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@222
PS9, Line 222:   // TODO(Todd): wrapping this in a TRACE_EVENT scope and a 
LOG_IF_SLOW and such
> Nit:
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@238
PS9, Line 238:     // Since every task submitted to the (single thread) pool 
runs this, it's
             :     // essentially a single iteration of a run loop which 
handles HMS client
             :     // reconnection and task processing.
> Do you think the pool should have a min_thread count of 1 so that we don't
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@253
PS9, Line 253:     // network or IO fault (not an applicaiton level failure). 
The HMS client
> application
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@258
PS9, Line 258:     for (int i = 0; i <= kNumRetries; i++) {
> Seems like kNumRetries should depend at least somewhat on the number of HMS
Reconnect() handles connecting to the live HMS, if others are down.  Note that 
the HMS is active/active, it's not like our master where you have to go to a 
certain one.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@291
PS9, Line 291:       // A fatal error occurred. Tear down the connection, and 
try again. We
> Is it possible for reconnect to succeed, for the task to exhibit a fatal er
Yes, this is possible because we can't really guarantee that we bucket errors 
100% accurately into application (non-retriable) vs fatal (retriable).  To make 
sure this doesn't loop forever we break after kNumRetries, which defaults to 
the low value of 1.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@300
PS9, Line 300:     return callback(s);
> This passes in the last failure; should we instead pass in the first?
I can't think of a reason it would make a difference, unless you are suggesting 
they somehow be combined?


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@316
PS9, Line 316:     hms_client_ = hms::HmsClient(address, 
hms::HmsClientOptions());
> Nit: might consider making HmsClientOptions() the default value of the cons
This is here because we're missing a bunch of flags that set HmsClient options, 
like enabling kerberos etc.  Going to fix in next revision.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@324
PS9, Line 324:     LOG(WARNING) << "Failed to connect to Hive Metastore ("
             :                  << address.ToString() << "): " << s.ToString();
> More terse:
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@330
PS9, Line 330:   return s;
> If we can't connect to any of the HMSs, should we return the first failure?
I can't think of a reason it would make a difference.


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@368
PS9, Line 368:       return string();
> Hmm, so what would happen at runtime if we returned an empty string here? A
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@387
PS9, Line 387:   table->tableType = "MANAGED_TABLE";
> Should this constant be given a little more visibility? What's its signific
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/master/hms_catalog.cc@420
PS9, Line 420:         "When the Hive Metastore integration is enabled, Kudu 
table names must be a "
> Nit: as a convention we should start a status message with a lower case let
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/mini-cluster/external_mini_cluster-test.cc
File src/kudu/mini-cluster/external_mini_cluster-test.cc:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/mini-cluster/external_mini_cluster-test.cc@19
PS9, Line 19: #include <ostream>
> Revert?
Done


http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/util/net/net_util.cc
File src/kudu/util/net/net_util.cc:

http://gerrit.cloudera.org:8080/#/c/8312/9/src/kudu/util/net/net_util.cc@18
PS9, Line 18: #include <cstdint>
> Nit: this belongs in the next group of includes.
Done



--
To view, visit http://gerrit.cloudera.org:8080/8312
To unsubscribe, visit http://gerrit.cloudera.org:8080/settings

Gerrit-Project: kudu
Gerrit-Branch: master
Gerrit-MessageType: comment
Gerrit-Change-Id: I1b8f360408b05d6ac4f7359a8ac0dd889b196baf
Gerrit-Change-Number: 8312
Gerrit-PatchSet: 9
Gerrit-Owner: Dan Burkert <danburk...@apache.org>
Gerrit-Reviewer: Adar Dembo <a...@cloudera.com>
Gerrit-Reviewer: Dan Burkert <danburk...@apache.org>
Gerrit-Reviewer: Hao Hao <hao....@cloudera.com>
Gerrit-Reviewer: Kudu Jenkins
Gerrit-Reviewer: Tidy Bot
Gerrit-Reviewer: Todd Lipcon <t...@apache.org>
Gerrit-Comment-Date: Wed, 28 Mar 2018 23:23:45 +0000
Gerrit-HasComments: Yes

Reply via email to