IMPALA-5028: Lock table in /catalog_objects endpoint. There was a missing lock acquisition before Table.toThrift() in the code used for implementing the /catalog_objects endpoint in the WebUI.
Testing: - Added a regression test in test_web_pages.py Change-Id: I3ad4ce286b8cc169f29b8ddfa215f8949b1c11ff Reviewed-on: http://gerrit.cloudera.org:8080/6296 Reviewed-by: Alex Behm <[email protected]> Tested-by: Impala Public Jenkins Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/3b7cecee Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/3b7cecee Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/3b7cecee Branch: refs/heads/master Commit: 3b7ceceed29f2f34539a0def4ddb71b34e74d2b7 Parents: 408d0ae Author: Alex Behm <[email protected]> Authored: Tue Mar 7 10:34:37 2017 -0800 Committer: Impala Public Jenkins <[email protected]> Committed: Wed Mar 8 22:09:53 2017 +0000 ---------------------------------------------------------------------- .../java/org/apache/impala/catalog/Catalog.java | 11 ++++++--- tests/webserver/test_web_pages.py | 24 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3b7cecee/fe/src/main/java/org/apache/impala/catalog/Catalog.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/org/apache/impala/catalog/Catalog.java b/fe/src/main/java/org/apache/impala/catalog/Catalog.java index 5a3fc61..994aa37 100644 --- a/fe/src/main/java/org/apache/impala/catalog/Catalog.java +++ b/fe/src/main/java/org/apache/impala/catalog/Catalog.java @@ -449,9 +449,14 @@ public abstract class Catalog { throw new CatalogException("Table not found: " + objectDesc.getTable().getTbl_name()); } - result.setType(table.getCatalogObjectType()); - result.setCatalog_version(table.getCatalogVersion()); - result.setTable(table.toThrift()); + table.getLock().lock(); + try { + result.setType(table.getCatalogObjectType()); + result.setCatalog_version(table.getCatalogVersion()); + result.setTable(table.toThrift()); + } finally { + table.getLock().unlock(); + } break; } case FUNCTION: { http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/3b7cecee/tests/webserver/test_web_pages.py ---------------------------------------------------------------------- diff --git a/tests/webserver/test_web_pages.py b/tests/webserver/test_web_pages.py index 4604e22..4a2d872 100644 --- a/tests/webserver/test_web_pages.py +++ b/tests/webserver/test_web_pages.py @@ -26,6 +26,8 @@ class TestWebPage(ImpalaTestSuite): RESET_JAVA_LOGLEVEL_URL = "http://localhost:{0}/reset_java_loglevel" SET_GLOG_LOGLEVEL_URL = "http://localhost:{0}/set_glog_level" RESET_GLOG_LOGLEVEL_URL = "http://localhost:{0}/reset_glog_level" + CATALOG_URL = "http://localhost:{0}/catalog" + CATALOG_OBJECT_URL = "http://localhost:{0}/catalog_object" # log4j changes do not apply to the statestore since it doesn't # have an embedded JVM. So we make two sets of ports to test the # log level endpoints, one without the statestore port and the @@ -130,3 +132,25 @@ class TestWebPage(ImpalaTestSuite): # Try a non-existent endpoint on log_level URL. bad_loglevel_url = self.SET_GLOG_LOGLEVEL_URL + "?badurl=foo" self.get_and_check_status(bad_loglevel_url, without_ss=False) + + def test_catalog(self): + """Tests the /catalog and /catalog_object endpoints.""" + self.get_and_check_status(self.CATALOG_URL, "functional", without_ss=True) + self.get_and_check_status(self.CATALOG_URL, "alltypes", without_ss=True) + # IMPALA-5028: Test toThrift() of a partitioned table via the WebUI code path. + self.__test_catalog_object("functional", "alltypes") + self.__test_catalog_object("functional_parquet", "alltypes") + self.__test_catalog_object("functional", "alltypesnopart") + self.__test_catalog_object("functional_kudu", "alltypes") + + def __test_catalog_object(self, db_name, tbl_name): + """Tests the /catalog_object endpoint for the given db/table. Runs + against an unloaded as well as a loaded table.""" + self.client.execute("invalidate metadata %s.%s" % (db_name, tbl_name)) + self.get_and_check_status(self.CATALOG_OBJECT_URL + + "?object_type=TABLE&object_name=%s.%s" % (db_name, tbl_name), tbl_name, + without_ss=True) + self.client.execute("select count(*) from %s.%s" % (db_name, tbl_name)) + self.get_and_check_status(self.CATALOG_OBJECT_URL + + "?object_type=TABLE&object_name=%s.%s" % (db_name, tbl_name), tbl_name, + without_ss=True)
