You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by li...@apache.org on 2017/05/19 18:52:02 UTC

hadoop git commit: HADOOP-14432. S3A copyFromLocalFile to be robust, tested. Contributed by Steve Loughran

Repository: hadoop
Updated Branches:
  refs/heads/trunk 19482e0d0 -> 6672810ee


HADOOP-14432. S3A copyFromLocalFile to be robust, tested. Contributed by Steve Loughran


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

Branch: refs/heads/trunk
Commit: 6672810eeac1c94fd764aaf2a709ace9d4b5aa76
Parents: 19482e0
Author: Mingliang Liu <li...@apache.org>
Authored: Fri May 19 11:51:43 2017 -0700
Committer: Mingliang Liu <li...@apache.org>
Committed: Fri May 19 11:51:43 2017 -0700

----------------------------------------------------------------------
 .../org/apache/hadoop/fs/s3a/S3AFileSystem.java |  29 +++-
 .../fs/s3a/ITestS3ACopyFromLocalFile.java       | 153 +++++++++++++++++++
 2 files changed, 175 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/6672810e/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java
----------------------------------------------------------------------
diff --git a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java
index d53fd13..25f2671 100644
--- a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java
+++ b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java
@@ -1736,28 +1736,43 @@ public class S3AFileSystem extends FileSystem {
    * delSrc indicates if the source should be removed
    * @param delSrc whether to delete the src
    * @param overwrite whether to overwrite an existing file
-   * @param src path
+   * @param src Source path: must be on local filesystem
    * @param dst path
    * @throws IOException IO problem
    * @throws FileAlreadyExistsException the destination file exists and
-   * overwrite==false
+   * overwrite==false, or if the destination is a directory.
+   * @throws FileNotFoundException if the source file does not exit
    * @throws AmazonClientException failure in the AWS SDK
+   * @throws IllegalArgumentException if the source path is not on the local FS
    */
   private void innerCopyFromLocalFile(boolean delSrc, boolean overwrite,
       Path src, Path dst)
       throws IOException, FileAlreadyExistsException, AmazonClientException {
     incrementStatistic(INVOCATION_COPY_FROM_LOCAL_FILE);
-    final String key = pathToKey(dst);
-
-    if (!overwrite && exists(dst)) {
-      throw new FileAlreadyExistsException(dst + " already exists");
-    }
     LOG.debug("Copying local file from {} to {}", src, dst);
 
     // Since we have a local file, we don't need to stream into a temporary file
     LocalFileSystem local = getLocal(getConf());
     File srcfile = local.pathToFile(src);
+    if (!srcfile.exists()) {
+      throw new FileNotFoundException("No file: " + src);
+    }
+    if (!srcfile.isFile()) {
+      throw new FileNotFoundException("Not a file: " + src);
+    }
 
+    try {
+      FileStatus status = getFileStatus(dst);
+      if (!status.isFile()) {
+        throw new FileAlreadyExistsException(dst + " exists and is not a file");
+      }
+      if (!overwrite) {
+        throw new FileAlreadyExistsException(dst + " already exists");
+      }
+    } catch (FileNotFoundException e) {
+      // no destination, all is well
+    }
+    final String key = pathToKey(dst);
     final ObjectMetadata om = newObjectMetadata(srcfile.length());
     PutObjectRequest putObjectRequest = newPutObjectRequest(key, om, srcfile);
     Upload up = putObject(putObjectRequest);

http://git-wip-us.apache.org/repos/asf/hadoop/blob/6672810e/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3ACopyFromLocalFile.java
----------------------------------------------------------------------
diff --git a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3ACopyFromLocalFile.java b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3ACopyFromLocalFile.java
new file mode 100644
index 0000000..71776ac
--- /dev/null
+++ b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3ACopyFromLocalFile.java
@@ -0,0 +1,153 @@
+/*
+ * 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.hadoop.fs.s3a;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import org.junit.Test;
+
+import org.apache.commons.io.Charsets;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.fs.FileAlreadyExistsException;
+import org.apache.hadoop.fs.Path;
+
+import static org.apache.hadoop.test.LambdaTestUtils.intercept;
+
+/**
+ * Test {@link S3AFileSystem#copyFromLocalFile(boolean, boolean, Path, Path)}.
+ */
+public class ITestS3ACopyFromLocalFile extends AbstractS3ATestBase {
+  private static final Charset ASCII = Charsets.US_ASCII;
+
+  private File file;
+
+  @Override
+  public void teardown() throws Exception {
+    super.teardown();
+    if (file != null) {
+      file.delete();
+    }
+  }
+
+  @Test
+  public void testCopyEmptyFile() throws Throwable {
+    file = File.createTempFile("test", ".txt");
+    Path dest = upload(file, true);
+    assertPathExists("uploaded file", dest);
+  }
+
+  @Test
+  public void testCopyFile() throws Throwable {
+    String message = "hello";
+    file = createTempFile(message);
+    Path dest = upload(file, true);
+    assertPathExists("uploaded file not found", dest);
+    S3AFileSystem fs = getFileSystem();
+    S3AFileStatus status = fs.getFileStatus(dest);
+    assertEquals("File length of " + status,
+        message.getBytes(ASCII).length, status.getLen());
+    assertFileTextEquals(dest, message);
+  }
+
+  public void assertFileTextEquals(Path path, String expected)
+      throws IOException {
+    assertEquals("Wrong data in " + path,
+        expected, IOUtils.toString(getFileSystem().open(path), ASCII));
+  }
+
+  @Test
+  public void testCopyFileNoOverwrite() throws Throwable {
+    file = createTempFile("hello");
+    Path dest = upload(file, true);
+    intercept(FileAlreadyExistsException.class,
+        () -> upload(file, false));
+  }
+
+  @Test
+  public void testCopyFileOverwrite() throws Throwable {
+    file = createTempFile("hello");
+    Path dest = upload(file, true);
+    String updated = "updated";
+    FileUtils.write(file, updated, ASCII);
+    upload(file, true);
+    assertFileTextEquals(dest, updated);
+  }
+
+  @Test
+  public void testCopyFileNoOverwriteDirectory() throws Throwable {
+    file = createTempFile("hello");
+    Path dest = upload(file, true);
+    S3AFileSystem fs = getFileSystem();
+    fs.delete(dest, false);
+    fs.mkdirs(dest);
+    intercept(FileAlreadyExistsException.class,
+        () -> upload(file, true));
+  }
+
+  @Test
+  public void testCopyMissingFile() throws Throwable {
+    file = File.createTempFile("test", ".txt");
+    file.delete();
+    // first upload to create
+    intercept(FileNotFoundException.class, "No file",
+        () -> upload(file, true));
+  }
+
+  @Test
+  public void testCopyDirectoryFile() throws Throwable {
+    file = File.createTempFile("test", ".txt");
+    // first upload to create
+    intercept(FileNotFoundException.class, "Not a file",
+        () -> upload(file.getParentFile(), true));
+  }
+
+
+  @Test
+  public void testLocalFilesOnly() throws Throwable {
+    Path dst = path("testLocalFilesOnly");
+    intercept(IllegalArgumentException.class,
+        () -> {
+          getFileSystem().copyFromLocalFile(false, true, dst, dst);
+          return "copy successful";
+        });
+  }
+
+  public Path upload(File srcFile, boolean overwrite) throws IOException {
+    Path src = new Path(srcFile.toURI());
+    Path dst = path(srcFile.getName());
+    getFileSystem().copyFromLocalFile(false, overwrite, src, dst);
+    return dst;
+  }
+
+  /**
+   * Create a temp file with some text.
+   * @param text text for the file
+   * @return the file
+   * @throws IOException on a failure
+   */
+  public File createTempFile(String text) throws IOException {
+    File f = File.createTempFile("test", ".txt");
+    FileUtils.write(f, text, ASCII);
+    return f;
+  }
+}


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