/*************************************************************************** * Copyright (C) 2009 by H-Store Project * * Brown University * * Massachusetts Institute of Technology * * Yale University * * * * Andy Pavlo (pavlo@cs.brown.edu) * * http://www.cs.brown.edu/~pavlo/ * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to * * the following conditions: * * * * The above copyright notice and this permission notice shall be * * included in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * ***************************************************************************/ package edu.brown.benchmark.tpce; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import org.apache.log4j.Logger; import org.voltdb.catalog.Table; import edu.brown.utils.TableDataIterable; /** * Java wrapper around the TPC-E EGenLoader executable * * @author pavlo */ public class EGenLoader { private static final Logger LOG = Logger.getLogger(EGenLoader.class); protected final File base_path; protected final File loader_bin; protected final File input_path; protected final File output_path; // Database Parameters private final Integer total_customers; private final Integer scale_factor; private final Integer initial_workdays; /** * Constructor * * @param egenloader_path * @param total_customers * @param scale_factor * @param initial_workdays */ public EGenLoader(String egenloader_path, int total_customers, int scale_factor, int initial_workdays) { assert (egenloader_path != null) : "The EGENLOADER_PATH parameter is null"; assert (!egenloader_path.isEmpty()) : "The EGENLOADER_PATH parameter is empty"; LOG.debug("egenloader_path: " + egenloader_path); this.base_path = new File(egenloader_path); this.loader_bin = new File(this.base_path + File.separator + "bin" + File.separator + "EGenLoader"); if (!this.loader_bin.exists()) { LOG.error("Unable to start benchmark. The executable " + this.loader_bin + " does not exist"); System.exit(1); } //TODO input_path + flat_in? this.input_path = new File(this.base_path + File.separator + "flat_in"); this.output_path = new File(this.base_path + File.separator + "flat_out"); this.total_customers = total_customers; this.scale_factor = scale_factor; this.initial_workdays = initial_workdays; } /** * For a given table catalog object, return an Iterable that will iterate * through tuples in the generated flat files. * * @param catalog_tbl * @return * @throws Exception */ public Iterable<Object[]> getTable(final Table catalog_tbl) throws Exception { File file = new File(EGenLoader.this.output_path + File.separator + catalog_tbl.getName().toUpperCase() + ".txt"); return (new TableDataIterable(catalog_tbl, file)); } public Integer getTotalCustomers() { return total_customers; } public Integer getScaleFactor() { return scale_factor; } public Integer getInitialWorkdays() { return initial_workdays; } /** * @throws Exception */ protected void generateFixedTables() throws Exception { assert (this.loader_bin.exists()); LOG.debug("Creating fixed sized tables"); String options[] = new String[] { "-xf" }; this.execute(options); } /** * @throws Exception */ protected void generateScalingTables(Integer start_customer) throws Exception { assert (this.loader_bin.exists()); LOG.debug("Creating scaling tables"); String options[] = new String[] { "-xs", "-c", this.total_customers.toString(), "-b", start_customer.toString(), }; this.execute(options); } /** * @throws Exception */ protected void generateGrowingTables(Integer start_customer) throws Exception { assert (this.loader_bin.exists()); LOG.info("Creating growing tables"); String options[] = new String[] { "-xg", "-c", this.total_customers.toString(), "-b", start_customer.toString(), }; this.execute(options); } /** * Clear all the table files in the output path * * @throws Exception */ protected void clearTables() throws Exception { for (File file : this.output_path.listFiles()) { if (file.isFile() && file.getName().endsWith(".txt")) { if (!file.delete()) { throw new Exception("Failed to delete file '" + file.getAbsolutePath() + "'"); } } } // FOR return; } public File getTablePath(String table_name) { return (new File(this.output_path + "/" + table_name.toUpperCase() + ".txt")); } /** * @param options * @throws Exception */ protected void execute(String[] options) throws Exception { assert (this.loader_bin.exists()); File working_dir = new File(this.loader_bin.getParent()); assert (working_dir.exists()); String base_command[] = new String[] { this.loader_bin.getAbsolutePath(), "-i", this.input_path.getAbsolutePath(), "-o", this.output_path.getAbsolutePath(), "-t", this.total_customers.toString(), "-f", this.scale_factor.toString(), "-w", this.initial_workdays.toString(), }; String command[] = new String[base_command.length + options.length]; int command_idx = 0; for (String c : base_command) command[command_idx++] = c; String options_debug = ""; for (String c : options) { command[command_idx++] = c; options_debug += " " + c; } // FOR LOG.debug("Executing " + this.loader_bin.getName() + " in " + working_dir); LOG.debug("Input Path: " + this.input_path); LOG.debug("Output Path: " + this.output_path); LOG.debug("Total Customers: " + this.total_customers); LOG.debug("Scale Factor: " + this.scale_factor); LOG.debug("Initial Workdays: " + this.initial_workdays); LOG.debug("Additional Params:" + options_debug); // // Bombs away! // String env[] = new String[] {}; Process proc = null; try { proc = Runtime.getRuntime().exec(command, env, working_dir); } catch (Exception ex) { LOG.fatal(ex.getMessage(), ex); System.exit(1); } BufferedReader stdout = new BufferedReader(new InputStreamReader(proc.getInputStream())); BufferedReader stderr = new BufferedReader(new InputStreamReader(proc.getErrorStream())); // // This seems so slutty. There must be a better way... just need to // google it // String line = null; while ((line = stdout.readLine()) != null) { if (!line.isEmpty()) LOG.debug(line); while ((line = stderr.readLine()) != null) { if (!line.isEmpty()) LOG.warn(line); } } // WHILE try { LOG.debug("Waiting for process to end"); if (proc.waitFor() != 0) { String msg = "Failed to execute " + this.loader_bin.getName() + ". Exit value = " + proc.exitValue(); LOG.error(msg); throw new Exception(msg); } } catch (InterruptedException e) { LOG.error(e); } } }