You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gobblin.apache.org by hu...@apache.org on 2020/05/07 21:35:22 UTC

[incubator-gobblin] branch master updated: [GOBBLIN-1142] Hive Distcp support filter on partitioned or snapshot tables

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

hutran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-gobblin.git


The following commit(s) were added to refs/heads/master by this push:
     new 4d76f45  [GOBBLIN-1142] Hive Distcp support filter on partitioned or snapshot tables
4d76f45 is described below

commit 4d76f4544e936af1ec1871143c95d86e25c239b0
Author: zhchen <zh...@linkedin.com>
AuthorDate: Thu May 7 14:35:15 2020 -0700

    [GOBBLIN-1142] Hive Distcp support filter on partitioned or snapshot tables
    
    Closes #2979 from zxcware/hive-distcp
---
 .../management/copy/hive/HiveDatasetFinder.java    | 15 +++++
 .../copy/predicates/TableTypeFilter.java           | 65 ++++++++++++++++++++++
 .../copy/hive/HiveDatasetFinderTest.java           | 48 ++++++++++++++++
 3 files changed, 128 insertions(+)

diff --git a/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinder.java b/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinder.java
index 98134b8..e04783f 100644
--- a/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinder.java
+++ b/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinder.java
@@ -62,6 +62,7 @@ import org.apache.gobblin.metrics.event.EventSubmitter;
 import org.apache.gobblin.metrics.event.sla.SlaEventSubmitter;
 import org.apache.gobblin.util.AutoReturnableObject;
 import org.apache.gobblin.util.ConfigUtils;
+import org.apache.gobblin.util.reflection.GobblinConstructorUtils;
 
 
 /**
@@ -76,6 +77,7 @@ public class HiveDatasetFinder implements IterableDatasetFinder<HiveDataset> {
   public static final String DB_KEY = HIVE_DATASET_PREFIX + ".database";
   public static final String TABLE_PATTERN_KEY = HIVE_DATASET_PREFIX + ".table.pattern";
   public static final String DEFAULT_TABLE_PATTERN = "*";
+  public static final String TABLE_FILTER = HIVE_DATASET_PREFIX + ".tableFilter";
 
   /*
    * By setting the prefix, only config keys with this prefix will be used to build a HiveDataset.
@@ -112,6 +114,7 @@ public class HiveDatasetFinder implements IterableDatasetFinder<HiveDataset> {
 
   protected Optional<String> configStoreUri;
   protected final Function<Table, String> configStoreDatasetUriBuilder;
+  protected final Optional<Predicate<Table>> tableFilter;
 
   protected final String datasetConfigPrefix;
   protected final ConfigClient configClient;
@@ -181,6 +184,14 @@ public class HiveDatasetFinder implements IterableDatasetFinder<HiveDataset> {
       throw new RuntimeException(e);
     }
     this.jobConfig = ConfigUtils.propertiesToConfig(properties);
+
+    String tableFilterPredicate = properties.getProperty(TABLE_FILTER);
+    if (StringUtils.isNotEmpty(tableFilterPredicate)) {
+      this.tableFilter = Optional.of((Predicate<Table>)GobblinConstructorUtils.invokeConstructor(
+          Predicate.class, tableFilterPredicate, properties));
+    } else {
+      this.tableFilter = Optional.absent();
+    }
   }
 
   protected static HiveMetastoreClientPool createClientPool(Properties properties) throws IOException {
@@ -249,6 +260,10 @@ public class HiveDatasetFinder implements IterableDatasetFinder<HiveDataset> {
 
           try (AutoReturnableObject<IMetaStoreClient> client = HiveDatasetFinder.this.clientPool.getClient()) {
             Table table = client.get().getTable(dbAndTable.getDb(), dbAndTable.getTable());
+            if (tableFilter.isPresent() && !tableFilter.get().apply(table)) {
+              continue;
+            }
+
             Config datasetConfig = getDatasetConfig(table);
             if (ConfigUtils.getBoolean(datasetConfig, HIVE_DATASET_IS_BLACKLISTED_KEY, DEFAULT_HIVE_DATASET_IS_BLACKLISTED_KEY)) {
               continue;
diff --git a/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/predicates/TableTypeFilter.java b/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/predicates/TableTypeFilter.java
new file mode 100644
index 0000000..b73610c
--- /dev/null
+++ b/gobblin-data-management/src/main/java/org/apache/gobblin/data/management/copy/predicates/TableTypeFilter.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.data.management.copy.predicates;
+
+import java.util.Properties;
+
+import org.apache.hadoop.hive.metastore.api.Table;
+
+import com.google.common.base.Predicate;
+
+import javax.annotation.Nullable;
+
+
+/**
+ * A predicate to check if a hive {@link Table} is of a certain type in {@link TABLE_TYPE}
+ *
+ * <p> Example usage: {@link org.apache.gobblin.data.management.copy.hive.HiveDatasetFinder#TABLE_FILTER}
+ */
+public class TableTypeFilter implements Predicate<Table> {
+
+  public static final String FILTER_TYPE = "tableTypeFilter.type";
+
+  private enum TABLE_TYPE {
+    SNAPSHOT,
+    PARTITIONED
+  }
+
+  private final TABLE_TYPE tableType;
+
+  public TableTypeFilter(Properties props) {
+    tableType = TABLE_TYPE.valueOf(
+        props.getProperty(FILTER_TYPE, TABLE_TYPE.SNAPSHOT.name()).toUpperCase());
+  }
+
+  @Override
+  public boolean apply(@Nullable Table input) {
+    if (input == null) {
+      return false;
+    }
+
+    switch (tableType) {
+      case SNAPSHOT:
+        return input.getPartitionKeys() == null || input.getPartitionKeys().size() == 0;
+      case PARTITIONED:
+        return input.getPartitionKeys() != null && input.getPartitionKeys().size() > 0;
+      default:
+        throw new UnsupportedOperationException("Invalid type: " + tableType);
+    }
+  }
+}
diff --git a/gobblin-data-management/src/test/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinderTest.java b/gobblin-data-management/src/test/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinderTest.java
index 70ef3d1..0794520 100644
--- a/gobblin-data-management/src/test/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinderTest.java
+++ b/gobblin-data-management/src/test/java/org/apache/gobblin/data/management/copy/hive/HiveDatasetFinderTest.java
@@ -24,6 +24,7 @@ import java.util.Properties;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.hive.metastore.IMetaStoreClient;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
 import org.apache.hadoop.hive.metastore.api.Table;
 import org.mockito.Mockito;
@@ -36,6 +37,7 @@ import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
 import com.typesafe.config.Config;
 
+import org.apache.gobblin.data.management.copy.predicates.TableTypeFilter;
 import org.apache.gobblin.hive.HiveMetastoreClientPool;
 import org.apache.gobblin.util.AutoReturnableObject;
 
@@ -61,6 +63,36 @@ public class HiveDatasetFinderTest {
   }
 
   @Test
+  public void testTableFilter() throws Exception {
+    List<HiveDatasetFinder.DbAndTable> dbAndTables = Lists.newArrayList();
+    dbAndTables.add(new HiveDatasetFinder.DbAndTable("db1", "table1"));
+    dbAndTables.add(new HiveDatasetFinder.DbAndTable("db1", "table2"));
+    dbAndTables.add(new DatePartitionTable("db1", "table3"));
+    dbAndTables.add(new DatePartitionTable("db1", "table4"));
+    HiveMetastoreClientPool pool = getTestPool(dbAndTables);
+
+    Properties properties = new Properties();
+    properties.put(HiveDatasetFinder.HIVE_DATASET_PREFIX + "." + WhitelistBlacklist.WHITELIST, "");
+
+    // Test snapshot only
+    properties.put(HiveDatasetFinder.TABLE_FILTER, TableTypeFilter.class.getName());
+    properties.put(TableTypeFilter.FILTER_TYPE, "snapshot");
+    HiveDatasetFinder finder = new TestHiveDatasetFinder(FileSystem.getLocal(new Configuration()), properties, pool);
+    List<HiveDataset> datasets = Lists.newArrayList(finder.getDatasetsIterator());
+    Assert.assertEquals(datasets.size(), 2);
+    Assert.assertTrue(datasets.stream().anyMatch(dataset -> dataset.getDbAndTable().toString().equals("db1.table1")));
+    Assert.assertTrue(datasets.stream().anyMatch(dataset -> dataset.getDbAndTable().toString().equals("db1.table2")));
+
+    // Test partitioned table only
+    properties.put(TableTypeFilter.FILTER_TYPE, "partitioned");
+    finder = new TestHiveDatasetFinder(FileSystem.getLocal(new Configuration()), properties, pool);
+    datasets = Lists.newArrayList(finder.getDatasetsIterator());
+    Assert.assertEquals(datasets.size(), 2);
+    Assert.assertTrue(datasets.stream().anyMatch(dataset -> dataset.getDbAndTable().toString().equals("db1.table3")));
+    Assert.assertTrue(datasets.stream().anyMatch(dataset -> dataset.getDbAndTable().toString().equals("db1.table4")));
+  }
+
+  @Test
   public void testException() throws Exception {
 
     List<HiveDatasetFinder.DbAndTable> dbAndTables = Lists.newArrayList();
@@ -201,6 +233,9 @@ public class HiveDatasetFinderTest {
       Table table = new Table();
       table.setDbName(dbAndTable.getDb());
       table.setTableName(dbAndTable.getTable());
+      if (dbAndTable instanceof DatePartitionTable) {
+        table.setPartitionKeys(((DatePartitionTable) dbAndTable).getPartitionKeys());
+      }
       StorageDescriptor sd = new StorageDescriptor();
       sd.setLocation("/tmp/test");
       table.setSd(sd);
@@ -235,4 +270,17 @@ public class HiveDatasetFinderTest {
     }
   }
 
+  private static class DatePartitionTable extends HiveDatasetFinder.DbAndTable {
+
+    static final FieldSchema DATE_PARTITION_KEY = new FieldSchema("datepartition", "String", "");
+
+    public DatePartitionTable(String db, String table) {
+      super(db, table);
+    }
+
+    public List<FieldSchema> getPartitionKeys() {
+      return Lists.newArrayList(DATE_PARTITION_KEY);
+    }
+  }
+
 }