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)

Reply via email to