/*************************************************************************** * Copyright (C) 2012 by H-Store Project * * Brown University * * Massachusetts Institute of Technology * * Yale University * * * * Alex Kalinin (akalinin@cs.brown.edu) * * http://www.cs.brown.edu/~akalinin/ * * * * 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.generators; import java.util.Date; import org.apache.log4j.Logger; import org.voltdb.catalog.Table; import org.voltdb.types.TimestampType; import edu.brown.benchmark.tpce.TPCEConstants; import edu.brown.benchmark.tpce.generators.StatusTypeGenerator.StatusTypeId; import edu.brown.benchmark.tpce.generators.TPCEGenerator.InputFile; import edu.brown.benchmark.tpce.util.EGenDate; import edu.brown.benchmark.tpce.util.EGenRandom; public class CustomerGenerator extends TableGenerator { // percent of people in ages: <= 18, 19-24, 25-34, 35-44, 45-54, 55-64, 65-74, 75-84, >=85 private static final int[] agePercents = {5, 16, 17, 19, 16, 11, 8, 7, 1}; // min-max age brackets for corresponding percents private static final int[] ageBrackets = {10, 19, 25, 35, 45, 55, 65, 75, 85, 100}; // phone country code US/Canada private static final String usCountryCode = "011"; // email domains private static final String[] emailDomains = {"@msn.com", "@hotmail.com", "@rr.com", "@netzero.com", "@earthlink.com", "@attbi.com"}; /* * Number of RNG calls to skip for one row in order * to not use any of the random values from the previous row. */ private static final int RNG_SKIP_ONE_ROW_CUSTOMER = 35; // real max count in v3.5 of EGen: 29 private final long customersNum; private final long startCustomerId; private final long exchNum; // the number of exchange records private final long compNum; // the number of company records private final EGenRandom rnd; private final PersonHandler person; private final InputFileHandler statusType; private final InputFileHandler areaCodes; private long counter; public CustomerGenerator(Table catalog_tbl, TPCEGenerator generator) { super(catalog_tbl, generator); customersNum = generator.getCustomersNum(); startCustomerId = generator.getStartCustomer(); rnd = new EGenRandom(EGenRandom.RNG_SEED_TABLE_DEFAULT); person = new PersonHandler(generator.getInputFile(InputFile.LNAME), generator.getInputFile(InputFile.FEMFNAME), generator.getInputFile(InputFile.MALEFNAME)); statusType = generator.getInputFile(InputFile.STATUS); areaCodes = generator.getInputFile(InputFile.AREA); exchNum = generator.getInputFile(InputFile.EXCHANGE).getRecordsNum(); /* * The official EGen uses the number of companies in the input file. * That seems incorrect since the number of companies for the ADDRESS table * changes according to the total number of customers */ compNum = generator.getCompanyCount(generator.getTotalCustomers()); } private void initNextLoadUnit() { rnd.setSeedNth(EGenRandom.RNG_SEED_TABLE_DEFAULT, (counter + startCustomerId - 1) * RNG_SKIP_ONE_ROW_CUSTOMER); } public long generateCustomerId() { if (counter % TPCEConstants.DEFAULT_LOAD_UNIT == 0) { initNextLoadUnit(); } counter++; return counter + startCustomerId - 1 + TPCEConstants.IDENT_SHIFT; } public long getCurrentCId() { return counter + startCustomerId - 1 + TPCEConstants.IDENT_SHIFT; } private Date getDOB() { // first, determine the age bracket int per = rnd.intRange(1, 100); int bracket = 0; int curr_per = agePercents[0]; while (per > curr_per) { bracket++; curr_per += agePercents[bracket]; } // current date int year = EGenDate.getYear(); int month = EGenDate.getMonth(); int day = EGenDate.getDay(); if (month == 1 && day == 29) { // Feb 29 --> March 1 month = 2; day = 1; } // random is based on the number of days from Jan 1, 0001AD int daysMin = EGenDate.getDayNo(year - ageBrackets[bracket + 1], month, day) - 1; int daysMax = EGenDate.getDayNo(year - ageBrackets[bracket], month, day); int dobInDays = rnd.intRange(daysMin, daysMax); return EGenDate.getDateFromDayNo(dobInDays); } private long getAddrID(long cid) { return exchNum + compNum + cid; } private String getAreaCode(int num, long cid) { long oldSeed = rnd.getSeed(); switch (num) { case 1: rnd.setSeedNth(EGenRandom.RNG_SEED_BASE_C_AREA_1, cid); break; case 2: rnd.setSeedNth(EGenRandom.RNG_SEED_BASE_C_AREA_2, cid); break; case 3: rnd.setSeedNth(EGenRandom.RNG_SEED_BASE_C_AREA_3, cid); break; default: assert(false); } int key = rnd.intRange(0, areaCodes.getMaxKey()); rnd.setSeed(oldSeed); return areaCodes.getTupleByKey(key)[0]; } private String getLocal() { return rnd.rndAlphaNumFormatted("nnnnnnn"); } private String getExt(int num) { int threshold; switch (num) { case 1: threshold = 25; break; case 2: threshold = 15; break; case 3: threshold = 5; break; default: assert(false); threshold = 0; } int per = rnd.intRange(1, 100); if (per <= threshold) { return rnd.rndAlphaNumFormatted("nnn"); } else { return ""; } } private String[] getEmails(String lname, String fname) { int ind1 = rnd.intRange(0, emailDomains.length - 1); int ind2 = rnd.intRangeExclude(0, emailDomains.length - 1, ind1); String[] res = new String[2]; res[0] = fname.charAt(0) + lname + emailDomains[ind1]; res[1] = fname.charAt(0) + lname + emailDomains[ind2]; return res; } @Override public boolean hasNext() { return counter < customersNum; } @Override public Object[] next() { Object tuple[] = new Object[columnsNum]; long cid = generateCustomerId(); String[] namesAndtaxId = person.getFirstNameLastNameTaxID(cid); tuple[0] = cid; // c_id tuple[1] = namesAndtaxId[2]; // c_tax_id tuple[2] = statusType.getTupleByIndex(StatusTypeId.E_ACTIVE.ordinal())[0]; // c_st_id tuple[3] = namesAndtaxId[1]; // c_l_name tuple[4] = namesAndtaxId[0]; // c_f_name tuple[5] = person.getMiddleName(cid); // c_m_name tuple[6] = person.getGender(cid); // c_gndr tuple[7] = (short)CustomerSelection.getTier(cid).ordinal() + 1; // c_tier tuple[8] = new TimestampType(getDOB()); // c_dob tuple[9] = getAddrID(cid); // c_ad_id tuple[10] = usCountryCode; // c_ctry_1 tuple[11] = getAreaCode(1, cid); // c_area_1 tuple[12] = getLocal(); // c_local_1 tuple[13] = getExt(1); // c_ext_1 tuple[14] = usCountryCode; // c_ctry_2 tuple[15] = getAreaCode(2, cid); // c_area_2 tuple[16] = getLocal(); // c_local_2 tuple[17] = getExt(2); // c_ext_2 tuple[18] = usCountryCode; // c_ctry_3 tuple[19] = getAreaCode(3, cid); // c_area_3 tuple[20] = getLocal(); // c_local_3 tuple[21] = getExt(3); // c_ext_3 String[] emails = getEmails(namesAndtaxId[1], namesAndtaxId[0]); tuple[22] = emails[0]; // c_email_1 tuple[23] = emails[1]; // c_email_2 return tuple; } }