/*************************************************************************** * Copyright (C) 2009 by H-Store Project * * Brown University * * Massachusetts Institute of Technology * * Yale University * * * * Original Version: * * Zhe Zhang (zhe@cs.brown.edu) * * * * Modifications by: * * 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.tm1; import org.apache.log4j.Logger; import org.voltdb.VoltTable; import org.voltdb.catalog.Database; import org.voltdb.catalog.Table; import org.voltdb.utils.Pair; import edu.brown.api.BenchmarkComponent; import edu.brown.api.Loader; import edu.brown.benchmark.tm1.procedures.GetTableCounts; import edu.brown.catalog.CatalogUtil; import edu.brown.utils.EventObservable; import edu.brown.utils.EventObservableExceptionHandler; import edu.brown.utils.EventObserver; /** * Magical TM1 Loader * @author zhe * @author pavlo */ public class TM1Loader extends Loader { private static final Logger LOG = Logger.getLogger(TM1Loader.class); private static final boolean d = LOG.isDebugEnabled(); private final long subscriberSize; private final boolean blocking = false; public static void main(String[] args) { BenchmarkComponent.main(TM1Loader.class, args, true); } public TM1Loader(String[] args) { super(args); this.subscriberSize = Math.round(TM1Constants.SUBSCRIBER_SIZE * this.getScaleFactor()); } @Override public void load() { if (d) LOG.debug(String.format("Starting TM1Loader [subscriberSize=%d, scaleFactor=%.2f]", this.subscriberSize, this.getScaleFactor())); final Database catalog_db = this.getCatalogContext().database; final Thread threads[] = { new Thread() { public void run() { if (d) LOG.debug("Start loading " + TM1Constants.TABLENAME_SUBSCRIBER); Table catalog_tbl = catalog_db.getTables().get(TM1Constants.TABLENAME_SUBSCRIBER); genSubscriber(catalog_tbl); if (d) LOG.debug("Finished loading " + TM1Constants.TABLENAME_SUBSCRIBER); } }, new Thread() { public void run() { if (d) LOG.debug("Start loading " + TM1Constants.TABLENAME_ACCESS_INFO); Table catalog_tbl = catalog_db.getTables().get(TM1Constants.TABLENAME_ACCESS_INFO); genAccessInfo(catalog_tbl); if (d) LOG.debug("Finished loading " + TM1Constants.TABLENAME_ACCESS_INFO); } }, new Thread() { public void run() { if (d) LOG.debug("Start loading " + TM1Constants.TABLENAME_SPECIAL_FACILITY + " and " + TM1Constants.TABLENAME_CALL_FORWARDING); Table catalog_spe = catalog_db.getTables().get(TM1Constants.TABLENAME_SPECIAL_FACILITY); Table catalog_cal = catalog_db.getTables().get(TM1Constants.TABLENAME_CALL_FORWARDING); genSpeAndCal(catalog_spe, catalog_cal); if (d) LOG.debug("Finished loading " + TM1Constants.TABLENAME_SPECIAL_FACILITY + " and " + TM1Constants.TABLENAME_CALL_FORWARDING); } } }; final EventObservableExceptionHandler handler = new EventObservableExceptionHandler(); handler.addObserver(new EventObserver<Pair<Thread,Throwable>>() { @Override public void update(EventObservable<Pair<Thread, Throwable>> o, Pair<Thread, Throwable> t) { for (Thread thread : threads) thread.interrupt(); } }); try { for (Thread t : threads) { t.setUncaughtExceptionHandler(handler); t.start(); if (this.blocking) t.join(); } // FOR if (!this.blocking) { for (Thread t : threads) t.join(); } this.getClientHandle().drain(); } catch (Exception e) { throw new RuntimeException(e); } finally { if (handler.hasError()) { throw new RuntimeException("Error while generating table data.", handler.getError()); } } // System.err.println("\n" + this.dumpTableCounts()); } public String dumpTableCounts() { if (d) LOG.debug("Getting table counts"); VoltTable results[] = null; try { results = this.getClientHandle().callProcedure(GetTableCounts.class.getSimpleName()).getResults(); } catch (Exception e) { e.printStackTrace(); System.exit(1); } assert (results.length == 1); String ret = "TM1 Table Stats:"; while (results[0].advanceRow()) { String name = results[0].getString(0); long count = results[0].getLong(1); ret += String.format("\n%-20s %d", name + ":", count); // assert(this.table_counts.containsKey(name)); // long expected = this.table_counts.get(name); // assert(expected == count) : "Expected " + expected + // " tuples for table " + name + " but got back " + count; } // WHILE return (ret); } /** * Populate Subscriber table per benchmark spec. */ void genSubscriber(Table catalog_tbl) { final VoltTable table = CatalogUtil.getVoltTable(catalog_tbl); Object row[] = new Object[table.getColumnCount()]; long total = 0; for (long s_id = 0; s_id < this.subscriberSize; s_id++) { int col = 0; row[col++] = s_id; row[col++] = TM1Util.padWithZero(s_id); // BIT_## for (int j = 0; j < 10; j++) { row[col++] = TM1Util.number(0, 1); } // FOR // HEX_## for (int j = 0; j < 10; j++) { row[col++] = TM1Util.number(0, 15); } // BYTE2_## for (int j = 0; j < 10; j++) { row[col++] = TM1Util.number(0, 255); } // MSC_LOCATION + VLR_LOCATION for (int j = 0; j < 2; j++) { row[col++] = TM1Util.number(0, Integer.MAX_VALUE); } assert col == table.getColumnCount(); table.addRow(row); total++; if (table.getRowCount() >= TM1Constants.BATCH_SIZE) { if (d) LOG.debug(String.format("%s: %6d / %d", TM1Constants.TABLENAME_SUBSCRIBER, total, this.subscriberSize)); loadVoltTable(TM1Constants.TABLENAME_SUBSCRIBER, table); table.clearRowData(); assert(table.getRowCount() == 0); } } // FOR if (table.getRowCount() > 0) { if (d) LOG.debug(String.format("%s: %6d / %d", TM1Constants.TABLENAME_SUBSCRIBER, total, this.subscriberSize)); loadVoltTable(TM1Constants.TABLENAME_SUBSCRIBER, table); table.clearRowData(); assert(table.getRowCount() == 0); } } /** * Populate Access_Info table per benchmark spec. */ void genAccessInfo(Table catalog_tbl) { final VoltTable table = CatalogUtil.getVoltTable(catalog_tbl); int[] arr = { 1, 2, 3, 4 }; int[] ai_types = TM1Util.subArr(arr, 1, 4); long total = 0; for (long s_id = 0; s_id < this.subscriberSize; s_id++) { for (int ai_type : ai_types) { Object row[] = new Object[table.getColumnCount()]; row[0] = s_id; row[1] = ai_type; row[2] = TM1Util.number(0, 255); row[3] = TM1Util.number(0, 255); row[4] = TM1Util.astring(3, 3); row[5] = TM1Util.astring(5, 5); table.addRow(row); total++; } // FOR if (table.getRowCount() >= TM1Constants.BATCH_SIZE) { if (d) LOG.debug(String.format("%s: %6d / %d", TM1Constants.TABLENAME_ACCESS_INFO, total, ai_types.length * subscriberSize)); loadVoltTable(TM1Constants.TABLENAME_ACCESS_INFO, table); table.clearRowData(); } } // WHILE if (table.getRowCount() > 0) { if (d) LOG.debug(String.format("%s: %6d / %d", TM1Constants.TABLENAME_ACCESS_INFO, total, ai_types.length * subscriberSize)); loadVoltTable(TM1Constants.TABLENAME_ACCESS_INFO, table); table.clearRowData(); } } /** * Populate Special_Facility table and CallForwarding table per benchmark * spec. */ void genSpeAndCal(Table catalog_spe, Table catalog_cal) { VoltTable speTbl = CatalogUtil.getVoltTable(catalog_spe); VoltTable calTbl = CatalogUtil.getVoltTable(catalog_cal); long speTotal = 0; long calTotal = 0; int[] arrSpe = { 1, 2, 3, 4 }; int[] arrCal = { 0, 8, 6 }; for (long s_id = 0; s_id < this.subscriberSize; s_id++) { int[] sf_types = TM1Util.subArr(arrSpe, 1, 4); for (int sf_type : sf_types) { Object row_spe[] = new Object[speTbl.getColumnCount()]; row_spe[0] = s_id; row_spe[1] = sf_type; row_spe[2] = TM1Util.isActive(); row_spe[3] = TM1Util.number(0, 255); row_spe[4] = TM1Util.number(0, 255); row_spe[5] = TM1Util.astring(5, 5); speTbl.addRow(row_spe); speTotal++; // now call_forwarding int[] start_times = TM1Util.subArr(arrCal, 0, 3); for (int start_time : start_times) { Object row_cal[] = new Object[calTbl.getColumnCount()]; row_cal[0] = s_id; row_cal[1] = sf_type; row_cal[2] = start_time; row_cal[3] = start_time + TM1Util.number(1, 8); row_cal[4] = TM1Util.nstring(15, 15); calTbl.addRow(row_cal); calTotal++; } // FOR } // FOR if (calTbl.getRowCount() >= TM1Constants.BATCH_SIZE) { if (d) LOG.debug(String.format("%s: %d", TM1Constants.TABLENAME_CALL_FORWARDING, calTotal)); loadVoltTable(TM1Constants.TABLENAME_CALL_FORWARDING, calTbl); calTbl.clearRowData(); assert(calTbl.getRowCount() == 0); } if (speTbl.getRowCount() >= TM1Constants.BATCH_SIZE) { if (d) LOG.debug(String.format("%s: %d", TM1Constants.TABLENAME_SPECIAL_FACILITY, speTotal)); loadVoltTable(TM1Constants.TABLENAME_SPECIAL_FACILITY, speTbl); speTbl.clearRowData(); assert(speTbl.getRowCount() == 0); } } // WHILE if (calTbl.getRowCount() > 0) { if (d) LOG.debug(String.format("%s: %d", TM1Constants.TABLENAME_CALL_FORWARDING, calTotal)); loadVoltTable(TM1Constants.TABLENAME_CALL_FORWARDING, calTbl); calTbl.clearRowData(); assert(calTbl.getRowCount() == 0); } if (speTbl.getRowCount() > 0) { if (d) LOG.debug(String.format("%s: %d", TM1Constants.TABLENAME_SPECIAL_FACILITY, speTotal)); loadVoltTable(TM1Constants.TABLENAME_SPECIAL_FACILITY, speTbl); speTbl.clearRowData(); assert(speTbl.getRowCount() == 0); } } }