Author: jlowe
Date: Fri Jun 27 23:22:35 2014
New Revision: 1606267

URL: http://svn.apache.org/r1606267
Log:
HADOOP-10739. Renaming a file into a directory containing the same filename 
results in a confusing I/O error. Contributed by chang li

Added:
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestMove.java
   (with props)
Modified:
    hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
    
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/MoveCommands.java

Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1606267&r1=1606266&r2=1606267&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt 
(original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt Fri Jun 
27 23:22:35 2014
@@ -632,6 +632,9 @@ Release 2.5.0 - UNRELEASED
     HADOOP-9705. FsShell cp -p does not preserve directory attibutes.
     (Akira AJISAKA via cnauroth)
 
+    HADOOP-10739. Renaming a file into a directory containing the same
+    filename results in a confusing I/O error (chang li via jlowe)
+
   BREAKDOWN OF HADOOP-10514 SUBTASKS AND RELATED JIRAS
 
     HADOOP-10520. Extended attributes definition and FileSystem APIs for

Modified: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/MoveCommands.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/MoveCommands.java?rev=1606267&r1=1606266&r2=1606267&view=diff
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/MoveCommands.java
 (original)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/shell/MoveCommands.java
 Fri Jun 27 23:22:35 2014
@@ -104,6 +104,9 @@ class MoveCommands {
         throw new PathIOException(src.toString(),
             "Does not match target filesystem");
       }
+      if (target.exists) {
+        throw new PathExistsException(target.toString());
+      }
       if (!target.fs.rename(src.path, target.path)) {
         // we have no way to know the actual error...
         throw new PathIOException(src.toString());

Added: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestMove.java
URL: 
http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestMove.java?rev=1606267&view=auto
==============================================================================
--- 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestMove.java
 (added)
+++ 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestMove.java
 Fri Jun 27 23:22:35 2014
@@ -0,0 +1,123 @@
+/**
+ * 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.shell;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.FilterFileSystem;
+import org.apache.hadoop.fs.PathExistsException;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestMove {
+  static Configuration conf;
+  static FileSystem mockFs;
+ 
+  @BeforeClass
+  public static void setup() throws IOException, URISyntaxException {
+    mockFs = mock(FileSystem.class);
+    conf = new Configuration();
+    conf.setClass("fs.mockfs.impl", MockFileSystem.class, FileSystem.class);
+  }
+    
+  @Before
+  public void resetMock() throws IOException {
+    reset(mockFs);
+  }
+    
+  @Test
+  public void testMoveTargetExistsWithoutExplicitRename() throws Exception {
+    Path srcPath = new Path("mockfs:/file");
+    Path targetPath = new Path("mockfs:/fold0");
+    Path dupPath = new Path("mockfs:/fold0/file");
+    Path srcPath2 = new Path("mockfs://user/file");
+    Path targetPath2 = new Path("mockfs://user/fold0");
+    Path dupPath2 = new Path("mockfs://user/fold0/file");
+    InstrumentedRenameCommand cmd;
+    String[] cmdargs = new String[]{"mockfs:/file", "mockfs:/fold0"};
+    FileStatus src_fileStat, target_fileStat, dup_fileStat;
+    URI myuri; 
+    
+    src_fileStat = mock(FileStatus.class);
+    target_fileStat = mock(FileStatus.class);
+    dup_fileStat = mock(FileStatus.class);
+    myuri = new URI("mockfs://user");
+      
+    when(src_fileStat.isDirectory()).thenReturn(false);
+    when(target_fileStat.isDirectory()).thenReturn(true);
+    when(dup_fileStat.isDirectory()).thenReturn(false);
+    when(src_fileStat.getPath()).thenReturn(srcPath2);
+    when(target_fileStat.getPath()).thenReturn(targetPath2);
+    when(dup_fileStat.getPath()).thenReturn(dupPath2);
+    when(mockFs.getFileStatus(eq(srcPath))).thenReturn(src_fileStat);
+    when(mockFs.getFileStatus(eq(targetPath))).thenReturn(target_fileStat);
+    when(mockFs.getFileStatus(eq(dupPath))).thenReturn(dup_fileStat);
+    when(mockFs.getFileStatus(eq(srcPath2))).thenReturn(src_fileStat);
+    when(mockFs.getFileStatus(eq(targetPath2))).thenReturn(target_fileStat);
+    when(mockFs.getFileStatus(eq(dupPath2))).thenReturn(dup_fileStat);
+    when(mockFs.getUri()).thenReturn(myuri);
+        
+    cmd = new InstrumentedRenameCommand();
+    cmd.setConf(conf);
+    cmd.setOverwrite(true);    
+    cmd.run(cmdargs);
+    
+    // make sure command failed with the proper exception
+    assertTrue("Rename should have failed with path exists exception",
+                         cmd.error instanceof PathExistsException);
+  }
+    
+  static class MockFileSystem extends FilterFileSystem {
+    Configuration conf;
+    MockFileSystem() {
+      super(mockFs);
+    }
+    @Override
+    public void initialize(URI uri, Configuration conf) {
+      this.conf = conf;
+    }
+    @Override
+    public Path makeQualified(Path path) {
+      return path;
+    }
+    @Override
+    public Configuration getConf() {
+      return conf;
+    }
+  }
+    
+  private static class InstrumentedRenameCommand extends MoveCommands.Rename {
+    private Exception error = null;
+    @Override
+    public void displayError(Exception e) {
+      error = e;
+    }
+  }
+}

Propchange: 
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/shell/TestMove.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to