StructureGenerator.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:10k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.fs.loadGenerator;
  19. import java.io.File;
  20. import java.io.FileNotFoundException;
  21. import java.io.PrintStream;
  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.Random;
  25. import org.apache.hadoop.util.ToolRunner;
  26. /**
  27.  * This program generates a random namespace structure with the following
  28.  * constraints:
  29.  * 1. The number of subdirectories is a random number in [minWidth, maxWidth].
  30.  * 2. The maximum depth of each subdirectory is a random number 
  31.  *    [2*maxDepth/3, maxDepth].
  32.  * 3. Files are randomly placed in the empty directories. The size of each
  33.  *    file follows Gaussian distribution.
  34.  * The generated namespace structure is described by two files in the output
  35.  * directory. Each line of the first file 
  36.  * contains the full name of a leaf directory.  
  37.  * Each line of the second file contains
  38.  * the full name of a file and its size, separated by a blank.
  39.  * 
  40.  * The synopsis of the command is
  41.  * java StructureGenerator
  42.     -maxDepth <maxDepth> : maximum depth of the directory tree; default is 5.
  43.     -minWidth <minWidth> : minimum number of subdirectories per directories; default is 1
  44.     -maxWidth <maxWidth> : maximum number of subdirectories per directories; default is 5
  45.     -numOfFiles <#OfFiles> : the total number of files; default is 10.
  46.     -avgFileSize <avgFileSizeInBlocks>: average size of blocks; default is 1.
  47.     -outDir <outDir>: output directory; default is the current directory.
  48.     -seed <seed>: random number generator seed; default is the current time.
  49.  */
  50. public class StructureGenerator {
  51.   private int maxDepth = 5;
  52.   private int minWidth = 1;
  53.   private int maxWidth = 5;
  54.   private int numOfFiles = 10;
  55.   private double avgFileSize = 1;
  56.   private File outDir = DEFAULT_STRUCTURE_DIRECTORY;
  57.   final static private String USAGE = "java StructureGeneratorn" +
  58.    "-maxDepth <maxDepth>n" +
  59.     "-minWidth <minWidth>n" +
  60.     "-maxWidth <maxWidth>n" +
  61.     "-numOfFiles <#OfFiles>n" +
  62.     "-avgFileSize <avgFileSizeInBlocks>n" +
  63.     "-outDir <outDir>n" +
  64.     "-seed <seed>";
  65.   
  66.   private Random r = null; 
  67.   
  68.   /** Default directory for storing file/directory structure */
  69.   final static File DEFAULT_STRUCTURE_DIRECTORY = new File(".");
  70.   /** The name of the file for storing directory structure */
  71.   final static String DIR_STRUCTURE_FILE_NAME = "dirStructure";
  72.   /** The name of the file for storing file structure */
  73.   final static String FILE_STRUCTURE_FILE_NAME = "fileStructure";
  74.   /** The name prefix for the files created by this program */
  75.   final static String FILE_NAME_PREFIX = "_file_";
  76.   
  77.   /**
  78.    * The main function first parses the command line arguments,
  79.    * then generates in-memory directory structure and outputs to a file,
  80.    * last generates in-memory files and outputs them to a file.
  81.    */
  82.   public int run(String[] args) throws Exception {
  83.     int exitCode = 0;
  84.     exitCode = init(args);
  85.     if (exitCode != 0) {
  86.       return exitCode;
  87.     }
  88.     genDirStructure();
  89.     output(new File(outDir, DIR_STRUCTURE_FILE_NAME));
  90.     genFileStructure();
  91.     outputFiles(new File(outDir, FILE_STRUCTURE_FILE_NAME));
  92.     return exitCode;
  93.   }
  94.   /** Parse the command line arguments and initialize the data */
  95.   private int init(String[] args) {
  96.     try {
  97.       for (int i = 0; i < args.length; i++) { // parse command line
  98.         if (args[i].equals("-maxDepth")) {
  99.           maxDepth = Integer.parseInt(args[++i]);
  100.           if (maxDepth<1) {
  101.             System.err.println("maxDepth must be positive: " + maxDepth);
  102.             return -1;
  103.           }
  104.         } else if (args[i].equals("-minWidth")) {
  105.           minWidth = Integer.parseInt(args[++i]);
  106.           if (minWidth<0) {
  107.             System.err.println("minWidth must be positive: " + minWidth);
  108.             return -1;
  109.           }
  110.         } else if (args[i].equals("-maxWidth")) {
  111.           maxWidth = Integer.parseInt(args[++i]);
  112.         } else if (args[i].equals("-numOfFiles")) {
  113.           numOfFiles = Integer.parseInt(args[++i]);
  114.           if (numOfFiles<1) {
  115.             System.err.println("NumOfFiles must be positive: " + numOfFiles);
  116.             return -1;
  117.           }
  118.         } else if (args[i].equals("-avgFileSize")) {
  119.           avgFileSize = Double.parseDouble(args[++i]);
  120.           if (avgFileSize<=0) {
  121.             System.err.println("AvgFileSize must be positive: " + avgFileSize);
  122.             return -1;
  123.           }
  124.         } else if (args[i].equals("-outDir")) {
  125.           outDir = new File(args[++i]);
  126.         } else if (args[i].equals("-seed")) {
  127.           r = new Random(Long.parseLong(args[++i]));
  128.         } else {
  129.           System.err.println(USAGE);
  130.           ToolRunner.printGenericCommandUsage(System.err);
  131.           return -1;
  132.         }
  133.       }
  134.     } catch (NumberFormatException e) {
  135.       System.err.println("Illegal parameter: " + e.getLocalizedMessage());
  136.       System.err.println(USAGE);
  137.       return -1;
  138.     }
  139.     
  140.     if (maxWidth < minWidth) {
  141.       System.err.println(
  142.           "maxWidth must be bigger than minWidth: " + maxWidth);
  143.       return -1;
  144.     }
  145.     
  146.     if (r==null) {
  147.       r = new Random();
  148.     }
  149.     return 0;
  150.   }
  151.   
  152.   /** In memory representation of a directory */
  153.   private static class INode {
  154.     private String name;
  155.     private List<INode> children = new ArrayList<INode>();
  156.     
  157.     /** Constructor */
  158.     private INode(String name) {
  159.       this.name = name;
  160.     }
  161.     
  162.     /** Add a child (subdir/file) */
  163.     private void addChild(INode child) {
  164.       children.add(child);
  165.     }
  166.     
  167.     /** Output the subtree rooted at the current node. 
  168.      * Only the leaves are printed.
  169.      */
  170.     private void output(PrintStream out, String prefix) {
  171.       prefix = prefix==null?name:prefix+"/"+name;
  172.       if (children.isEmpty()) {
  173.         out.println(prefix);
  174.       } else {
  175.         for (INode child : children) {
  176.           child.output(out, prefix);
  177.         }
  178.       }
  179.     }
  180.     
  181.     /** Output the files in the subtree rooted at this node */
  182.     protected void outputFiles(PrintStream out, String prefix) {
  183.       prefix = prefix==null?name:prefix+"/"+name;
  184.       for (INode child : children) {
  185.         child.outputFiles(out, prefix);
  186.       }
  187.     }
  188.     
  189.     /** Add all the leaves in the subtree to the input list */
  190.     private void getLeaves(List<INode> leaves) {
  191.       if (children.isEmpty()) {
  192.         leaves.add(this);
  193.       } else {
  194.         for (INode child : children) {
  195.           child.getLeaves(leaves);
  196.         }
  197.       }
  198.     }
  199.   }
  200.   
  201.   /** In memory representation of a file */
  202.   private static class FileINode extends INode {
  203.     private double numOfBlocks;
  204.     /** constructor */
  205.     private FileINode(String name, double numOfBlocks) {
  206.       super(name);
  207.       this.numOfBlocks = numOfBlocks;
  208.     }
  209.     
  210.     /** Output a file attribute */
  211.     protected void outputFiles(PrintStream out, String prefix) {
  212.       prefix = (prefix == null)?super.name: prefix + "/"+super.name;
  213.       out.println(prefix + " " + numOfBlocks);
  214.     }
  215.   }
  216.   private INode root;
  217.   
  218.   /** Generates a directory tree with a max depth of <code>maxDepth</code> */
  219.   private void genDirStructure() {
  220.     root = genDirStructure("", maxDepth);
  221.   }
  222.   
  223.   /** Generate a directory tree rooted at <code>rootName</code>
  224.    * The number of subtree is in the range of [minWidth, maxWidth].
  225.    * The maximum depth of each subtree is in the range of
  226.    * [2*maxDepth/3, maxDepth].
  227.    */
  228.   private INode genDirStructure(String rootName, int maxDepth) {
  229.     INode root = new INode(rootName);
  230.     
  231.     if (maxDepth>0) {
  232.       maxDepth--;
  233.       int minDepth = maxDepth*2/3;
  234.       // Figure out the number of subdirectories to generate
  235.       int numOfSubDirs = minWidth + r.nextInt(maxWidth-minWidth+1);
  236.       // Expand the tree
  237.       for (int i=0; i<numOfSubDirs; i++) {
  238.         int childDepth = (maxDepth == 0)?0:
  239.           (r.nextInt(maxDepth-minDepth+1)+minDepth);
  240.         INode child = genDirStructure("dir"+i, childDepth);
  241.         root.addChild(child);
  242.       }
  243.     }
  244.     return root;
  245.   }
  246.   
  247.   /** Collects leaf nodes in the tree */
  248.   private List<INode> getLeaves() {
  249.     List<INode> leaveDirs = new ArrayList<INode>();
  250.     root.getLeaves(leaveDirs);
  251.     return leaveDirs;
  252.   }
  253.   
  254.   /** Decides where to place all the files and its length.
  255.    * It first collects all empty directories in the tree.
  256.    * For each file, it randomly chooses an empty directory to place the file.
  257.    * The file's length is generated using Gaussian distribution.
  258.    */
  259.   private void genFileStructure() {
  260.     List<INode> leaves = getLeaves();
  261.     int totalLeaves = leaves.size();
  262.     for (int i=0; i<numOfFiles; i++) {
  263.       int leaveNum = r.nextInt(totalLeaves);
  264.       double fileSize;
  265.       do {
  266.         fileSize = r.nextGaussian()+avgFileSize;
  267.       } while (fileSize<0);
  268.       leaves.get(leaveNum).addChild(
  269.           new FileINode(FILE_NAME_PREFIX+i, fileSize));
  270.     }
  271.   }
  272.   
  273.   /** Output directory structure to a file, each line of the file
  274.    * contains the directory name. Only empty directory names are printed. */
  275.   private void output(File outFile) throws FileNotFoundException {
  276.     System.out.println("Printing to " + outFile.toString());
  277.     PrintStream out = new PrintStream(outFile);
  278.     root.output(out, null);
  279.     out.close();
  280.   }
  281.   
  282.   /** Output all files' attributes to a file, each line of the output file
  283.    * contains a file name and its length. */
  284.   private void outputFiles(File outFile) throws FileNotFoundException {
  285.     System.out.println("Printing to " + outFile.toString());
  286.     PrintStream out = new PrintStream(outFile);
  287.     root.outputFiles(out, null);
  288.     out.close();
  289.   }
  290.   
  291.   /**
  292.    * Main program
  293.    * @param args Command line arguments
  294.    * @throws Exception
  295.    */
  296.   public static void main(String[] args) throws Exception {
  297.     StructureGenerator sg = new StructureGenerator();
  298.     System.exit(sg.run(args));
  299.   }
  300. }