Browse Source

svn merge -c 1102012 from trunk for HADOOP-7275.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/yahoo-merge@1127286 13f79535-47bb-0310-9956-ffa450edef68
Tsz-wo Sze 14 years ago
parent
commit
bca7cce0ec

+ 3 - 0
CHANGES.txt

@@ -62,6 +62,9 @@ Trunk (unreleased changes)
     HADOOP-7271. Standardize shell command error messages.  (Daryn Sharp
     via szetszwo)
 
+    HADOOP-7275. Refactor the stat commands to conform to new FsCommand
+    class.  (Daryn Sharp via szetszwo)
+
   OPTIMIZATIONS
 
   BUG FIXES

+ 3 - 82
src/java/org/apache/hadoop/fs/FsShell.java

@@ -25,9 +25,7 @@ import java.net.URI;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.List;
-import java.util.TimeZone;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -61,12 +59,8 @@ public class FsShell extends Configured implements Tool {
 
   public static final SimpleDateFormat dateForm = 
     new SimpleDateFormat("yyyy-MM-dd HH:mm");
-  protected static final SimpleDateFormat modifFmt =
-    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   static final int BORDER = 2;
-  static {
-    modifFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
-  }
+
   static final String GET_SHORT_USAGE = "-get [-ignoreCrc] [-crc] <src> <localdst>";
   static final String COPYTOLOCAL_SHORT_USAGE = GET_SHORT_USAGE.replace(
       "-get", "-copyToLocal");
@@ -484,62 +478,6 @@ public class FsShell extends Configured implements Tool {
     }
   }
 
-  /**
-   * Print statistics about path in specified format.
-   * Format sequences:
-   *   %b: Size of file in blocks
-   *   %n: Filename
-   *   %o: Block size
-   *   %r: replication
-   *   %y: UTC date as &quot;yyyy-MM-dd HH:mm:ss&quot;
-   *   %Y: Milliseconds since January 1, 1970 UTC
-   */
-  void stat(char[] fmt, String src) throws IOException {
-    Path srcPath = new Path(src);
-    FileSystem srcFs = srcPath.getFileSystem(getConf());
-    FileStatus glob[] = srcFs.globStatus(srcPath);
-    if (null == glob)
-      throw new PathNotFoundException(src);
-    for (FileStatus f : glob) {
-      StringBuilder buf = new StringBuilder();
-      for (int i = 0; i < fmt.length; ++i) {
-        if (fmt[i] != '%') {
-          buf.append(fmt[i]);
-        } else {
-          if (i + 1 == fmt.length) break;
-          switch(fmt[++i]) {
-            case 'b':
-              buf.append(f.getLen());
-              break;
-            case 'F':
-              buf.append(f.isDirectory() ? "directory" 
-                                         : (f.isFile() ? "regular file" : "symlink"));
-              break;
-            case 'n':
-              buf.append(f.getPath().getName());
-              break;
-            case 'o':
-              buf.append(f.getBlockSize());
-              break;
-            case 'r':
-              buf.append(f.getReplication());
-              break;
-            case 'y':
-              buf.append(modifFmt.format(new Date(f.getModificationTime())));
-              break;
-            case 'Y':
-              buf.append(f.getModificationTime());
-              break;
-            default:
-              buf.append(fmt[i]);
-              break;
-          }
-        }
-      }
-      System.out.println(buf.toString());
-    }
-  }
-
   /**
    * Move files that match the file pattern <i>srcf</i>
    * to a destination file.
@@ -825,7 +763,7 @@ public class FsShell extends Configured implements Tool {
       GET_SHORT_USAGE + "\n\t" +
       "[" + COPYTOLOCAL_SHORT_USAGE + "] [-moveToLocal <src> <localdst>]\n\t" +
       "[-report]\n\t" +
-      "[-touchz <path>] [-test -[ezd] <path>] [-stat [format] <path>]";
+      "[-touchz <path>] [-test -[ezd] <path>]";
 
     String conf ="-conf <configuration file>:  Specify an application configuration file.";
  
@@ -905,10 +843,6 @@ public class FsShell extends Configured implements Tool {
     String test = "-test -[ezd] <path>: If file { exists, has zero length, is a directory\n" +
       "\t\tthen return 0, else return 1.\n";
 
-    String stat = "-stat [format] <path>: Print statistics about the file/directory at <path>\n" +
-      "\t\tin the specified format. Format accepts filesize in blocks (%b), filename (%n),\n" +
-      "\t\tblock size (%o), replication (%r), modification date (%y, %Y)\n";
-    
     String expunge = "-expunge: Empty the Trash.\n";
     
     String help = "-help [cmd]: \tDisplays help for given command or all commands if none\n" +
@@ -957,8 +891,6 @@ public class FsShell extends Configured implements Tool {
       System.out.println(touchz);
     } else if ("test".equals(cmd)) {
       System.out.println(test);
-    } else if ("stat".equals(cmd)) {
-      System.out.println(stat);
     } else if ("help".equals(cmd)) {
       System.out.println(help);
     } else {
@@ -985,7 +917,6 @@ public class FsShell extends Configured implements Tool {
       System.out.println(moveToLocal);
       System.out.println(touchz);
       System.out.println(test);
-      System.out.println(stat);
 
       for (String thisCmdName : commandFactory.getNames()) {
         printHelp(commandFactory.getInstance(thisCmdName));
@@ -1099,9 +1030,6 @@ public class FsShell extends Configured implements Tool {
     } else if ("-test".equals(cmd)) {
       System.err.println("Usage: java FsShell" +
                          " [-test -[ezd] <path>]");
-    } else if ("-stat".equals(cmd)) {
-      System.err.println("Usage: java FsShell" +
-                         " [-stat [format] <path>]");
     } else {
       System.err.println("Usage: java FsShell");
       System.err.println("           [-df [<path>]]");
@@ -1120,7 +1048,6 @@ public class FsShell extends Configured implements Tool {
       System.err.println("           [-moveToLocal [-crc] <src> <localdst>]");
       System.err.println("           [-touchz <path>]");
       System.err.println("           [-test -[ezd] <path>]");
-      System.err.println("           [-stat [format] <path>]");
       for (String name : commandFactory.getNames()) {
       	instance = commandFactory.getInstance(name);
         System.err.println("           [" + instance.getUsage() + "]");
@@ -1170,7 +1097,7 @@ public class FsShell extends Configured implements Tool {
         return exitCode;
       }
     } else if ("-rm".equals(cmd) || "-rmr".equals(cmd) ||
-               "-touchz".equals(cmd) || "-stat".equals(cmd)) {
+               "-touchz".equals(cmd)) {
       if (argv.length < 2) {
         printUsage(cmd);
         return exitCode;
@@ -1243,12 +1170,6 @@ public class FsShell extends Configured implements Tool {
         exitCode = doall(cmd, argv, i);
       } else if ("-test".equals(cmd)) {
         exitCode = test(argv, i);
-      } else if ("-stat".equals(cmd)) {
-        if (i + 1 < argv.length) {
-          stat(argv[i++].toCharArray(), argv[i++]);
-        } else {
-          stat("%y".toCharArray(), argv[i]);
-        }
       } else if ("-help".equals(cmd)) {
         if (i < argv.length) {
           printHelp(argv[i]);

+ 1 - 0
src/java/org/apache/hadoop/fs/shell/FsCommand.java

@@ -50,6 +50,7 @@ abstract public class FsCommand extends Command {
     factory.registerCommands(Ls.class);
     factory.registerCommands(Mkdir.class);
     factory.registerCommands(SetReplication.class);
+    factory.registerCommands(Stat.class);
     factory.registerCommands(Tail.class);
   }
 

+ 121 - 0
src/java/org/apache/hadoop/fs/shell/Stat.java

@@ -0,0 +1,121 @@
+/**
+ * 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 java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.TimeZone;
+
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.fs.FileStatus;
+
+/**
+ * Print statistics about path in specified format.
+ * Format sequences:
+ *   %b: Size of file in blocks
+ *   %n: Filename
+ *   %o: Block size
+ *   %r: replication
+ *   %y: UTC date as &quot;yyyy-MM-dd HH:mm:ss&quot;
+ *   %Y: Milliseconds since January 1, 1970 UTC
+ */
+@InterfaceAudience.Private
+@InterfaceStability.Unstable
+
+class Stat extends FsCommand {
+  public static void registerCommands(CommandFactory factory) {
+    factory.addClass(Stat.class, "-stat");
+  }
+
+  public static final String NAME = "stat";
+  public static final String USAGE = "[format] <path> ...";
+  public static final String DESCRIPTION =
+    "Print statistics about the file/directory at <path>\n" +
+    "in the specified format. Format accepts filesize in blocks (%b), filename (%n),\n" +
+    "block size (%o), replication (%r), modification date (%y, %Y)\n";
+
+  protected static final SimpleDateFormat timeFmt;
+  static {
+    timeFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    timeFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
+  }
+
+  // default format string
+  protected String format = "%y";
+
+  @Override
+  protected void processOptions(LinkedList<String> args) throws IOException {
+    CommandFormat cf = new CommandFormat(null, 1, Integer.MAX_VALUE, "R");
+    cf.parse(args);
+    setRecursive(cf.getOpt("R"));
+    if (args.getFirst().contains("%")) format = args.removeFirst();
+    cf.parse(args); // make sure there's still at least one arg
+  }
+
+  @Override
+  protected void processPath(PathData item) throws IOException {
+    FileStatus stat = item.stat;
+    StringBuilder buf = new StringBuilder();
+
+    char[] fmt = format.toCharArray();
+    for (int i = 0; i < fmt.length; ++i) {
+      if (fmt[i] != '%') {
+        buf.append(fmt[i]);
+      } else {
+        // this silently drops a trailing %?
+        if (i + 1 == fmt.length) break;
+        switch (fmt[++i]) {
+          case 'b':
+            buf.append(stat.getLen());
+            break;
+          case 'F':
+            buf.append(stat.isDirectory()
+                ? "directory" 
+                : (stat.isFile() ? "regular file" : "symlink"));
+            break;
+          case 'n':
+            buf.append(item);
+            break;
+          case 'o':
+            buf.append(stat.getBlockSize());
+            break;
+          case 'r':
+            buf.append(stat.getReplication());
+            break;
+          case 'y':
+            buf.append(timeFmt.format(new Date(stat.getModificationTime())));
+            break;
+          case 'Y':
+            buf.append(stat.getModificationTime());
+            break;
+          default:
+            // this leaves %<unknown> alone, which causes the potential for
+            // future format options to break strings; should use %% to
+            // escape percents
+            buf.append(fmt[i]);
+            break;
+        }
+      }
+    }
+    out.println(buf.toString());
+  }
+}

+ 1 - 1
src/test/core/org/apache/hadoop/cli/testConf.xml

@@ -583,7 +583,7 @@
       <comparators>
         <comparator>
           <type>RegexpComparator</type>
-          <expected-output>^-stat \[format\] &lt;path&gt;: Print statistics about the file/directory at &lt;path&gt;( )*</expected-output>
+          <expected-output>^-stat \[format\] &lt;path&gt; \.\.\.:( |\t)*Print statistics about the file/directory at &lt;path&gt;( )*</expected-output>
         </comparator>
         <comparator>
           <type>RegexpComparator</type>