Repository: hadoop
Updated Branches:
  refs/heads/HADOOP-13345 a1b47db40 -> e3f20027f


HADOOP-13960. Initialize DynamoDBMetadataStore without associated 
S3AFileSystem. (Mingliang Liu via Lei Xu)


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/e3f20027
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/e3f20027
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/e3f20027

Branch: refs/heads/HADOOP-13345
Commit: e3f20027fef53c9a9f30764021af5725d900da07
Parents: a1b47db
Author: Lei Xu <l...@apache.org>
Authored: Mon Jan 9 16:48:57 2017 +0800
Committer: Lei Xu <l...@apache.org>
Committed: Mon Jan 9 16:48:57 2017 +0800

----------------------------------------------------------------------
 .../fs/s3a/s3guard/DynamoDBClientFactory.java   | 47 ++++++++++++---
 .../fs/s3a/s3guard/DynamoDBMetadataStore.java   | 61 +++++++++-----------
 .../PathMetadataDynamoDBTranslation.java        |  4 +-
 .../hadoop/fs/s3native/S3xLoginHelper.java      |  4 ++
 .../s3a/s3guard/TestDynamoDBMetadataStore.java  | 21 ++++++-
 5 files changed, 93 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/e3f20027/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBClientFactory.java
----------------------------------------------------------------------
diff --git 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBClientFactory.java
 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBClientFactory.java
index 1cbf464..05b96dc 100644
--- 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBClientFactory.java
+++ 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBClientFactory.java
@@ -57,6 +57,18 @@ interface DynamoDBClientFactory extends Configurable {
       throws IOException;
 
   /**
+   * To create a DynamoDB client against the given endpoint in config.
+   *
+   * This DynamoDB client does not relate to any S3 buckets so the region is
+   * determined implicitly by the endpoint.
+   *
+   * @return a new DynamoDB client
+   * @throws IOException if any IO error happens
+   */
+  AmazonDynamoDBClient createDynamoDBClient(Configuration conf)
+      throws IOException;
+
+  /**
    * The default implementation for creating an AmazonDynamoDBClient.
    */
   class DefaultDynamoDBClientFactory extends Configured
@@ -87,16 +99,37 @@ interface DynamoDBClientFactory extends Configurable {
       ddb.withRegion(region.toAWSRegion());
       final String endPoint = conf.getTrimmed(S3GUARD_DDB_ENDPOINT_KEY);
       if (StringUtils.isNotEmpty(endPoint)) {
-        try {
-          ddb.withEndpoint(endPoint);
-        } catch (IllegalArgumentException e) {
-          final String msg = "Incorrect DynamoDB endpoint: "  + endPoint;
-          LOG.error(msg, e);
-          throw new IllegalArgumentException(msg, e);
-        }
+        setEndPoint(ddb, endPoint);
       }
       return ddb;
     }
+
+    @Override
+    public AmazonDynamoDBClient createDynamoDBClient(Configuration conf)
+        throws IOException {
+      final AWSCredentialsProvider credentials =
+          createAWSCredentialProviderSet(null, conf, null);
+      final ClientConfiguration awsConf =
+          DefaultS3ClientFactory.createAwsConf(conf);
+      AmazonDynamoDBClient ddb = new AmazonDynamoDBClient(credentials, 
awsConf);
+      setEndPoint(ddb, conf.getTrimmed(S3GUARD_DDB_ENDPOINT_KEY));
+
+      return ddb;
+    }
+
+    /**
+     * Helper method to set the endpoint for an AmazonDynamoDBClient.
+     */
+    private static void setEndPoint(AmazonDynamoDBClient ddb, String endPoint) 
{
+      assert ddb != null;
+      try {
+        ddb.withEndpoint(endPoint);
+      } catch (IllegalArgumentException e) {
+        final String msg = "Incorrect DynamoDB endpoint: " + endPoint;
+        LOG.error(msg, e);
+        throw new IllegalArgumentException(msg, e);
+      }
+    }
   }
 
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e3f20027/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBMetadataStore.java
----------------------------------------------------------------------
diff --git 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBMetadataStore.java
 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBMetadataStore.java
index 1c19625..45ecaff 100644
--- 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBMetadataStore.java
+++ 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/DynamoDBMetadataStore.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.fs.s3a.s3guard;
 
 import java.io.IOException;
 import java.io.InterruptedIOException;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -45,10 +46,10 @@ import 
com.amazonaws.services.dynamodbv2.model.ResourceInUseException;
 import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException;
 
 import com.amazonaws.services.dynamodbv2.model.WriteRequest;
-import com.amazonaws.services.s3.AmazonS3;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -59,7 +60,7 @@ import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.s3a.S3AFileStatus;
 import org.apache.hadoop.fs.s3a.S3AFileSystem;
-import org.apache.hadoop.fs.s3a.S3ClientFactory;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.util.ReflectionUtils;
 
 import static org.apache.hadoop.fs.s3a.s3guard.S3Guard.*;
@@ -158,14 +159,15 @@ public class DynamoDBMetadataStore implements 
MetadataStore {
   private String region;
   private Table table;
   private String tableName;
-  private S3AFileSystem s3afs;
+  private Configuration conf;
+  private URI s3Uri;
   private String username;
 
   @Override
   public void initialize(FileSystem fs) throws IOException {
     Preconditions.checkArgument(fs instanceof S3AFileSystem,
         "DynamoDBMetadataStore only supports S3A filesystem.");
-    s3afs = (S3AFileSystem) fs;
+    final S3AFileSystem s3afs = (S3AFileSystem) fs;
     final String bucket = s3afs.getBucket();
     try {
       region = s3afs.getAmazonS3Client().getBucketLocation(bucket);
@@ -175,8 +177,8 @@ public class DynamoDBMetadataStore implements MetadataStore 
{
     }
 
     username = s3afs.getUsername();
-
-    final Configuration conf = s3afs.getConf();
+    conf = s3afs.getConf();
+    s3Uri = s3afs.getUri();
     Class<? extends DynamoDBClientFactory> cls = conf.getClass(
         S3GUARD_DDB_CLIENT_FACTORY_IMPL,
         S3GUARD_DDB_CLIENT_FACTORY_IMPL_DEFAULT,
@@ -197,36 +199,25 @@ public class DynamoDBMetadataStore implements 
MetadataStore {
   /**
    * Performs one-time initialization of the metadata store via configuration.
    *
-   * This initialization depends on the configuration object to get DEFAULT
-   * S3AFileSystem URI, AWS credentials, S3ClientFactory implementation class,
-   * DynamoDBFactor implementation class, DynamoDB endpoints, metadata table
-   * names etc. Generally you should use {@link #initialize(FileSystem)} 
instead
-   * given an initialized S3 file system.
+   * This initialization depends on the configuration object to get AWS
+   * credentials, DynamoDBFactory implementation class, DynamoDB endpoints,
+   * DynamoDB table names etc. After initialization, this metadata store does
+   * not explicitly relate to any S3 bucket, which be nonexistent.
+   *
+   * This is used to operate the metadata store directly beyond the scope of 
the
+   * S3AFileSystem integration, e.g. command line tools. Generally you should
+   * use {@link #initialize(FileSystem)} if given an initialized S3 file 
system.
    *
    * @see #initialize(FileSystem)
    * @throws IOException if there is an error
    */
-  void initialize(Configuration conf) throws IOException {
-    final FileSystem defautFs = FileSystem.get(conf);
-    Preconditions.checkArgument(defautFs instanceof S3AFileSystem,
-        "DynamoDBMetadataStore only supports S3A filesystem.");
-    s3afs = (S3AFileSystem) defautFs;
-
+  void initialize(Configuration config) throws IOException {
+    conf = config;
     // use the bucket as the DynamoDB table name if not specified in config
     tableName = conf.getTrimmed(S3GUARD_DDB_TABLE_NAME_KEY);
-    Preconditions.checkNotNull(tableName, "No DynamoDB table name 
configured!");
-
-    final Class<? extends S3ClientFactory> clsS3 = conf.getClass(
-        S3_CLIENT_FACTORY_IMPL,
-        DEFAULT_S3_CLIENT_FACTORY_IMPL,
-        S3ClientFactory.class);
-    final S3ClientFactory factory = ReflectionUtils.newInstance(clsS3, conf);
-    AmazonS3 s3 = factory.createS3Client(s3afs.getUri(), s3afs.getUri());
-    try {
-      region = s3.getBucketLocation(tableName);
-    } catch (AmazonClientException e) {
-      throw new IOException("Can not find location for bucket " + tableName, 
e);
-    }
+    Preconditions.checkArgument(!StringUtils.isEmpty(tableName),
+        "No DynamoDB table name configured!");
+    username = UserGroupInformation.getCurrentUser().getShortUserName();
 
     Class<? extends DynamoDBClientFactory> clsDdb = conf.getClass(
         S3GUARD_DDB_CLIENT_FACTORY_IMPL,
@@ -235,8 +226,9 @@ public class DynamoDBMetadataStore implements MetadataStore 
{
     LOG.debug("Creating dynamo DB client {}", clsDdb);
     AmazonDynamoDBClient dynamoDBClient =
         ReflectionUtils.newInstance(clsDdb, conf)
-            .createDynamoDBClient(s3afs.getUri(), region);
+            .createDynamoDBClient(conf);
     dynamoDB = new DynamoDB(dynamoDBClient);
+    region = dynamoDBClient.getEndpointPrefix();
 
     createTable();
   }
@@ -293,7 +285,7 @@ public class DynamoDBMetadataStore implements MetadataStore 
{
             .withPrimaryKey(pathToKey(path))
             .withConsistentRead(true); // strictly consistent read
         final Item item = table.getItem(spec);
-        meta = itemToPathMetadata(s3afs.getUri(), item, username);
+        meta = itemToPathMetadata(s3Uri, item, username);
         LOG.debug("Get from table {} in region {} returning for {}: {}",
             tableName, region, path, meta);
       }
@@ -330,7 +322,7 @@ public class DynamoDBMetadataStore implements MetadataStore 
{
 
       final List<PathMetadata> metas = new ArrayList<>();
       for (Item item : items) {
-        metas.add(itemToPathMetadata(s3afs.getUri(), item, username));
+        metas.add(itemToPathMetadata(s3Uri, item, username));
       }
       LOG.trace("Listing table {} in region {} for {} returning {}",
           tableName, region, path, metas);
@@ -527,7 +519,6 @@ public class DynamoDBMetadataStore implements MetadataStore 
{
    */
   @VisibleForTesting
   void createTable() throws IOException {
-    final Configuration conf = s3afs.getConf();
     final ProvisionedThroughput capacity = new ProvisionedThroughput(
         conf.getLong(S3GUARD_DDB_TABLE_CAPACITY_READ_KEY,
             S3GUARD_DDB_TABLE_CAPACITY_READ_DEFAULT),
@@ -602,7 +593,7 @@ public class DynamoDBMetadataStore implements MetadataStore 
{
     Preconditions.checkNotNull(path);
     Preconditions.checkArgument(path.isAbsolute(),
         "Path '" + path + "' is not absolute!");
-    return path.makeQualified(s3afs.getUri(), null);
+    return s3Uri == null ? path : path.makeQualified(s3Uri, null);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e3f20027/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/PathMetadataDynamoDBTranslation.java
----------------------------------------------------------------------
diff --git 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/PathMetadataDynamoDBTranslation.java
 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/PathMetadataDynamoDBTranslation.java
index 15b23d2..ad89cf9 100644
--- 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/PathMetadataDynamoDBTranslation.java
+++ 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/s3guard/PathMetadataDynamoDBTranslation.java
@@ -101,7 +101,9 @@ final class PathMetadataDynamoDBTranslation {
       return null;
     }
 
-    path = path.makeQualified(s3aUri, null);
+    if (s3aUri != null) {
+      path = path.makeQualified(s3aUri, null);
+    }
     boolean isDir = item.hasAttribute(IS_DIR) && item.getBoolean(IS_DIR);
     final FileStatus fileStatus;
     if (isDir) {

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e3f20027/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3native/S3xLoginHelper.java
----------------------------------------------------------------------
diff --git 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3native/S3xLoginHelper.java
 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3native/S3xLoginHelper.java
index 97ece37..9fb4138 100644
--- 
a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3native/S3xLoginHelper.java
+++ 
b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3native/S3xLoginHelper.java
@@ -98,6 +98,10 @@ public final class S3xLoginHelper {
    * @return a login tuple, possibly empty.
    */
   public static Login extractLoginDetails(URI name) {
+    if (name == null) {
+      return Login.EMPTY;
+    }
+
     try {
       String authority = name.getAuthority();
       if (authority == null) {

http://git-wip-us.apache.org/repos/asf/hadoop/blob/e3f20027/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/s3guard/TestDynamoDBMetadataStore.java
----------------------------------------------------------------------
diff --git 
a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/s3guard/TestDynamoDBMetadataStore.java
 
b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/s3guard/TestDynamoDBMetadataStore.java
index 72144b7..f88137b 100644
--- 
a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/s3guard/TestDynamoDBMetadataStore.java
+++ 
b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/s3guard/TestDynamoDBMetadataStore.java
@@ -213,8 +213,27 @@ public class TestDynamoDBMetadataStore extends 
MetadataStoreTestBase {
   @Test
   public void testInitializeWithConfiguration() throws IOException {
     final String tableName = "testInitializeWithConfiguration";
-    final Configuration conf = createContract().getFileSystem().getConf();
+    final Configuration conf = new Configuration();
+    String a = conf.get(Constants.S3GUARD_DDB_ENDPOINT_KEY);
+    try {
+      DynamoDBMetadataStore ddbms = new DynamoDBMetadataStore();
+      ddbms.initialize(conf);
+      fail("Should have failed because the table name is not set!");
+    } catch (IllegalArgumentException ignored) {
+    }
+    // config table name
     conf.set(Constants.S3GUARD_DDB_TABLE_NAME_KEY, tableName);
+    try {
+      DynamoDBMetadataStore ddbms = new DynamoDBMetadataStore();
+      ddbms.initialize(conf);
+      fail("Should have failed because as the endpoint is not set!");
+    } catch (IllegalArgumentException ignored) {
+    }
+    // config endpoint
+    conf.set(Constants.S3GUARD_DDB_ENDPOINT_KEY, ddbEndpoint);
+    // config credentials
+    conf.set(Constants.ACCESS_KEY, "dummy-access-key");
+    conf.set(Constants.SECRET_KEY, "dummy-secret-key");
     try (DynamoDBMetadataStore ddbms = new DynamoDBMetadataStore()) {
       ddbms.initialize(conf);
       verifyTableInitialized(tableName);


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to