This is an automated email from the ASF dual-hosted git repository.

ngangam pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 07464b1  HIVE-24135: Delete DB managed directory on drop db (Naveen 
Gangam)
07464b1 is described below

commit 07464b12ada011f13546b3d5d37276b76218416c
Author: Naveen Gangam <ngan...@cloudera.com>
AuthorDate: Sun Jun 6 10:53:04 2021 -0400

    HIVE-24135: Delete DB managed directory on drop db (Naveen Gangam)
---
 .../apache/hadoop/hive/metastore/HMSHandler.java   | 43 ++++++++++++++------
 .../hadoop/hive/metastore/TestHiveMetaStore.java   | 46 ++++++++++++++++++++++
 2 files changed, 76 insertions(+), 13 deletions(-)

diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
index f3eb3bc..9d659fd 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
@@ -1716,8 +1716,12 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
       }
       Path path = new Path(db.getLocationUri()).getParent();
       if (!wh.isWritable(path)) {
-        throw new MetaException("Database not dropped since " +
-            path + " is not writable by " +
+        throw new MetaException("Database not dropped since its external 
warehouse location " + path + " is not writable by " +
+            SecurityUtils.getUser());
+      }
+      path = wh.getDatabaseManagedPath(db).getParent();
+      if (!wh.isWritable(path)) {
+        throw new MetaException("Database not dropped since its managed 
warehouse location " + path + " is not writable by " +
             SecurityUtils.getUser());
       }
 
@@ -1845,23 +1849,36 @@ public class HMSHandler extends FacebookBase implements 
IHMSHandler {
         for (Path tablePath : tablePaths) {
           deleteTableData(tablePath, false, db);
         }
-        // Delete the data in the database
+        final Database dbFinal = db;
+        final Path path = (dbFinal.getManagedLocationUri() != null) ?
+            new Path(dbFinal.getManagedLocationUri()) : 
wh.getDatabaseManagedPath(dbFinal);
         try {
-          if (db.getManagedLocationUri() != null) {
-            wh.deleteDir(new Path(db.getManagedLocationUri()), true, db);
+
+          Boolean deleted = UserGroupInformation.getLoginUser().doAs(new 
PrivilegedExceptionAction<Boolean>() {
+            @Override public Boolean run() throws IOException, MetaException {
+              return wh.deleteDir(path, true, dbFinal);
+            }
+          });
+          if (!deleted) {
+            LOG.error("Failed to delete database's managed warehouse 
directory: " + path);
           }
         } catch (Exception e) {
-          LOG.error("Failed to delete database directory: " + 
db.getManagedLocationUri() +
-              " " + e.getMessage());
+          LOG.error("Failed to delete database's managed warehouse directory: 
" + path + " " + e.getMessage());
         }
-        // Delete the data in the database's location only if it is a legacy 
db path?
+
         try {
-          wh.deleteDir(new Path(db.getLocationUri()), true, db);
-        } catch (Exception e) {
-          LOG.error("Failed to delete database directory: " + 
db.getLocationUri() +
-              " " + e.getMessage());
+          Boolean deleted = UserGroupInformation.getCurrentUser().doAs(new 
PrivilegedExceptionAction<Boolean>() {
+            @Override public Boolean run() throws MetaException {
+              return wh.deleteDir(new Path(dbFinal.getLocationUri()), true, 
dbFinal);
+            }
+          });
+          if (!deleted) {
+            LOG.error("Failed to delete database external warehouse directory 
" + db.getLocationUri());
+          }
+        } catch (IOException | InterruptedException | 
UndeclaredThrowableException e) {
+          LOG.error("Failed to delete the database external warehouse 
directory: " + db.getLocationUri() + " " + e
+              .getMessage());
         }
-        // it is not a terrible thing even if the data is not deleted
       }
 
       if (!listeners.isEmpty()) {
diff --git 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
index f71d1fd..0399f2e 100644
--- 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
+++ 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
@@ -1278,6 +1278,52 @@ public abstract class TestHiveMetaStore {
 
 
   @Test
+  public void testDatabaseLocationOnDrop() throws Throwable {
+    try {
+      // clear up any existing databases
+      silentDropDatabase(TEST_DB1_NAME);
+
+      String dbLocation =
+          MetastoreConf.getVar(conf, ConfVars.WAREHOUSE_EXTERNAL) + 
"/testdb1.db";
+      String mgdLocation =
+          MetastoreConf.getVar(conf, ConfVars.WAREHOUSE) + "/testdb1.db";
+      new DatabaseBuilder()
+          .setName(TEST_DB1_NAME)
+          .setLocation(dbLocation)
+          .setManagedLocation(mgdLocation)
+          .create(client, conf);
+
+      Database db = client.getDatabase(TEST_DB1_NAME);
+
+      assertEquals("name of returned db is different from that of inserted db",
+          TEST_DB1_NAME, db.getName());
+      assertEquals("location of the returned db is different from that of 
inserted db",
+          warehouse.getDnsPath(new Path(dbLocation)).toString(), 
db.getLocationUri());
+      assertEquals("managed location of the returned db is different from that 
of inserted db",
+          warehouse.getDnsPath(new Path(mgdLocation)).toString(), 
db.getManagedLocationUri());
+
+      client.dropDatabase(TEST_DB1_NAME, true, false, true);
+
+      boolean objectNotExist = false;
+      try {
+        client.getDatabase(TEST_DB1_NAME);
+      } catch (NoSuchObjectException e) {
+        objectNotExist = true;
+      }
+      assertTrue("Database " + TEST_DB1_NAME + " exists ", objectNotExist);
+
+      FileSystem fs = FileSystem.get(new Path(dbLocation).toUri(), conf);
+      assertFalse("Database's location not deleted", fs.exists(new 
Path(dbLocation)));
+      fs = FileSystem.get(new Path(mgdLocation).toUri(), conf);
+      assertFalse("Database's managed location not deleted", fs.exists(new 
Path(mgdLocation)));
+    } catch (Throwable e) {
+      System.err.println(StringUtils.stringifyException(e));
+      System.err.println("testDatabaseLocationOnDrop() failed.");
+      throw e;
+    }
+  }
+
+  @Test
   public void testSimpleTypeApi() throws Exception {
     try {
       client.dropType(ColumnType.INT_TYPE_NAME);

Reply via email to