source: DCWoRMS/trunk/src/simulator/DataCenterWorkloadSimulator.java @ 512

Revision 512, 14.0 KB checked in by wojtekp, 13 years ago (diff)
  • Property svn:mime-type set to text/plain
Line 
1package simulator;
2
3import java.io.File;
4import java.io.FileReader;
5import java.io.FileWriter;
6import java.io.IOException;
7import java.io.PrintStream;
8import java.security.InvalidParameterException;
9import java.text.NumberFormat;
10import java.util.Calendar;
11import java.util.Date;
12
13import javax.swing.JFileChooser;
14import javax.swing.filechooser.FileFilter;
15
16import org.apache.commons.logging.Log;
17import org.apache.commons.logging.LogFactory;
18import org.exolab.castor.xml.MarshalException;
19import org.exolab.castor.xml.ValidationException;
20import org.joda.time.DateTimeUtilsExt;
21import org.qcg.broker.schemas.jobdesc.QcgJob;
22
23import schedframe.Initializable;
24import schedframe.ResourceController;
25import simulator.reader.ResourceReader;
26import simulator.stats.AccumulatedStatistics;
27import simulator.stats.implementation.DCWormsStatistics;
28import simulator.utils.LogErrStream;
29import simulator.workload.WorkloadLoader;
30import simulator.workload.reader.archive.AbstractWAReader;
31import simulator.workload.reader.archive.WAReader;
32import simulator.workload.reader.xmlJob.QcgXmlJobReader;
33import simulator.workload.reader.xmlJob.XMLJobReader;
34import cern.jet.random.Uniform;
35import cern.jet.random.engine.MersenneTwister64;
36
37/**
38 * The main class of the Data Center Workload Scheduling Simulator. It has the
39 * {@link #main(String[])} method used to invoke the program. This class also
40 * provides second possibility to start the simulator, namely one may use the
41 * {@link #performSimulation(ConfigurationOptions, DCWormsStatistics)} method.
42 * In this case, the input parameter, describing the simulation options, must be
43 * earlier prepared. The results of the simulation can be acquired using the
44 * {@link #getAccumulatedStatistics()} method.
45 *
46 * @author Stanislaw Szczepanowski & Wojciech Piatek
47 */
48public class DataCenterWorkloadSimulator {
49
50        /**
51         * The name of the simulator application
52         */
53        public static final String SIMULATOR_NAME = "Data Center Workload Simulator";
54
55        /**
56         * Stores the statistical data of last run of the simulator (it may consist
57         * of several runs of simulations)
58         */
59        protected static AccumulatedStatistics accumulatedStatistics;
60
61        protected static int simulationRunNumber = 0;
62
63        /**
64         * Determines the maximum fraction digits when printing floating point
65         * values
66         */
67        public static int MAXIMUM_FRACTION_DIGITS = 3;
68
69        /**
70         * The format of the numbers that will be printed
71         */
72        public static NumberFormat DFAULT_NUMBER_FORMAT = NumberFormat
73                        .getInstance();
74        static {
75                DFAULT_NUMBER_FORMAT.setMaximumFractionDigits(MAXIMUM_FRACTION_DIGITS); // 0,001
76        }
77
78        private Log log = LogFactory.getLog(DataCenterWorkloadSimulator.class);
79
80        protected String statsOutputPath;
81
82
83        /**
84         * Default empty constructor
85         */
86        public DataCenterWorkloadSimulator() {
87        }
88
89        /**
90         * The main method to start the simulation the accepted arguments are:
91         * args[0] - the name of the resource bundle file with the configuration
92         * args[1] (optional) - the number of simulations that are to be performed
93         * (the default value is 1)
94         *
95         * @param args
96         *            the arguments passed to the application
97         */
98        public static void main(String[] args) {
99                DataCenterWorkloadSimulator dcworms = new DataCenterWorkloadSimulator();
100                dcworms.run(args);
101        }
102
103        public void run(String args[]) {
104                System.setErr(new PrintStream(new LogErrStream(log)));
105
106                String propertiesFileName = null;
107                if (args.length == 0) {
108                        JFileChooser ch = new JFileChooser(".");
109                        FileFilter filter = new FileFilter() {
110                                @Override
111                                public boolean accept(File f) {
112                                        return f.getName().endsWith(".properties")
113                                                        || f.isDirectory();
114                                }
115
116                                @Override
117                                public String getDescription() {
118                                        return "DCWoRMS experiment file";
119                                }
120                        };
121                        ch.setFileFilter(filter);
122                        ch.setDialogTitle("Choose the WoRMS simulation experiment file");
123                        int result = ch.showOpenDialog(ch);
124                        if (result == JFileChooser.APPROVE_OPTION) {
125                                propertiesFileName = ch.getSelectedFile().getAbsolutePath();
126                        } else {
127                                if (log.isFatalEnabled())
128                                        log.fatal("Resource bundle file name was not provided.");
129                                return;
130                        }
131                } else if (args.length == 2 && "-multiuser".equals(args[0])) {
132                        runMultiuser(args[1], this);
133                        return;
134                } else {
135                        propertiesFileName = args[0];
136                }
137
138                ConfigurationOptions configurationOptions = ConfigurationOptions
139                                .getConfiguration(propertiesFileName);
140                int noOfSimulations = 1; // default value is one
141
142                if(configurationOptions.getNumberOfSimulations() > 1)
143                        noOfSimulations = configurationOptions.getNumberOfSimulations();
144                else if (args.length == 2) {// second parameter is given
145                        noOfSimulations = Integer.parseInt(args[1]);
146                        if (noOfSimulations < 1) {
147                                throw new InvalidParameterException(
148                                                "Number of simulations cannot be less than 1");
149                        }
150                }
151
152                if (log.isInfoEnabled())
153                        log.info(":: Starting " + SIMULATOR_NAME + ". " + noOfSimulations
154                                        + " simulation runs will be performed. ::");
155
156                File outputDir = null;
157
158                try {
159                        outputDir = prepareDirecotry(configurationOptions);
160                } catch (Exception e) {
161                        if (log.isErrorEnabled())
162                                log.error("FAILED to create the output path", e);
163                        return;
164                }
165
166                File outputPropertiesFile = new File(outputDir, "experiment.properties");
167
168                accumulatedStatistics = new AccumulatedStatistics(noOfSimulations);
169               
170                for (int i = 0; i < noOfSimulations; ++i) {
171                        simulationRunNumber++;
172                        String simulationIdentifier = "Simulation " + (i + 1);
173                        try {
174                                performSimulation(simulationIdentifier,
175                                                configurationOptions); // run the simulation
176
177                        } catch (Exception e) {
178                                if (log.isErrorEnabled())
179                                        log.error("ERROR in simulation run \""
180                                                        + simulationIdentifier + "\":", e);
181                                break;
182                        }
183                }
184
185                if (log.isInfoEnabled())
186                        log.info("Done :: " + SIMULATOR_NAME + " has finished "
187                                        + noOfSimulations + " simulation runs ::");
188
189                System.out.flush();
190                System.err.flush();
191
192                try {
193                        copyFile(new File(propertiesFileName), outputPropertiesFile);
194                } catch (IOException e) {
195                        log.error("IO exception occured during copying properties file to output path");
196                }
197        }
198
199        private void runMultiuser(String rootDirPath, DataCenterWorkloadSimulator dcworms) {
200                throw new RuntimeException("not supported yet");
201        }
202
203
204        /**
205         * Starts a single simulation run.
206         *
207         * @param options
208         *            the configuration options according to which the simulation is
209         *            to be performed
210         * @param simulationStatistics
211         *            the statistics object that is to be filled after the
212         *            simulation run
213         * @throws Exception
214         *             any exception that may occur
215         */
216        private void performSimulation(String simulationIdentifier,
217                        ConfigurationOptions options) throws Exception {
218                // Startup of the random number generators must be set up with a random
219                // seed that is greater than zero
220                // if seed is not given then all consecutive simulations are the same
221                // if seed < 0 then the random numbers are equal to zero
222                Uniform uniform = new Uniform(new MersenneTwister64(new Date()));
223                // seed should be > 0 and fits to int size (which is also important)
224                long seed = uniform.nextLongFromTo(1, Integer.MAX_VALUE);
225                if (log.isDebugEnabled())
226                        log.debug("Shuffled initial seed: " + seed);
227
228                assert seed > 0 && seed <= Integer.MAX_VALUE : "Initial seed is <= 0, what is improper";
229               
230                GridSimWrapper.setSeed(seed);
231                GridSimWrapper.setTraceSettings();
232               
233                long startSimulation = System.currentTimeMillis();
234                if (log.isInfoEnabled()) {
235                        log.info(":: Starting simulation run: \"" + simulationIdentifier
236                                        + "\" ::");
237                        log.info(":: In the the mode of ");
238                }
239
240                WorkloadLoader workload = loadWorkload(options);
241       
242                // BEGIN: Initializing the GridSim:
243                int numUser = 1; // the number of users in the experiment simulation
244                // (default 1)
245               
246                Date date = workload.getSimulationStartTime();
247                Calendar calendar = Calendar.getInstance();
248                if (date == null)
249                        calendar.setTimeInMillis(0L);
250                else
251                        calendar.setTime(date);
252
253                boolean traceFlag = true; // means: trace GridSim events/activities
254                String[] excludeFromFile = { "" }, excludeFromProcessing = { "" };
255               
256                GridSimWrapper.init(numUser, calendar, traceFlag, excludeFromFile,
257                                excludeFromProcessing, null);
258                DateTimeUtilsExt.initVirtualTimeAccess(calendar);
259
260                ResourceReader resourceReader = new ResourceReader(
261                                options);
262                ResourceController rc = resourceReader.read();
263
264                for(Initializable initObj: rc.getToInit()){
265                        initObj.initiate();
266                }
267                rc.setInitList(null);
268               
269                DCWormsUsers wl = new DCWormsUsers("Users",
270                                rc.getScheduler().get_name(), workload);
271               
272                GridSimWrapper.startSimulation();
273                long stopSimulation = System.currentTimeMillis();
274
275                DCWormsStatistics stats = new DCWormsStatistics(simulationIdentifier,
276                                options, wl, statsOutputPath, rc);
277                accumulatedStatistics.add(stats);
278                if (log.isInfoEnabled())
279                        log.info("Generating statistics...");
280                stats.generateStatistics();
281
282                long duration = (stopSimulation - startSimulation) / 1000;
283                if (log.isInfoEnabled())
284                        log.info("The simulation run took " + duration + " seconds");
285
286                // if necessary generate gifs from sjvg - need to rewrite the SJVG
287                // classes for public methods
288                if (log.isInfoEnabled())
289                        log.info(":: Finished simulation run: \"" + simulationIdentifier
290                                        + "\" ::");
291
292                System.out.flush();
293                System.err.flush();
294        }
295
296        private WorkloadLoader loadWorkload(ConfigurationOptions options) throws IOException, MarshalException, ValidationException{
297                XMLJobReader<QcgJob> xmlJobReader = null;
298                WAReader<QcgJob> swfReader = null;
299
300                String wlFileName = options.inputWorkloadFileName;
301
302                if (options.inputFolder != null) {
303                        File f = null;
304                        if (options.inputTar != null) {
305                                f = new File(options.inputFolder + File.separator
306                                                + options.inputTar);
307                        } else {
308                                f = new File(options.inputFolder);
309                        }
310
311                        xmlJobReader = new QcgXmlJobReader(f);
312
313                        wlFileName = options.inputFolder + File.separator
314                                        + options.inputWorkloadFileName;
315                }
316
317                swfReader = AbstractWAReader.getInstace(wlFileName);
318
319                WorkloadLoader workload = new WorkloadLoader(xmlJobReader, swfReader);
320                workload.load();
321
322                return workload;
323        }
324       
325
326        private File prepareDirecotry(ConfigurationOptions options) throws Exception {
327                // String statsOutputPath = null;
328                if (options.createScenario) {
329                        File outputFolderFile = new File(options.outputFolder);
330                        if (!outputFolderFile.exists()) {
331                                if (!outputFolderFile.mkdirs())
332                                        throw new IOException("Cannot create the output path: "
333                                                        + statsOutputPath + ". Cause: ");
334                        }
335
336                        if (log.isInfoEnabled())
337                                log.info("CREATING SCENARIO ::");
338                        statsOutputPath = options.outputFolder
339                                        + options.statsOutputSubfolderNameCreate;
340                } else {
341                        if (log.isInfoEnabled())
342                                log.info("READING SCENARIO ::");
343                        String prefix = null;
344                        if (options.inputFolder != null) {
345                                prefix = options.inputFolder;
346                        } else if (options.inputWorkloadFileName != null) {
347                                prefix = new File(options.inputWorkloadFileName).getParent();
348                        } else {
349                                prefix = System.getProperty("user.dir");
350                        }
351                        statsOutputPath = prefix + File.separator
352                                        + options.statsOutputSubfolderNameRerad;
353                }
354                statsOutputPath += File.separator;
355
356                // create the output folder
357                File statsOutputPathFile = new File(statsOutputPath);
358                if (!statsOutputPathFile.exists()) {
359                        if (!statsOutputPathFile.mkdirs())
360                                throw new IOException("Cannot create the output (stats) path: "
361                                                + statsOutputPath + ". Cause: ");
362                }
363
364                File folder = new File(statsOutputPath);
365                File fileList[] = folder.listFiles();
366                for (int i = 0; i < fileList.length; i++) {
367                        File tmpFile = fileList[i];
368                        String name = tmpFile.getName();
369                        if (name.length() > 4) {
370                                String subName = name.substring(0, 5);
371                                if (subName.compareTo("Chart") == 0
372                                                || subName.compareTo("Stats") == 0) {
373                                        tmpFile.delete();
374                                }
375                        }
376                }
377                return statsOutputPathFile;
378        }
379
380        /**
381         * Removes the given directory no matter if it is empty or non empty. If the
382         * given parameter represents a file, it is not deleted. See the description
383         * of the return statement.
384         *
385         * @param dirPath
386         *            the file representing the directory to be deleted.
387         * @return true, if the given directory with all its contents have been
388         *         remove; false if deletion of any of files ended with error (all
389         *         other files are possibly also deleted)
390         */
391        private static boolean deleteDirectory(File dirPath) {
392                if (dirPath.exists() && dirPath.isDirectory()) {
393                        boolean result = true;
394                        File[] files = dirPath.listFiles();
395                        for (File file : files) {
396                                if (file.isFile())
397                                        result |= file.delete();
398                                else
399                                        result |= deleteDirectory(file);
400                        }
401                        result |= dirPath.delete();
402                        return result;
403                }
404                return false; // it is not a directory
405        }
406       
407        /**
408         * Static method to move a file from given "from" location to "to" location
409         *
410         * @param from
411         *            from location
412         * @param to
413         *            to location
414         * @return true if the operation succeeded, false otherwise
415         */
416        private static boolean moveFile(String from, String to) {
417                File fromFile = new File(from);
418                File toFile = new File(to);
419                if (toFile.exists()) {
420                        if (!toFile.delete())
421                                return false;
422                }
423                if (!fromFile.renameTo(toFile)) {
424                        return false;
425                }
426                return true;
427        }
428       
429        private void copyFile(File inputFile, File outputFile) throws IOException {
430
431                FileReader in = new FileReader(inputFile);
432                FileWriter out = new FileWriter(outputFile);
433                int c;
434
435                while ((c = in.read()) != -1)
436                        out.write(c);
437
438                in.close();
439                out.close();
440        }
441
442        /**
443         * Returns the accumulated simulation statistics from the last run of the
444         * simulator
445         *
446         * @return the accumulated simulation statistics from the last run of the
447         *         simulator
448         */
449        public static AccumulatedStatistics getAccumulatedStatistics() {
450                return accumulatedStatistics;
451        }
452
453        public static int getSimulationRunNumber(){
454                return simulationRunNumber;
455        }
456       
457        protected class WorkloadDirectoryFilter implements java.io.FileFilter {
458
459                public boolean accept(File file) {
460                        if (file.isDirectory() && file.getName().startsWith("workload"))
461                                return true;
462                        else
463                                return false;
464                }
465        }
466
467        protected class PropertiesFileFilter implements java.io.FileFilter {
468
469                public boolean accept(File file) {
470                        if (file.isFile() && file.getName().endsWith(".properties"))
471                                return true;
472                        else
473                                return false;
474                }
475        }
476
477}
Note: See TracBrowser for help on using the repository browser.