should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,373 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy
* - Doug Johnson
*/
#include "main/EGenTables_stdafx.h"
using namespace TPCE;
const UINT iUSACtryCode = 1; // must be the same as the code in country tax rates file
const UINT iCanadaCtryCode = 2; // must be the same as the code in country tax rates file
// Minimum and maximum to use when generating address street numbers.
const int iStreetNumberMin = 100;
const int iStreetNumberMax = 25000;
// Some customers have an AD_LINE_2, some are NULL.
const int iPctCustomersWithNullAD_LINE_2 = 60;
// Of the customers that have an AD_LINE_2, some are
// an apartment, others are a suite.
const int iPctCustomersWithAptAD_LINE_2 = 75;
// Minimum and maximum to use when generating apartment numbers.
const int iApartmentNumberMin = 1;
const int iApartmentNumberMax = 1000;
// Minimum and maximum to use when generating suite numbers.
const int iSuiteNumberMin = 1;
const int iSuiteNumberMax = 500;
// Number of RNG calls to skip for one row in order
// to not use any of the random values from the previous row.
const int iRNGSkipOneRowAddress = 10; // real number in 3.5: 7
/*
* Constructor for the ADDRESS table class.
*
* PARAMETERS:
* IN inputFiles - input flat files loaded in memory
* IN iCustomerCount - number of customers to generate
* IN iStartFromCustomer - ordinal position of the first customer in
* the sequence (Note: 1-based) for whom to generate the addresses. Used if
* generating customer addresses only. IN bCustomerAddressesOnly - if true,
* generate only customer addresses if false, generate exchange, company, and
* customer addresses (always start from the first customer in this case)
*/
CAddressTable::CAddressTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer,
bool bCustomerAddressesOnly, bool bCacheEnabled)
: TableTemplate<ADDRESS_ROW>(), m_companies(dfm.CompanyFile()), m_Street(dfm.StreetNameDataFile()),
m_StreetSuffix(dfm.StreetSuffixDataFile()), m_ZipCode(dfm.ZipCodeDataFile()),
m_iStartFromCustomer(iStartFromCustomer), m_iCustomerCount(iCustomerCount),
m_bCustomerAddressesOnly(bCustomerAddressesOnly), m_bCustomerAddress(bCustomerAddressesOnly),
m_bCacheEnabled(bCacheEnabled), INVALID_CACHE_ENTRY(-1) {
m_iExchangeCount = dfm.ExchangeDataFile().size(); // number of rows in Exchange
m_iCompanyCount = m_companies.GetConfiguredCompanyCount(); // number of configured companies
// Generate customer addresses only (used for CUSTOMER_TAXRATE)
if (bCustomerAddressesOnly) {
// skip exchanges and companies
m_iLastRowNumber = m_iExchangeCount + m_iCompanyCount + iStartFromCustomer - 1;
// This is not really a count, but the last address row to generate.
//
m_iTotalAddressCount = m_iLastRowNumber + m_iCustomerCount;
} else { // Generating not only customer, but also exchange and company
// addresses
m_iLastRowNumber = iStartFromCustomer - 1;
// This is not really a count, but the last address row to generate.
//
m_iTotalAddressCount = m_iLastRowNumber + m_iCustomerCount + m_iExchangeCount + m_iCompanyCount;
}
m_row.AD_ID = m_iLastRowNumber + iTIdentShift; // extend to 64 bits for address id
if (m_bCacheEnabled) {
m_iCacheSize = (int)iDefaultLoadUnitSize;
m_iCacheOffset = iTIdentShift + m_iExchangeCount + m_iCompanyCount + m_iStartFromCustomer;
m_CacheZipCode = new int[m_iCacheSize];
for (int i = 0; i < m_iCacheSize; i++) {
m_CacheZipCode[i] = INVALID_CACHE_ENTRY;
}
}
}
CAddressTable::~CAddressTable() {
if (m_bCacheEnabled) {
delete[] m_CacheZipCode;
}
}
/*
* Reset the state for the next load unit.
*
* PARAMETERS:
* none.
*
* RETURNS:
* none.
*/
void CAddressTable::InitNextLoadUnit() {
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault, (RNGSEED)m_iLastRowNumber * iRNGSkipOneRowAddress));
ClearRecord(); // this is needed for EGenTest to work
if (m_bCacheEnabled) {
m_iCacheOffset += iDefaultLoadUnitSize;
for (int i = 0; i < m_iCacheSize; i++) {
m_CacheZipCode[i] = INVALID_CACHE_ENTRY;
}
}
}
/*
* Generates the next A_ID value.
* It is stored in the internal record structure and also returned.
* The number of rows generated is incremented. This is why
* this function cannot be called more than once for a record.
*
* PARAMETERS:
* none.
*
* RETURNS:
* next address id.
*/
TIdent CAddressTable::GenerateNextAD_ID() {
// Reset RNG at Load Unit boundary, so that all data is repeatable.
//
if (m_iLastRowNumber > (m_iExchangeCount + m_iCompanyCount) &&
((m_iLastRowNumber - (m_iExchangeCount + m_iCompanyCount)) % iDefaultLoadUnitSize == 0)) {
InitNextLoadUnit();
}
++m_iLastRowNumber;
// Find out whether this next row is for a customer (so as to generate
// AD_LINE_2). Exchange and Company addresses are before Customer ones.
//
m_bCustomerAddress = m_iLastRowNumber >= m_iExchangeCount + m_iCompanyCount;
// update state info
m_bMoreRecords = m_iLastRowNumber < m_iTotalAddressCount;
m_row.AD_ID = m_iLastRowNumber + iTIdentShift;
return m_row.AD_ID;
}
/*
* Returns the address id of the customer specified by the customer id.
*
* PARAMETERS:
* IN C_ID - customer id (1-based)
*
* RETURNS:
* address id.
*/
TIdent CAddressTable::GetAD_IDForCustomer(TIdent C_ID) {
return m_iExchangeCount + m_iCompanyCount + C_ID;
}
/*
* Generate AD_LINE_1 and store it in the record structure.
* Does not increment the number of rows generated.
*
* PARAMETERS:
* none.
*
* RETURNS:
* none.
*/
void CAddressTable::GenerateAD_LINE_1() {
int iStreetNum = m_rnd.RndIntRange(iStreetNumberMin, iStreetNumberMax);
// int iStreetThreshold = m_rnd.RndIntRange(0,
// m_Street->GetGreatestKey()-2);
int iStreetThreshold = m_rnd.RndIntRange(0, m_Street.size() - 2);
int iStreetSuffixThreshold = m_rnd.RndIntRange(0, m_StreetSuffix.size() - 1);
snprintf(m_row.AD_LINE1, sizeof(m_row.AD_LINE1), "%d %s %s", iStreetNum, m_Street[iStreetThreshold].STREET_CSTR(),
m_StreetSuffix[iStreetSuffixThreshold].SUFFIX_CSTR());
}
/*
* Generate AD_LINE_2 and store it in the record structure.
* Does not increment the number of rows generated.
*
* PARAMETERS:
* none.
*
* RETURNS:
* none.
*/
void CAddressTable::GenerateAD_LINE_2() {
if (!m_bCustomerAddress || m_rnd.RndPercent(iPctCustomersWithNullAD_LINE_2)) { // Generate second address line
// only for customers (not
// companies)
m_row.AD_LINE2[0] = '\0';
} else {
if (m_rnd.RndPercent(iPctCustomersWithAptAD_LINE_2)) {
snprintf(m_row.AD_LINE2, sizeof(m_row.AD_LINE2), "Apt. %d",
m_rnd.RndIntRange(iApartmentNumberMin, iApartmentNumberMax));
} else {
snprintf(m_row.AD_LINE2, sizeof(m_row.AD_LINE2), "Suite %d",
m_rnd.RndIntRange(iSuiteNumberMin, iSuiteNumberMax));
}
}
}
/*
* For a given address id returns the same Threshold used to
* select the town, division, zip, and country.
* Needed to return a specific division/country for a given address id (for
* customer tax rates).
*
* PARAMETERS:
* IN ADID - address id
*
* RETURNS:
* none.
*/
int CAddressTable::GetTownDivisionZipCodeThreshold(TIdent ADID) {
RNGSEED OldSeed;
int iThreshold;
OldSeed = m_rnd.GetSeed();
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseTownDivZip, (RNGSEED)ADID));
iThreshold = m_rnd.RndIntRange(0, m_ZipCode.size() - 1);
m_rnd.SetSeed(OldSeed);
return (iThreshold);
}
/*
* Return the country code code for a given zip code.
*
* PARAMETERS:
* IN szZipCode - string with a US or Canada zip code
*
* RETURNS:
* country code.
*/
UINT CAddressTable::GetCountryCode(const char *szZipCode) {
if (('0' <= szZipCode[0]) && (szZipCode[0] <= '9')) {
// If the zip code starts with a number, then it's a USA code.
return (iUSACtryCode);
} else {
// If the zip code does NOT start with a number, than it's a Canadian
// code.
return (iCanadaCtryCode);
}
}
/*
* Return a certain division/country code (from the input file) for a given
* address id. Used in the loader to properly calculate tax on a trade.
*
* PARAMETERS:
* IN AD_ID - address id
* OUT iDivCode - division (state/province) code
* OUT iCtryCode - country (USA/CANADA) code
*
* RETURNS:
* none.
*/
void CAddressTable::GetDivisionAndCountryCodesForAddress(TIdent AD_ID, UINT &iDivCode, UINT &iCtryCode) {
// const TZipCodeInputRow* pZipCodeInputRow = NULL;
// We will sometimes get AD_ID values that are outside the current
// load unit (cached range). We need to check for this case
// and avoid the lookup (as we will segfault or get bogus data.)
TIdent index = AD_ID - m_iCacheOffset;
bool bCheckCache = (index >= 0 && index <= m_iCacheSize);
if (m_bCacheEnabled && bCheckCache && (INVALID_CACHE_ENTRY != m_CacheZipCode[index])) {
// Make use of the cache to get the data.
iDivCode = m_ZipCode[m_CacheZipCode[index]].DivisionTaxKey();
iCtryCode = GetCountryCode(m_ZipCode[m_CacheZipCode[index]].ZC_CODE_CSTR());
// We're done, so bail out.
return;
}
// The cache wasn't used so get the necessary value.
int iThreshold = GetTownDivisionZipCodeThreshold(AD_ID);
// If possible, cache the result in case we need it again.
if (m_bCacheEnabled && bCheckCache) {
m_CacheZipCode[index] = iThreshold;
}
// Get the data.
iDivCode = m_ZipCode[iThreshold].DivisionTaxKey();
iCtryCode = GetCountryCode(m_ZipCode[iThreshold].ZC_CODE_CSTR());
}
/*
* Generate zip code and country for the current address id
* and store them in the record structure.
* Does not increment the number of rows generated.
*
* PARAMETERS:
* none.
*
* RETURNS:
* none.
*/
void CAddressTable::GenerateAD_ZC_CODE_CTRY() {
int iThreshold;
iThreshold = GetTownDivisionZipCodeThreshold(m_row.AD_ID);
const ZipCodeDataFileRecord &dfr = m_ZipCode[iThreshold];
strncpy(m_row.AD_ZC_CODE, dfr.ZC_CODE_CSTR(), sizeof(m_row.AD_ZC_CODE));
if (iUSACtryCode == GetCountryCode(dfr.ZC_CODE_CSTR())) { // US state
strncpy(m_row.AD_CTRY, "USA", sizeof(m_row.AD_CTRY));
} else { // Canadian province
strncpy(m_row.AD_CTRY, "CANADA", sizeof(m_row.AD_CTRY));
}
}
/*
* Generate all column values for the next row
* and store them in the record structure.
* Increment the number of rows generated.
*
* PARAMETERS:
* none.
*
* RETURNS:
* TRUE, if there are more records in the ADDRESS table; FALSE
* othewise.
*/
bool CAddressTable::GenerateNextRecord() {
GenerateNextAD_ID();
GenerateAD_LINE_1();
GenerateAD_LINE_2();
GenerateAD_ZC_CODE_CTRY();
// Return false if all the rows have been generated
return (MoreRecords());
}

View File

@@ -0,0 +1,150 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Matt Emmerton
*/
/******************************************************************************
* Description: This file implements the interface for data logging.
******************************************************************************/
#include <iostream>
#include <sstream>
#include "utilities/EGenStandardTypes.h"
#include "main/DriverTypes.h"
#include "main/DriverParamSettings.h"
#include "main/BaseLogger.h"
#include "main/BaseLogFormatter.h"
using namespace TPCE;
char TPCE::szDriverTypeNames[eDriverMax][14] = {"EGenLoader", "EGenDriverAll", "EGenDriverCE", "EGenDriverMEE",
"EGenDriverDM"};
/* Constructor */
CBaseLogger::CBaseLogger(eDriverType drvType, INT32 UniqueId, CBaseLogFormatter *pFormatter)
: m_pLogFormatter(pFormatter) {
char m_Version[32];
// Get EGen Version
GetEGenVersionString(m_Version, sizeof(m_Version));
// Generate Log Prefix String
snprintf(&m_Prefix[0], sizeof(m_Prefix), "%s (%s) %d", szDriverTypeNames[drvType], m_Version, UniqueId);
}
/* Methods */
bool CBaseLogger::SendToLogger(const char *szPrefix, const char *szMsg) {
CDateTime curTime;
return SendToLoggerImpl(szPrefix, curTime.ToStr(12), szMsg);
}
// Strings
bool CBaseLogger::SendToLogger(const char *str) {
return SendToLogger(m_Prefix, str);
}
bool CBaseLogger::SendToLogger(string str) {
return SendToLogger(str.c_str());
}
// Parameter Structures
bool CBaseLogger::SendToLogger(CLoaderSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CDriverGlobalSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CDriverCESettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CDriverCEPartitionSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CDriverMEESettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CDriverDMSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CBrokerVolumeSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CCustomerPositionSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CMarketWatchSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CSecurityDetailSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CTradeLookupSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CTradeOrderSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CTradeUpdateSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(CTxnMixGeneratorSettings &parms) {
return SendToLogger(m_pLogFormatter->GetLogOutput(parms));
}
bool CBaseLogger::SendToLogger(TDriverCETxnSettings &parms) {
bool result = false;
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.BV_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.CP_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.MW_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.SD_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.TL_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.TO_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.TU_settings));
result |= SendToLogger(m_pLogFormatter->GetLogOutput(parms.TxnMixGenerator_settings));
return result;
}

View File

@@ -0,0 +1,276 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson, Matt Emmerton
*/
/******************************************************************************
* Description: Implementation of the CE class.
* See CE.h for a description.
******************************************************************************/
#include "main/CE.h"
using namespace TPCE;
// Initialization that is common for all constructors.
void CCE::Initialize(PDriverCETxnSettings pTxnParamSettings) {
m_pLogger->SendToLogger(m_DriverGlobalSettings);
// Always configure the CE with default settings, to ensure that it is
// set up properly.
SetTxnTunables(&m_DriverCETxnSettings);
// If user tunables are provided, set them now. If they are invalid, they
// will not be used and we will continue to use the defaults set above.
if (pTxnParamSettings) {
SetTxnTunables(pTxnParamSettings);
}
}
// Automatically generate unique RNG seeds.
// The CRandom class uses an unsigned 64-bit value for the seed.
// This routine automatically generates two unique seeds. One is used for
// the TxnInput generator RNG, and the other is for the TxnMixGenerator RNG.
// The 64 bits are used as follows.
//
// Bits 0 - 31 Caller provided unique unsigned 32-bit id.
// Bit 32 0 for TxnInputGenerator, 1 for TxnMixGenerator
// Bits 33 - 43 Number of days since the base time. The base time
// is set to be January 1 of the most recent year that is
// a multiple of 5. This allows enough space for the last
// field, and it makes the algorithm "timeless" by resetting
// the generated values every 5 years.
// Bits 44 - 63 Current time of day measured in 1/10's of a second.
//
void CCE::AutoSetRNGSeeds(UINT32 UniqueId) {
CDateTime Now;
INT32 BaseYear;
INT32 Tmp1, Tmp2;
Now.GetYMD(&BaseYear, &Tmp1, &Tmp2);
// Set the base year to be the most recent year that was a multiple of 5.
BaseYear -= (BaseYear % 5);
CDateTime Base(BaseYear, 1, 1); // January 1st in the BaseYear
// Initialize the seed with the current time of day measured in 1/10's of a
// second. This will use up to 20 bits.
RNGSEED Seed;
Seed = Now.MSec() / 100;
// Now add in the number of days since the base time.
// The number of days in the 5 year period requires 11 bits.
// So shift up by that much to make room in the "lower" bits.
Seed <<= 11;
Seed += (RNGSEED)((INT64)Now.DayNo() - (INT64)Base.DayNo());
// So far, we've used up 31 bits.
// Save the "last" bit of the "upper" 32 for the RNG id.
// In addition, make room for the caller's 32-bit unique id.
// So shift a total of 33 bits.
Seed <<= 33;
// Now the "upper" 32-bits have been set with a value for RNG 0.
// Add in the sponsor's unique id for the "lower" 32-bits.
Seed += UniqueId;
// Set the TxnMixGenerator RNG to the unique seed.
m_TxnMixGenerator.SetRNGSeed(Seed);
m_DriverCESettings.cur.TxnMixRNGSeed = Seed;
// Set the RNG Id to 1 for the TxnInputGenerator.
Seed |= UINT64_CONST(0x0000000100000000);
m_TxnInputGenerator.SetRNGSeed(Seed);
m_DriverCESettings.cur.TxnInputRNGSeed = Seed;
}
/*
* Constructor - no partitioning by C_ID, automatic RNG seed generation
* (requires unique input)
*/
CCE::CCE(CCESUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iDaysOfInitialTrades, UINT32 UniqueId,
const PDriverCETxnSettings pDriverCETxnSettings)
: m_DriverGlobalSettings(iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor, iDaysOfInitialTrades),
m_DriverCESettings(UniqueId, 0, 0), m_pSUT(pSUT), m_pLogger(pLogger),
m_TxnMixGenerator(&m_DriverCETxnSettings, m_pLogger),
m_TxnInputGenerator(dfm, iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor,
iDaysOfInitialTrades * HoursPerWorkDay, m_pLogger, &m_DriverCETxnSettings) {
m_pLogger->SendToLogger("CE object constructed using constructor 1 (valid "
"for publication: YES).");
Initialize(pDriverCETxnSettings);
AutoSetRNGSeeds(UniqueId);
m_pLogger->SendToLogger(m_DriverCESettings); // log the RNG seeds
}
/*
* Constructor - no partitioning by C_ID, RNG seeds provided
*/
CCE::CCE(CCESUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iDaysOfInitialTrades, UINT32 UniqueId,
RNGSEED TxnMixRNGSeed, RNGSEED TxnInputRNGSeed, const PDriverCETxnSettings pDriverCETxnSettings)
: m_DriverGlobalSettings(iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor, iDaysOfInitialTrades),
m_DriverCESettings(UniqueId, TxnMixRNGSeed, TxnInputRNGSeed), m_pSUT(pSUT), m_pLogger(pLogger),
m_TxnMixGenerator(&m_DriverCETxnSettings, TxnMixRNGSeed, m_pLogger),
m_TxnInputGenerator(dfm, iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor,
iDaysOfInitialTrades * HoursPerWorkDay, TxnInputRNGSeed, m_pLogger, &m_DriverCETxnSettings) {
m_pLogger->SendToLogger("CE object constructed using constructor 2 (valid "
"for publication: NO).");
Initialize(pDriverCETxnSettings);
m_pLogger->SendToLogger(m_DriverCESettings); // log the RNG seeds
}
/*
* Constructor - partitioning by C_ID, automatic RNG seed generation (requires
* unique input)
*/
CCE::CCE(CCESUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, TIdent iMyStartingCustomerId, TIdent iMyCustomerCount, INT32 iPartitionPercent,
INT32 iScaleFactor, INT32 iDaysOfInitialTrades, UINT32 UniqueId,
const PDriverCETxnSettings pDriverCETxnSettings)
: m_DriverGlobalSettings(iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor, iDaysOfInitialTrades),
m_DriverCESettings(UniqueId, 0, 0),
m_DriverCEPartitionSettings(iMyStartingCustomerId, iMyCustomerCount, iPartitionPercent), m_pSUT(pSUT),
m_pLogger(pLogger), m_TxnMixGenerator(&m_DriverCETxnSettings, m_pLogger),
m_TxnInputGenerator(dfm, iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor,
iDaysOfInitialTrades * HoursPerWorkDay, iMyStartingCustomerId, iMyCustomerCount,
iPartitionPercent, m_pLogger, &m_DriverCETxnSettings) {
m_pLogger->SendToLogger("CE object constructed using constructor 3 (valid "
"for publication: YES).");
Initialize(pDriverCETxnSettings);
AutoSetRNGSeeds(UniqueId);
m_pLogger->SendToLogger(m_DriverCEPartitionSettings); // log the partition settings
m_pLogger->SendToLogger(m_DriverCESettings); // log the RNG seeds
}
/*
* Constructor - partitioning by C_ID, RNG seeds provided
*/
CCE::CCE(CCESUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, TIdent iMyStartingCustomerId, TIdent iMyCustomerCount, INT32 iPartitionPercent,
INT32 iScaleFactor, INT32 iDaysOfInitialTrades, UINT32 UniqueId, RNGSEED TxnMixRNGSeed,
RNGSEED TxnInputRNGSeed, const PDriverCETxnSettings pDriverCETxnSettings)
: m_DriverGlobalSettings(iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor, iDaysOfInitialTrades),
m_DriverCESettings(UniqueId, TxnMixRNGSeed, TxnInputRNGSeed),
m_DriverCEPartitionSettings(iMyStartingCustomerId, iMyCustomerCount, iPartitionPercent), m_pSUT(pSUT),
m_pLogger(pLogger), m_TxnMixGenerator(&m_DriverCETxnSettings, TxnMixRNGSeed, m_pLogger),
m_TxnInputGenerator(dfm, iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor,
iDaysOfInitialTrades * HoursPerWorkDay, iMyStartingCustomerId, iMyCustomerCount,
iPartitionPercent, TxnInputRNGSeed, m_pLogger, &m_DriverCETxnSettings) {
m_pLogger->SendToLogger("CE object constructed using constructor 4 (valid "
"for publication: NO).");
Initialize(pDriverCETxnSettings);
m_pLogger->SendToLogger(m_DriverCEPartitionSettings); // log the partition settings
m_pLogger->SendToLogger(m_DriverCESettings); // log the RNG seeds
}
CCE::~CCE(void) {
m_pLogger->SendToLogger("CE object destroyed.");
}
RNGSEED CCE::GetTxnInputGeneratorRNGSeed(void) {
return (m_TxnInputGenerator.GetRNGSeed());
}
RNGSEED CCE::GetTxnMixGeneratorRNGSeed(void) {
return (m_TxnMixGenerator.GetRNGSeed());
}
void CCE::SetTxnTunables(const PDriverCETxnSettings pTxnParamSettings) {
if (pTxnParamSettings->IsValid()) {
// Update Tunables
if (pTxnParamSettings != &m_DriverCETxnSettings) // only copy from a different location
{
m_DriverCETxnSettings = *pTxnParamSettings;
}
// Trigger Runtime Updates
m_TxnMixGenerator.UpdateTunables();
m_TxnInputGenerator.UpdateTunables();
} else {
m_pLogger->SendToLogger("ERROR: CCE::SetTxnTunables() failed due to invalid tunables.");
}
}
void CCE::DoTxn(void) {
int iTxnType = m_TxnMixGenerator.GenerateNextTxnType();
switch (iTxnType) {
case CCETxnMixGenerator::BROKER_VOLUME:
m_TxnInputGenerator.GenerateBrokerVolumeInput(m_BrokerVolumeTxnInput);
m_pSUT->BrokerVolume(&m_BrokerVolumeTxnInput);
break;
case CCETxnMixGenerator::CUSTOMER_POSITION:
m_TxnInputGenerator.GenerateCustomerPositionInput(m_CustomerPositionTxnInput);
m_pSUT->CustomerPosition(&m_CustomerPositionTxnInput);
break;
case CCETxnMixGenerator::MARKET_WATCH:
m_TxnInputGenerator.GenerateMarketWatchInput(m_MarketWatchTxnInput);
m_pSUT->MarketWatch(&m_MarketWatchTxnInput);
break;
case CCETxnMixGenerator::SECURITY_DETAIL:
m_TxnInputGenerator.GenerateSecurityDetailInput(m_SecurityDetailTxnInput);
m_pSUT->SecurityDetail(&m_SecurityDetailTxnInput);
break;
case CCETxnMixGenerator::TRADE_LOOKUP:
m_TxnInputGenerator.GenerateTradeLookupInput(m_TradeLookupTxnInput);
m_pSUT->TradeLookup(&m_TradeLookupTxnInput);
break;
case CCETxnMixGenerator::TRADE_ORDER:
bool bExecutorIsAccountOwner;
INT32 iTradeType;
m_TxnInputGenerator.GenerateTradeOrderInput(m_TradeOrderTxnInput, iTradeType, bExecutorIsAccountOwner);
m_pSUT->TradeOrder(&m_TradeOrderTxnInput, iTradeType, bExecutorIsAccountOwner);
break;
case CCETxnMixGenerator::TRADE_STATUS:
m_TxnInputGenerator.GenerateTradeStatusInput(m_TradeStatusTxnInput);
m_pSUT->TradeStatus(&m_TradeStatusTxnInput);
break;
case CCETxnMixGenerator::TRADE_UPDATE:
m_TxnInputGenerator.GenerateTradeUpdateInput(m_TradeUpdateTxnInput);
m_pSUT->TradeUpdate(&m_TradeUpdateTxnInput);
break;
default:
cerr << "CE: Generated illegal transaction" << endl;
exit(1);
}
}

View File

@@ -0,0 +1,960 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy, Doug Johnson, Matt Emmerton
*/
#include "main/CETxnInputGenerator.h"
#include "main/DailyMarketTable.h"
#include "main/TradeTypeIDs.h"
using namespace TPCE;
/*
* Constructor - no partitioning by C_ID.
*
* PARAMETERS:
* IN dfm - Data file manager
* IN iConfiguredCustomerCount - number of configured customers in
* the database IN iActiveCustomerCount - number of active customers in
* the database IN iScaleFactor - scale factor (number of
* customers per 1 tpsE) of the database IN iHoursOfInitialTrades -
* number of hours of the initial trades portion of the database IN pLogger -
* reference to parameter logging object IN pDriverCETxnSettings -
* initial transaction parameter settings
*
* RETURNS:
* not applicable.
*/
CCETxnInputGenerator::CCETxnInputGenerator(const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iHoursOfInitialTrades,
CBaseLogger *pLogger,
const PDriverCETxnSettings pDriverCETxnSettings)
: m_rnd(RNGSeedBaseTxnInputGenerator) // initialize with a default seed
,
m_Person(dfm, 0, false), m_CustomerSelection(&m_rnd, iDefaultStartFromCustomer, iActiveCustomerCount),
m_AccsAndPerms(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Holdings(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Brokers(dfm, iActiveCustomerCount, iDefaultStartFromCustomer), m_pCompanies(dfm.CompanyFile()),
m_pSecurities(dfm.SecurityFile()), m_pIndustries(dfm.IndustryDataFile()), m_pSectors(dfm.SectorDataFile()),
m_pStatusType(dfm.StatusTypeDataFile()), m_pTradeType(dfm.TradeTypeDataFile()),
m_pDriverCETxnSettings(pDriverCETxnSettings), m_pLogger(pLogger),
m_iConfiguredCustomerCount(iConfiguredCustomerCount), m_iActiveCustomerCount(iActiveCustomerCount),
m_iMyStartingCustomerId(iDefaultStartFromCustomer), m_iMyCustomerCount(iActiveCustomerCount),
m_iPartitionPercent(100), m_iScaleFactor(iScaleFactor), m_iHoursOfInitialTrades(iHoursOfInitialTrades) {
Initialize();
}
/*
* Constructor - no partitioning by C_ID, RNG seed provided.
*
* RNG seed is for testing/engineering work allowing repeatable transaction
* parameter stream. This constructor is NOT legal for a benchmark publication.
*
* PARAMETERS:
* IN dfm - Data file manager
* IN iConfiguredCustomerCount - number of configured customers in
* the database IN iActiveCustomerCount - number of active customers in
* the database IN iScaleFactor - scale factor (number of
* customers per 1 tpsE) of the database IN iHoursOfInitialTrades -
* number of hours of the initial trades portion of the database IN RNGSeed -
* initial seed for random number generator IN pLogger -
* reference to parameter logging object IN pDriverCETxnSettings -
* initial transaction parameter settings
*
* RETURNS:
* not applicable.
*/
CCETxnInputGenerator::CCETxnInputGenerator(const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iHoursOfInitialTrades,
RNGSEED RNGSeed, CBaseLogger *pLogger,
const PDriverCETxnSettings pDriverCETxnSettings)
: m_rnd(RNGSeed) // to be predictable
,
m_Person(dfm, 0, false), m_CustomerSelection(&m_rnd, iDefaultStartFromCustomer, iActiveCustomerCount),
m_AccsAndPerms(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Holdings(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Brokers(dfm, iActiveCustomerCount, iDefaultStartFromCustomer), m_pCompanies(dfm.CompanyFile()),
m_pSecurities(dfm.SecurityFile()), m_pIndustries(dfm.IndustryDataFile()), m_pSectors(dfm.SectorDataFile()),
m_pStatusType(dfm.StatusTypeDataFile()), m_pTradeType(dfm.TradeTypeDataFile()),
m_pDriverCETxnSettings(pDriverCETxnSettings), m_pLogger(pLogger),
m_iConfiguredCustomerCount(iConfiguredCustomerCount), m_iActiveCustomerCount(iActiveCustomerCount),
m_iMyStartingCustomerId(iDefaultStartFromCustomer), m_iMyCustomerCount(iActiveCustomerCount),
m_iPartitionPercent(100), m_iScaleFactor(iScaleFactor), m_iHoursOfInitialTrades(iHoursOfInitialTrades) {
Initialize();
}
/*
* Constructor - partitioning by C_ID.
*
* PARAMETERS:
* IN dfm - Data file manager
* IN iConfiguredCustomerCount - number of configured customers in
* the database IN iActiveCustomerCount - number of active customers in
* the database IN iScaleFactor - scale factor (number of
* customers per 1 tpsE) of the database IN iHoursOfInitialTrades -
* number of hours of the initial trades portion of the database IN
* iMyStartingCustomerId - first customer id (1-based) of the partition
* for this instance IN iMyCustomerCount - number of customers in
* the partition for this instance IN iPartitionPercent - the
* percentage of C_IDs generated within this instance's partition IN pLogger -
* reference to parameter logging object IN pDriverCETxnSettings -
* initial transaction parameter settings
*
* RETURNS:
* not applicable.
*/
CCETxnInputGenerator::CCETxnInputGenerator(const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iHoursOfInitialTrades,
TIdent iMyStartingCustomerId, TIdent iMyCustomerCount,
INT32 iPartitionPercent, CBaseLogger *pLogger,
const PDriverCETxnSettings pDriverCETxnSettings)
: m_rnd(RNGSeedBaseTxnInputGenerator) // initialize with a default seed
,
m_Person(dfm, 0, false), m_CustomerSelection(&m_rnd, iDefaultStartFromCustomer, iActiveCustomerCount,
iPartitionPercent, iMyStartingCustomerId, iMyCustomerCount),
m_AccsAndPerms(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Holdings(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Brokers(dfm, iActiveCustomerCount, iDefaultStartFromCustomer), m_pCompanies(dfm.CompanyFile()),
m_pSecurities(dfm.SecurityFile()), m_pIndustries(dfm.IndustryDataFile()), m_pSectors(dfm.SectorDataFile()),
m_pStatusType(dfm.StatusTypeDataFile()), m_pTradeType(dfm.TradeTypeDataFile()),
m_pDriverCETxnSettings(pDriverCETxnSettings), m_pLogger(pLogger),
m_iConfiguredCustomerCount(iConfiguredCustomerCount), m_iActiveCustomerCount(iActiveCustomerCount),
m_iMyStartingCustomerId(iMyStartingCustomerId), m_iMyCustomerCount(iMyCustomerCount),
m_iPartitionPercent(iPartitionPercent), m_iScaleFactor(iScaleFactor),
m_iHoursOfInitialTrades(iHoursOfInitialTrades) {
Initialize();
}
/*
* Constructor - partitioning by C_ID, RNG seed provided.
*
* RNG seed is for testing/engineering work allowing repeatable transaction
* parameter stream. This constructor is NOT legal for a benchmark publication.
*
* PARAMETERS:
* IN dfm - Data file manager
* IN iConfiguredCustomerCount - number of configured customers in
* the database IN iActiveCustomerCount - number of active customers in
* the database IN iScaleFactor - scale factor (number of
* customers per 1 tpsE) of the database IN iHoursOfInitialTrades -
* number of hours of the initial trades portion of the database IN
* iMyStartingCustomerId - first customer id (1-based) of the partition
* for this instance IN iMyCustomerCount - number of customers in
* the partition for this instance IN iPartitionPercent - the
* percentage of C_IDs generated within this instance's partition IN pLogger -
* reference to parameter logging object IN pDriverCETxnSettings -
* initial transaction parameter settings
*
* RETURNS:
* not applicable.
*/
CCETxnInputGenerator::CCETxnInputGenerator(const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iHoursOfInitialTrades,
TIdent iMyStartingCustomerId, TIdent iMyCustomerCount,
INT32 iPartitionPercent, RNGSEED RNGSeed, CBaseLogger *pLogger,
const PDriverCETxnSettings pDriverCETxnSettings)
: m_rnd(RNGSeed) // to be predictable
,
m_Person(dfm, 0, false), m_CustomerSelection(&m_rnd, iDefaultStartFromCustomer, iActiveCustomerCount,
iPartitionPercent, iMyStartingCustomerId, iMyCustomerCount),
m_AccsAndPerms(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Holdings(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Brokers(dfm, iActiveCustomerCount, iDefaultStartFromCustomer), m_pCompanies(dfm.CompanyFile()),
m_pSecurities(dfm.SecurityFile()), m_pIndustries(dfm.IndustryDataFile()), m_pSectors(dfm.SectorDataFile()),
m_pStatusType(dfm.StatusTypeDataFile()), m_pTradeType(dfm.TradeTypeDataFile()),
m_pDriverCETxnSettings(pDriverCETxnSettings), m_pLogger(pLogger),
m_iConfiguredCustomerCount(iConfiguredCustomerCount), m_iActiveCustomerCount(iActiveCustomerCount),
m_iMyStartingCustomerId(iMyStartingCustomerId), m_iMyCustomerCount(iMyCustomerCount),
m_iPartitionPercent(iPartitionPercent), m_iScaleFactor(iScaleFactor),
m_iHoursOfInitialTrades(iHoursOfInitialTrades) {
Initialize();
}
/*
* Perform initialization common to all constructors.
*
* PARAMETERS:
* IN pDriverCETxnSettings - initial transaction parameter
* settings
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::Initialize() {
m_iActiveCompanyCount = m_pCompanies.GetActiveCompanyCount();
m_iActiveSecurityCount = m_pSecurities.GetActiveSecurityCount();
m_iIndustryCount = m_pIndustries.size();
m_iSectorCount = m_pSectors.size();
m_iStartFromCompany = m_pCompanies.GetCompanyId(0); // from the first company
// In order for this computation to overflow an INT64, assuming that all
// multiplications are executed before divisions and the default value
// for ITD is used, the active customer count must be greater than 2.1e10
// (21 billion customers). I hope we never get to that point.
// NOTE: (iAbortTrade / 100) = 1.01, which is compensation for rollbacks.
m_iMaxActivePrePopulatedTradeID = m_iHoursOfInitialTrades;
m_iMaxActivePrePopulatedTradeID *= SecondsPerHour;
m_iMaxActivePrePopulatedTradeID *= m_iActiveCustomerCount;
m_iMaxActivePrePopulatedTradeID /= m_iScaleFactor;
m_iMaxActivePrePopulatedTradeID *= iAbortTrade;
m_iMaxActivePrePopulatedTradeID /= 100;
// Set the start time (time 0) to the base time
m_StartTime.Set(InitialTradePopulationBaseYear, InitialTradePopulationBaseMonth, InitialTradePopulationBaseDay,
InitialTradePopulationBaseHour, InitialTradePopulationBaseMinute, InitialTradePopulationBaseSecond,
InitialTradePopulationBaseFraction);
// UpdateTunables() is called from CCE constructor (Initialize)
}
/*
* Return internal random number generator seed.
*
* PARAMETERS:
* none.
*
* RETURNS:
* current random number generator seed.
*/
RNGSEED CCETxnInputGenerator::GetRNGSeed(void) {
return (m_rnd.GetSeed());
}
/*
* Set internal random number generator seed.
*
* PARAMETERS:
* IN RNGSeed - new random number generator seed
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::SetRNGSeed(RNGSEED RNGSeed) {
m_rnd.SetSeed(RNGSeed);
}
/*
* Refresh internal information from the external transaction parameters.
* This function should be called anytime the external transaction
* parameter structure changes.
*
* PARAMETERS:
* none.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::UpdateTunables(void) {
INT64 secondsOfInitialTrades = (INT64)m_iHoursOfInitialTrades * SecondsPerHour;
m_iTradeLookupFrame2MaxTimeInMilliSeconds =
(INT64)(secondsOfInitialTrades - ((INT64)m_pDriverCETxnSettings->TL_settings.cur.BackOffFromEndTimeFrame2)) *
MsPerSecond;
m_iTradeLookupFrame3MaxTimeInMilliSeconds =
(INT64)(secondsOfInitialTrades - ((INT64)m_pDriverCETxnSettings->TL_settings.cur.BackOffFromEndTimeFrame3)) *
MsPerSecond;
m_iTradeLookupFrame4MaxTimeInMilliSeconds =
(INT64)(secondsOfInitialTrades - ((INT64)m_pDriverCETxnSettings->TL_settings.cur.BackOffFromEndTimeFrame4)) *
MsPerSecond;
m_iTradeUpdateFrame2MaxTimeInMilliSeconds =
(INT64)(secondsOfInitialTrades - ((INT64)m_pDriverCETxnSettings->TU_settings.cur.BackOffFromEndTimeFrame2)) *
MsPerSecond;
m_iTradeUpdateFrame3MaxTimeInMilliSeconds =
(INT64)(secondsOfInitialTrades - ((INT64)m_pDriverCETxnSettings->TU_settings.cur.BackOffFromEndTimeFrame3)) *
MsPerSecond;
// Set the completion time of the last initial trade.
// 15 minutes are added at the end of hours of initial trades for pending
// trades.
m_EndTime = m_StartTime;
m_EndTime.AddWorkMs((INT64)(secondsOfInitialTrades + 15 * SecondsPerMinute) * MsPerSecond);
// Based on 10 * Trade-Order transaction mix percentage.
// This is currently how the mix levels are set, so use that.
m_iTradeOrderRollbackLimit = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeOrderMixLevel;
m_iTradeOrderRollbackLevel = m_pDriverCETxnSettings->TO_settings.cur.rollback;
// Log Tunables
m_pLogger->SendToLogger(m_pDriverCETxnSettings->BV_settings);
m_pLogger->SendToLogger(m_pDriverCETxnSettings->CP_settings);
m_pLogger->SendToLogger(m_pDriverCETxnSettings->MW_settings);
m_pLogger->SendToLogger(m_pDriverCETxnSettings->SD_settings);
m_pLogger->SendToLogger(m_pDriverCETxnSettings->TL_settings);
m_pLogger->SendToLogger(m_pDriverCETxnSettings->TO_settings);
m_pLogger->SendToLogger(m_pDriverCETxnSettings->TU_settings);
}
/*
* Generate Non-Uniform customer ID.
*
* PARAMETERS:
* OUT iCustomerId - generated C_ID
* OUT iCustomerTier - generated C_TIER
*
* RETURNS:
* none.
*/
inline void CCETxnInputGenerator::GenerateNonUniformRandomCustomerId(TIdent &iCustomerId,
eCustomerTier &iCustomerTier) {
m_CustomerSelection.GenerateRandomCustomer(iCustomerId, iCustomerTier);
}
/*
* Generate customer account ID (uniformly distributed).
*
* PARAMETERS:
* none.
*
* RETURNS:
* CA_ID uniformly distributed across all load units.
*/
TIdent CCETxnInputGenerator::GenerateRandomCustomerAccountId() {
TIdent iCustomerId;
TIdent iCustomerAccountId;
eCustomerTier iCustomerTier;
m_CustomerSelection.GenerateRandomCustomer(iCustomerId, iCustomerTier);
iCustomerAccountId = m_AccsAndPerms.GenerateRandomAccountId(m_rnd, iCustomerId, iCustomerTier);
return (iCustomerAccountId);
}
/*
* Generate a trade id to be used in Trade-Lookup / Trade-Update Frame 1.
*
* PARAMETERS:
* IN AValue - parameter to NURAND function
* IN SValue - parameter to NURAND function
*
* RETURNS:
* T_ID, distributed non-uniformly.
*/
TTrade CCETxnInputGenerator::GenerateNonUniformTradeID(INT32 AValue, INT32 SValue) {
TTrade TradeId;
TradeId = m_rnd.NURnd(1, m_iMaxActivePrePopulatedTradeID, AValue, SValue);
// Skip over trade id's that were skipped over during load time.
if (m_Holdings.IsAbortedTrade(TradeId)) {
TradeId++;
}
TradeId += iTTradeShift; // shift trade id to 64-bit value
return (TradeId);
}
/*
* Generate a trade timestamp to be used in Trade-Lookup / Trade-Update.
*
* PARAMETERS:
* OUT dts - returned timestamp
* IN MaxTimeInMilliSeconds - time interval (from the first initial
* trade) in which to generate the timestamp IN AValue -
* parameter to NURAND function IN SValue - parameter to
* NURAND function
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateNonUniformTradeDTS(TPCE::TIMESTAMP_STRUCT &dts, INT64 MaxTimeInMilliSeconds,
INT32 AValue, INT32 SValue) {
CDateTime TradeTime(InitialTradePopulationBaseYear, InitialTradePopulationBaseMonth, InitialTradePopulationBaseDay,
InitialTradePopulationBaseHour, InitialTradePopulationBaseMinute,
InitialTradePopulationBaseSecond,
InitialTradePopulationBaseFraction); // NOTE: Interpretting Fraction as
// milliseconds,
// probably 0 anyway.
INT64 TradeTimeOffset;
// Generate random number of seconds from the base time.
//
TradeTimeOffset = m_rnd.NURnd(1, MaxTimeInMilliSeconds, AValue, SValue);
// The time we have is an offset into the initial pre-populated trading
// time. This needs to be converted into a "real" time taking into account 8
// hour business days, etc.
TradeTime.AddWorkMs(TradeTimeOffset);
TradeTime.GetTimeStamp(&dts);
}
/*
* Generate Broker-Volume transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* the number of brokers generated.
*/
void CCETxnInputGenerator::GenerateBrokerVolumeInput(TBrokerVolumeTxnInput &TxnReq) {
INT32 iNumBrokers;
INT32 iCount, i;
TIdent B_ID[max_broker_list_len];
INT32 iSectorIndex;
// Make sure we're starting with a clean object.
TxnReq.Clear();
// Select the range of brokers, honoring partitioning by CID settings.
// iBrokersStart = iStartingBrokerID;
// iBrokersCount = m_iActiveCustomerCount / iBrokersDiv;
iNumBrokers = m_rnd.RndIntRange(min_broker_list_len,
max_broker_list_len); // 20..40 brokers
// Small databases (<=4LUs) may contain less than the chosen number of
// brokers. Broker names for Broker Volume are unique, so need to re-adjust
// or be caught in an infinite loop below.
if (iNumBrokers > m_Brokers.GetBrokerCount()) {
iNumBrokers = (INT32)m_Brokers.GetBrokerCount(); // adjust for small databases
}
iCount = 0;
do {
// select random broker ID (from active customer range)
B_ID[iCount] = m_Brokers.GenerateRandomBrokerId(&m_rnd);
for (i = 0; (i < iCount) && (B_ID[i] != B_ID[iCount]); ++i) {
};
if (i == iCount) // make sure brokers are distinct
{
// put the broker name into the input parameter
m_Brokers.GenerateBrokerName(B_ID[iCount], TxnReq.broker_list[iCount],
static_cast<int>(sizeof(TxnReq.broker_list[iCount])));
++iCount;
}
} while (iCount < iNumBrokers);
// select sector name
iSectorIndex = m_rnd.RndIntRange(0, m_iSectorCount - 1);
strncpy(TxnReq.sector_name, m_pSectors[iSectorIndex].SC_NAME_CSTR(), sizeof(TxnReq.sector_name));
}
/*
* Generate Customer-Position transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateCustomerPositionInput(TCustomerPositionTxnInput &TxnReq) {
TIdent iCustomerId;
eCustomerTier iCustomerTier;
// Make sure we're starting with a clean object.
TxnReq.Clear();
GenerateNonUniformRandomCustomerId(iCustomerId, iCustomerTier);
if (m_rnd.RndPercent(m_pDriverCETxnSettings->CP_settings.cur.by_tax_id)) {
// send tax id instead of customer id
m_Person.GetTaxID(iCustomerId, TxnReq.tax_id);
} else {
// send customer id and not the tax id
TxnReq.cust_id = iCustomerId;
}
TxnReq.get_history = m_rnd.RndPercent(m_pDriverCETxnSettings->CP_settings.cur.get_history);
if (TxnReq.get_history) {
TxnReq.acct_id_idx = m_rnd.RndIntRange(0, m_AccsAndPerms.GetNumberOfAccounts(iCustomerId, iCustomerTier) - 1);
} else {
TxnReq.acct_id_idx = -1;
}
}
/*
* Generate Market-Watch transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateMarketWatchInput(TMarketWatchTxnInput &TxnReq) {
TIdent iCustomerId;
eCustomerTier iCustomerTier;
INT32 iThreshold;
INT32 iWeek;
INT32 iDailyMarketDay;
CDateTime StartDate(iDailyMarketBaseYear, iDailyMarketBaseMonth, iDailyMarketBaseDay, iDailyMarketBaseHour,
iDailyMarketBaseMinute, iDailyMarketBaseSecond, iDailyMarketBaseMsec);
// Make sure we're starting with a clean object.
TxnReq.Clear();
iThreshold = m_rnd.RndGenerateIntegerPercentage();
// have some distribution on what inputs to send
if (iThreshold <= m_pDriverCETxnSettings->MW_settings.cur.by_industry) {
// send industry name
strncpy(TxnReq.industry_name, m_pIndustries[m_rnd.RndIntRange(0, m_iIndustryCount - 1)].IN_NAME_CSTR(),
sizeof(TxnReq.industry_name));
if (iBaseCompanyCount < m_iActiveCompanyCount) {
TxnReq.starting_co_id = m_rnd.RndInt64Range(
m_iStartFromCompany, m_iStartFromCompany + m_iActiveCompanyCount - (iBaseCompanyCount - 1));
TxnReq.ending_co_id = TxnReq.starting_co_id + (iBaseCompanyCount - 1);
} else {
TxnReq.starting_co_id = m_iStartFromCompany;
TxnReq.ending_co_id = m_iStartFromCompany + m_iActiveCompanyCount - 1;
}
} else {
if (iThreshold <= (m_pDriverCETxnSettings->MW_settings.cur.by_industry +
m_pDriverCETxnSettings->MW_settings.cur.by_watch_list)) {
// Send customer id
GenerateNonUniformRandomCustomerId(TxnReq.c_id, iCustomerTier);
} else {
// Send account id
GenerateNonUniformRandomCustomerId(iCustomerId, iCustomerTier);
m_AccsAndPerms.GenerateRandomAccountId(m_rnd, iCustomerId, iCustomerTier, &TxnReq.acct_id, NULL);
}
}
// Set start_day for both cases of the 'if'.
//
iWeek = (INT32)m_rnd.NURnd(0, 255, 255, 0) + 5; // A = 255, S = 0
// Week is now between 5 and 260.
// Select a day within the week.
//
iThreshold = m_rnd.RndGenerateIntegerPercentage();
if (iThreshold > 40) {
iDailyMarketDay = iWeek * DaysPerWeek + 4; // Friday
} else // 1..40 case
{
if (iThreshold <= 20) {
iDailyMarketDay = iWeek * DaysPerWeek; // Monday
} else {
if (iThreshold <= 27) {
iDailyMarketDay = iWeek * DaysPerWeek + 1; // Tuesday
} else {
if (iThreshold <= 33) {
iDailyMarketDay = iWeek * DaysPerWeek + 2; // Wednesday
} else {
iDailyMarketDay = iWeek * DaysPerWeek + 3; // Thursday
}
}
}
}
// Go back 256 weeks and then add our calculated day.
//
StartDate.Add(iDailyMarketDay, 0);
StartDate.GetTimeStamp(&TxnReq.start_day);
}
/*
* Generate Security-Detail transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateSecurityDetailInput(TSecurityDetailTxnInput &TxnReq) {
CDateTime StartDate(iDailyMarketBaseYear, iDailyMarketBaseMonth, iDailyMarketBaseDay, iDailyMarketBaseHour,
iDailyMarketBaseMinute, iDailyMarketBaseSecond, iDailyMarketBaseMsec);
INT32 iStartDay; // day from the StartDate
// Make sure we're starting with a clean object.
TxnReq.Clear();
// random symbol
m_pSecurities.CreateSymbol(m_rnd.RndInt64Range(0, m_iActiveSecurityCount - 1), TxnReq.symbol,
static_cast<int>(sizeof(TxnReq.symbol)));
// Whether or not to access the LOB.
TxnReq.access_lob_flag = m_rnd.RndPercent(m_pDriverCETxnSettings->SD_settings.cur.LOBAccessPercentage);
// random number of financial rows to return
TxnReq.max_rows_to_return = m_rnd.RndIntRange(iSecurityDetailMinRows, iSecurityDetailMaxRows);
iStartDay = m_rnd.RndIntRange(0, iDailyMarketTotalRows - TxnReq.max_rows_to_return);
// add the offset
StartDate.Add(iStartDay, 0);
StartDate.GetTimeStamp(&TxnReq.start_day);
}
/*
* Generate Trade-Lookup transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateTradeLookupInput(TTradeLookupTxnInput &TxnReq) {
INT32 iThreshold;
// Make sure we're starting with a clean object.
TxnReq.Clear();
iThreshold = m_rnd.RndGenerateIntegerPercentage();
if (iThreshold <= m_pDriverCETxnSettings->TL_settings.cur.do_frame1) {
// Frame 1
TxnReq.frame_to_execute = 1;
TxnReq.max_trades = m_pDriverCETxnSettings->TL_settings.cur.MaxRowsFrame1;
// Generate list of unique trade id's
int ii, jj;
bool Accepted;
TTrade TID;
for (ii = 0; ii < TxnReq.max_trades; ii++) {
Accepted = false;
while (!Accepted) {
TID = GenerateNonUniformTradeID(TradeLookupAValueForTradeIDGenFrame1,
TradeLookupSValueForTradeIDGenFrame1);
jj = 0;
while (jj < ii && TxnReq.trade_id[jj] != TID) {
jj++;
}
if (jj == ii) {
// We have a unique TID for this batch
TxnReq.trade_id[ii] = TID;
Accepted = true;
}
}
}
} else if (iThreshold <=
m_pDriverCETxnSettings->TL_settings.cur.do_frame1 + m_pDriverCETxnSettings->TL_settings.cur.do_frame2) {
// Frame 2
TxnReq.frame_to_execute = 2;
TxnReq.acct_id = GenerateRandomCustomerAccountId();
TxnReq.max_trades = m_pDriverCETxnSettings->TL_settings.cur.MaxRowsFrame2;
GenerateNonUniformTradeDTS(TxnReq.start_trade_dts, m_iTradeLookupFrame2MaxTimeInMilliSeconds,
TradeLookupAValueForTimeGenFrame2, TradeLookupSValueForTimeGenFrame2);
// Set to the end of initial trades.
m_EndTime.GetTimeStamp(&TxnReq.end_trade_dts);
} else if (iThreshold <= m_pDriverCETxnSettings->TL_settings.cur.do_frame1 +
m_pDriverCETxnSettings->TL_settings.cur.do_frame2 +
m_pDriverCETxnSettings->TL_settings.cur.do_frame3) {
// Frame 3
TxnReq.frame_to_execute = 3;
TxnReq.max_trades = m_pDriverCETxnSettings->TL_settings.cur.MaxRowsFrame3;
m_pSecurities.CreateSymbol(m_rnd.NURnd(0, m_iActiveSecurityCount - 1, TradeLookupAValueForSymbolFrame3,
TradeLookupSValueForSymbolFrame3),
TxnReq.symbol, static_cast<int>(sizeof(TxnReq.symbol)));
GenerateNonUniformTradeDTS(TxnReq.start_trade_dts, m_iTradeLookupFrame3MaxTimeInMilliSeconds,
TradeLookupAValueForTimeGenFrame3, TradeLookupSValueForTimeGenFrame3);
// Set to the end of initial trades.
m_EndTime.GetTimeStamp(&TxnReq.end_trade_dts);
TxnReq.max_acct_id = m_AccsAndPerms.GetEndingCA_ID(m_iActiveCustomerCount);
} else {
// Frame 4
TxnReq.frame_to_execute = 4;
TxnReq.acct_id = GenerateRandomCustomerAccountId();
GenerateNonUniformTradeDTS(TxnReq.start_trade_dts, m_iTradeLookupFrame4MaxTimeInMilliSeconds,
TradeLookupAValueForTimeGenFrame4, TradeLookupSValueForTimeGenFrame4);
}
}
/*
* Generate Trade-Order transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction. OUT TradeType - integer representation of
* generated trade type (as eTradeTypeID enum). OUT bExecutorIsAccountOwner -
* whether Trade-Order frame 2 should (FALSE) or shouldn't (TRUE) be called.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateTradeOrderInput(TTradeOrderTxnInput &TxnReq, INT32 &iTradeType,
bool &bExecutorIsAccountOwner) {
TIdent iCustomerId; // owner
eCustomerTier iCustomerTier;
TIdent CID_1, CID_2;
bool bMarket;
INT32 iAdditionalPerms;
UINT iSymbIndex;
TIdent iFlatFileSymbIndex;
eTradeTypeID eTradeType;
// Make sure we're starting with a clean object.
TxnReq.Clear();
// Generate random customer
//
GenerateNonUniformRandomCustomerId(iCustomerId, iCustomerTier);
// Generate random account id and security index
//
m_Holdings.GenerateRandomAccountSecurity(iCustomerId, iCustomerTier, &TxnReq.acct_id, &iFlatFileSymbIndex,
&iSymbIndex);
// find out how many permission rows there are for this account (in addition
// to the owner's)
iAdditionalPerms = m_AccsAndPerms.GetNumPermsForCA(TxnReq.acct_id);
// distribution same as in the loader for now
if (iAdditionalPerms == 0) { // select the owner
m_Person.GetFirstLastAndTaxID(iCustomerId, TxnReq.exec_f_name, TxnReq.exec_l_name, TxnReq.exec_tax_id);
bExecutorIsAccountOwner = true;
} else {
// If there is more than one permission set on the account,
// have some distribution on whether the executor is still
// the account owner, or it is one of the additional permissions.
// Here we must take into account the fact that we've excluded
// a large portion of customers that don't have any additional
// executors in the above code (iAdditionalPerms == 0); the
// "exec_is_owner" percentage implicity includes such customers
// and must be factored out here.
int exec_is_owner =
(m_pDriverCETxnSettings->TO_settings.cur.exec_is_owner - iPercentAccountAdditionalPermissions_0) * 100 /
(100 - iPercentAccountAdditionalPermissions_0);
if (m_rnd.RndPercent(exec_is_owner)) {
m_Person.GetFirstLastAndTaxID(iCustomerId, TxnReq.exec_f_name, TxnReq.exec_l_name, TxnReq.exec_tax_id);
bExecutorIsAccountOwner = true;
} else {
if (iAdditionalPerms == 1) {
// select the first non-owner
m_AccsAndPerms.GetCIDsForPermissions(TxnReq.acct_id, iCustomerId, &CID_1, NULL);
m_Person.GetFirstLastAndTaxID(CID_1, TxnReq.exec_f_name, TxnReq.exec_l_name, TxnReq.exec_tax_id);
} else {
// select the second non-owner
m_AccsAndPerms.GetCIDsForPermissions(TxnReq.acct_id, iCustomerId, &CID_1, &CID_2);
// generate third account permission row
m_Person.GetFirstLastAndTaxID(CID_2, TxnReq.exec_f_name, TxnReq.exec_l_name, TxnReq.exec_tax_id);
}
bExecutorIsAccountOwner = false;
}
}
// Select either stock symbol or company from the securities flat file.
//
// have some distribution on the company/symbol input preference
if (m_rnd.RndPercent(m_pDriverCETxnSettings->TO_settings.cur.security_by_symbol)) {
// Submit the symbol
m_pSecurities.CreateSymbol(iFlatFileSymbIndex, TxnReq.symbol, static_cast<int>(sizeof(TxnReq.symbol)));
} else {
// Submit the company name
m_pCompanies.CreateName(m_pSecurities.GetCompanyIndex(iFlatFileSymbIndex), TxnReq.co_name,
static_cast<int>(sizeof(TxnReq.co_name)));
strncpy(TxnReq.issue, m_pSecurities.GetRecord(iFlatFileSymbIndex).S_ISSUE_CSTR(), sizeof(TxnReq.issue));
}
TxnReq.trade_qty = cTRADE_QTY_SIZES[m_rnd.RndIntRange(0, cNUM_TRADE_QTY_SIZES - 1)];
TxnReq.requested_price = m_rnd.RndDoubleIncrRange(fMinSecPrice, fMaxSecPrice, 0.01);
// Determine whether Market or Limit order
bMarket = m_rnd.RndPercent(m_pDriverCETxnSettings->TO_settings.cur.market);
// Determine whether Buy or Sell trade
if (m_rnd.RndPercent(m_pDriverCETxnSettings->TO_settings.cur.buy_orders)) {
if (bMarket) {
// Market Buy
eTradeType = eMarketBuy;
} else {
// Limit Buy
eTradeType = eLimitBuy;
}
// Set margin or cash for Buy
TxnReq.type_is_margin = m_rnd.RndPercent(
// type_is_margin is specified for all orders, but used only for
// buys
m_pDriverCETxnSettings->TO_settings.cur.type_is_margin * 100 /
m_pDriverCETxnSettings->TO_settings.cur.buy_orders);
} else {
if (bMarket) {
// Market Sell
eTradeType = eMarketSell;
} else {
// determine whether the Limit Sell is a Stop Loss
if (m_rnd.RndPercent(m_pDriverCETxnSettings->TO_settings.cur.stop_loss)) {
// Stop Loss
eTradeType = eStopLoss;
} else {
// Limit Sell
eTradeType = eLimitSell;
}
}
TxnReq.type_is_margin = false; // all sell orders are cash
}
iTradeType = eTradeType;
// Distribution of last-in-first-out flag
TxnReq.is_lifo = m_rnd.RndPercent(m_pDriverCETxnSettings->TO_settings.cur.lifo);
// Copy the trade type id from the flat file
strncpy(TxnReq.trade_type_id, m_pTradeType[eTradeType].TT_ID_CSTR(), sizeof(TxnReq.trade_type_id));
// Copy the status type id's from the flat file
strncpy(TxnReq.st_pending_id, m_pStatusType[ePending].ST_ID_CSTR(), sizeof(TxnReq.st_pending_id));
strncpy(TxnReq.st_submitted_id, m_pStatusType[eSubmitted].ST_ID_CSTR(), sizeof(TxnReq.st_submitted_id));
TxnReq.roll_it_back = (m_iTradeOrderRollbackLevel >= m_rnd.RndIntRange(1, m_iTradeOrderRollbackLimit));
// Need to address logging more comprehensively.
// return eTradeType;
}
/*
* Generate Trade-Status transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateTradeStatusInput(TTradeStatusTxnInput &TxnReq) {
TIdent iCustomerId;
eCustomerTier iCustomerTier;
// Make sure we're starting with a clean object.
TxnReq.Clear();
// select customer id first
GenerateNonUniformRandomCustomerId(iCustomerId, iCustomerTier);
// select random account id
m_AccsAndPerms.GenerateRandomAccountId(m_rnd, iCustomerId, iCustomerTier, &TxnReq.acct_id, NULL);
}
/*
* Generate Trade-Update transaction input.
*
* PARAMETERS:
* OUT TxnReq - input parameter structure filled in
* for the transaction.
*
* RETURNS:
* none.
*/
void CCETxnInputGenerator::GenerateTradeUpdateInput(TTradeUpdateTxnInput &TxnReq) {
INT32 iThreshold;
// Make sure we're starting with a clean object.
TxnReq.Clear();
iThreshold = m_rnd.RndGenerateIntegerPercentage();
if (iThreshold <= m_pDriverCETxnSettings->TU_settings.cur.do_frame1) {
// Frame 1
TxnReq.frame_to_execute = 1;
TxnReq.max_trades = m_pDriverCETxnSettings->TU_settings.cur.MaxRowsFrame1;
TxnReq.max_updates = m_pDriverCETxnSettings->TU_settings.cur.MaxRowsToUpdateFrame1;
// Generate list of unique trade id's
int ii, jj;
bool Accepted;
TTrade TID;
for (ii = 0; ii < TxnReq.max_trades; ii++) {
Accepted = false;
while (!Accepted) {
TID = GenerateNonUniformTradeID(TradeUpdateAValueForTradeIDGenFrame1,
TradeUpdateSValueForTradeIDGenFrame1);
jj = 0;
while (jj < ii && TxnReq.trade_id[jj] != TID) {
jj++;
}
if (jj == ii) {
// We have a unique TID for this batch
TxnReq.trade_id[ii] = TID;
Accepted = true;
}
}
}
} else if (iThreshold <=
m_pDriverCETxnSettings->TU_settings.cur.do_frame1 + m_pDriverCETxnSettings->TU_settings.cur.do_frame2) {
// Frame 2
TxnReq.frame_to_execute = 2;
TxnReq.max_trades = m_pDriverCETxnSettings->TU_settings.cur.MaxRowsFrame2;
TxnReq.max_updates = m_pDriverCETxnSettings->TU_settings.cur.MaxRowsToUpdateFrame2;
TxnReq.acct_id = GenerateRandomCustomerAccountId();
GenerateNonUniformTradeDTS(TxnReq.start_trade_dts, m_iTradeUpdateFrame2MaxTimeInMilliSeconds,
TradeUpdateAValueForTimeGenFrame2, TradeUpdateSValueForTimeGenFrame2);
// Set to the end of initial trades.
m_EndTime.GetTimeStamp(&TxnReq.end_trade_dts);
} else {
// Frame 3
TxnReq.frame_to_execute = 3;
TxnReq.max_trades = m_pDriverCETxnSettings->TU_settings.cur.MaxRowsFrame3;
TxnReq.max_updates = m_pDriverCETxnSettings->TU_settings.cur.MaxRowsToUpdateFrame3;
m_pSecurities.CreateSymbol(m_rnd.NURnd(0, m_iActiveSecurityCount - 1, TradeUpdateAValueForSymbolFrame3,
TradeUpdateSValueForSymbolFrame3),
TxnReq.symbol, static_cast<int>(sizeof(TxnReq.symbol)));
GenerateNonUniformTradeDTS(TxnReq.start_trade_dts, m_iTradeUpdateFrame3MaxTimeInMilliSeconds,
TradeUpdateAValueForTimeGenFrame3, TradeUpdateSValueForTimeGenFrame3);
// Set to the end of initial trades.
m_EndTime.GetTimeStamp(&TxnReq.end_trade_dts);
TxnReq.max_acct_id = m_AccsAndPerms.GetEndingCA_ID(m_iActiveCustomerCount);
}
}

View File

@@ -0,0 +1,179 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Gregory Dake, Cecil Reames, Doug Johnson, Matt Emmerton
*/
/******************************************************************************
* Description: Implementation of CTxnGeneration class.
* See TxnMixGenerator.h for description.
******************************************************************************/
#include "main/CETxnMixGenerator.h"
using namespace TPCE;
CCETxnMixGenerator::CCETxnMixGenerator(const PDriverCETxnSettings pDriverCETxnSettings, CBaseLogger *pLogger)
: m_pDriverCETxnSettings(pDriverCETxnSettings), m_rnd(RNGSeedBaseTxnMixGenerator) // initialize with default seed
,
m_pLogger(pLogger), m_iTxnArrayCurrentIndex(0), m_pTxnArray(NULL) {
// UpdateTunables() is called from CCE constructor (Initialize)
}
CCETxnMixGenerator::CCETxnMixGenerator(const PDriverCETxnSettings pDriverCETxnSettings, RNGSEED RNGSeed,
CBaseLogger *pLogger)
: m_pDriverCETxnSettings(pDriverCETxnSettings), m_rnd(RNGSeed) // seed is provided for us
,
m_pLogger(pLogger), m_iTxnArrayCurrentIndex(0), m_pTxnArray(NULL) {
// UpdateTunables() is called from CCE constructor (Initialize)
}
RNGSEED CCETxnMixGenerator::GetRNGSeed(void) {
return (m_rnd.GetSeed());
}
void CCETxnMixGenerator::SetRNGSeed(RNGSEED RNGSeed) {
m_rnd.SetSeed(RNGSeed);
}
CCETxnMixGenerator::~CCETxnMixGenerator() {
if (m_pTxnArray != NULL) {
delete[] m_pTxnArray;
m_pTxnArray = NULL;
}
}
void CCETxnMixGenerator::UpdateTunables(void) {
INT32 i;
INT32 BrokerVolumeMixLimit;
INT32 CustomerPositionMixLimit;
INT32 MarketWatchMixLimit;
INT32 SecurityDetailMixLimit;
INT32 TradeLookupMixLimit;
INT32 TradeOrderMixLimit;
INT32 TradeStatusMixLimit;
INT32 TradeUpdateMixLimit;
// Add all the weights together
m_CETransactionMixTotal = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.BrokerVolumeMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.CustomerPositionMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.MarketWatchMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.SecurityDetailMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeLookupMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeOrderMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeStatusMixLevel +
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeUpdateMixLevel;
TradeStatusMixLimit = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeStatusMixLevel;
MarketWatchMixLimit =
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.MarketWatchMixLevel + TradeStatusMixLimit;
SecurityDetailMixLimit =
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.SecurityDetailMixLevel + MarketWatchMixLimit;
CustomerPositionMixLimit =
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.CustomerPositionMixLevel + SecurityDetailMixLimit;
TradeOrderMixLimit =
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeOrderMixLevel + CustomerPositionMixLimit;
TradeLookupMixLimit = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeLookupMixLevel + TradeOrderMixLimit;
TradeUpdateMixLimit =
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeUpdateMixLevel + TradeLookupMixLimit;
BrokerVolumeMixLimit =
m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.BrokerVolumeMixLevel + TradeUpdateMixLimit;
// Reset the random transaction array.
//
if (m_pTxnArray != NULL) {
delete[] m_pTxnArray;
m_pTxnArray = NULL;
}
m_pTxnArray = new char[m_CETransactionMixTotal];
// Initialize the array with transaction types.
//
for (i = 0; i < TradeStatusMixLimit; ++i) {
m_pTxnArray[i] = TRADE_STATUS;
}
for (; i < MarketWatchMixLimit; ++i) {
m_pTxnArray[i] = MARKET_WATCH;
}
for (; i < SecurityDetailMixLimit; ++i) {
m_pTxnArray[i] = SECURITY_DETAIL;
}
for (; i < CustomerPositionMixLimit; ++i) {
m_pTxnArray[i] = CUSTOMER_POSITION;
}
for (; i < TradeOrderMixLimit; ++i) {
m_pTxnArray[i] = TRADE_ORDER;
}
for (; i < TradeLookupMixLimit; ++i) {
m_pTxnArray[i] = TRADE_LOOKUP;
}
for (; i < TradeUpdateMixLimit; ++i) {
m_pTxnArray[i] = TRADE_UPDATE;
}
for (; i < BrokerVolumeMixLimit; ++i) {
m_pTxnArray[i] = BROKER_VOLUME;
}
m_iTxnArrayCurrentIndex = 0; // reset the current element index
// Log Tunables
m_pLogger->SendToLogger(m_pDriverCETxnSettings->TxnMixGenerator_settings);
}
int CCETxnMixGenerator::GenerateNextTxnType() {
// Select the next transaction type using the "card deck shuffle"
// algorithm (also Knuth algorithm) that guarantees a certain number
// of transactions of each type is returned.
//
// 1) Get a 32-bit random number.
// 2) Use random number to select next transaction type from m_pTxnArray
// in the range [m_iTxnArrayCurrentIndex, m_CETransactionMixTotal).
// 3) Swap the selected random element in m_pTxnArray
// with m_pTxnArray[m_iTxnArrayCurrentIndex].
// 4) Increment m_iTxnArrayCurrentIndex to remove the returned
// transaction type from further consideration.
//
INT32 rnd = m_rnd.RndIntRange(m_iTxnArrayCurrentIndex, m_CETransactionMixTotal - 1);
char iTxnType = m_pTxnArray[rnd];
// Swap two array entries.
//
m_pTxnArray[rnd] = m_pTxnArray[m_iTxnArrayCurrentIndex];
m_pTxnArray[m_iTxnArrayCurrentIndex] = iTxnType;
m_iTxnArrayCurrentIndex = (m_iTxnArrayCurrentIndex + 1) % m_CETransactionMixTotal;
return iTxnType;
}

View File

@@ -0,0 +1,38 @@
add_library(tpce_main OBJECT
AddressTable.cpp
BaseLogger.cpp
CE.cpp
CETxnInputGenerator.cpp
CETxnMixGenerator.cpp
ChargeTable.cpp
CommissionRateTable.cpp
CustomerSelection.cpp
CustomerTable.cpp
DM.cpp
EGenGenerateAndLoad.cpp
EGenLogFormatterTab.cpp
ExchangeTable.cpp
FlatFileLoader.cpp
IndustryTable.cpp
MEE.cpp
MEEPriceBoard.cpp
MEESecurity.cpp
MEETickerTape.cpp
MEETradingFloor.cpp
Person.cpp
SectorTable.cpp
StatusTypeTable.cpp
TaxRateTable.cpp
TradeGen.cpp
TradeTypeTable.cpp
WheelTime.cpp
ZipCodeTable.cpp
bucketsimulator.cpp
progressmeter.cpp
progressmeterinterface.cpp
strutil.cpp)
set(TPCE_OBJECT_FILES
${TPCE_OBJECT_FILES} $<TARGET_OBJECTS:tpce_main>
PARENT_SCOPE)
disable_target_warnings(tpce_main)

View File

@@ -0,0 +1,55 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/ChargeTable.h"
#include <cstring>
using namespace TPCE;
CChargeTable::CChargeTable(const ChargeDataFile_t &dataFile) : FixedTable<ChargeDataFile_t, CHARGE_ROW>(dataFile) {
}
CChargeTable::~CChargeTable() {
}
void CChargeTable::LoadTableRow() {
const ChargeDataFileRecord &dataRecord(df[recordIdx]);
tableRow.CH_CHRG = dataRecord.CH_CHRG();
tableRow.CH_C_TIER = dataRecord.CH_C_TIER();
strncpy(tableRow.CH_TT_ID, dataRecord.CH_TT_ID_CSTR(), sizeof(tableRow.CH_TT_ID));
}

View File

@@ -0,0 +1,59 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/CommissionRateTable.h"
#include <cstring>
using namespace TPCE;
CCommissionRateTable::CCommissionRateTable(const CommissionRateDataFile_t &dataFile)
: FixedTable<CommissionRateDataFile_t, COMMISSION_RATE_ROW>(dataFile) {
}
CCommissionRateTable::~CCommissionRateTable() {
}
void CCommissionRateTable::LoadTableRow() {
const CommissionRateDataFileRecord &dataRecord(df[recordIdx]);
tableRow.CR_C_TIER = dataRecord.CR_C_TIER();
strncpy(tableRow.CR_EX_ID, dataRecord.CR_EX_ID_CSTR(), sizeof(tableRow.CR_EX_ID));
tableRow.CR_FROM_QTY = dataRecord.CR_FROM_QTY();
tableRow.CR_RATE = dataRecord.CR_RATE();
tableRow.CR_TO_QTY = dataRecord.CR_TO_QTY();
strncpy(tableRow.CR_TT_ID, dataRecord.CR_TT_ID_CSTR(), sizeof(tableRow.CR_TT_ID));
}

View File

@@ -0,0 +1,273 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy, Doug Johnson
*/
/******************************************************************************
* Description: Implementation of the CustomerSelection class.
* (see CustomerSelction.h for details)
******************************************************************************/
#include "main/EGenTables_stdafx.h"
using namespace TPCE;
/*
* Default constructor.
*/
CCustomerSelection::CCustomerSelection()
: m_pRND(NULL), m_iStartFromCustomer(0 + iTIdentShift), m_iCustomerCount(0), m_bPartitionByCID(false),
m_iPartitionPercent(0), m_iMyStartFromCustomer(0 + iTIdentShift), m_iMyCustomerCount(0) {
}
/*
* Constructor to set the customer range when not partitioining
*/
CCustomerSelection::CCustomerSelection(CRandom *pRND, TIdent iStartFromCustomer, TIdent iCustomerCount)
: m_pRND(pRND), m_iStartFromCustomer(iStartFromCustomer + iTIdentShift), m_iCustomerCount(iCustomerCount),
m_bPartitionByCID(false), m_iPartitionPercent(0), m_iMyStartFromCustomer(0 + iTIdentShift),
m_iMyCustomerCount(0) {
}
/*
* Constructor to set subrange when partitioning by C_ID.
*/
CCustomerSelection::CCustomerSelection(CRandom *pRND, TIdent iStartFromCustomer, TIdent iCustomerCount,
int iPartitionPercent, TIdent iMyStartFromCustomer, TIdent iMyCustomerCount)
: m_pRND(pRND), m_iStartFromCustomer(iStartFromCustomer + iTIdentShift), m_iCustomerCount(iCustomerCount)
,
m_bPartitionByCID(true), m_iPartitionPercent(iPartitionPercent),
m_iMyStartFromCustomer(iMyStartFromCustomer + iTIdentShift), m_iMyCustomerCount(iMyCustomerCount) {
if ((iStartFromCustomer == iMyStartFromCustomer) && (iCustomerCount == iMyCustomerCount)) {
// Even though the partitioning constructor was called, we're apparently
// not really partitioning.
m_bPartitionByCID = false;
}
}
/*
* Re-set the customer range for the partition.
*/
void CCustomerSelection::SetPartitionRange(TIdent iStartFromCustomer, TIdent iCustomerCount) {
if (m_bPartitionByCID) {
m_iMyStartFromCustomer = iStartFromCustomer;
m_iMyCustomerCount = iCustomerCount;
}
}
/*
* Forward permutation.
*/
TIdent CCustomerSelection::Permute(TIdent iLow, TIdent iHigh) {
return ((677 * iLow + 33 * (iHigh + 1)) % 1000);
}
/*
* Inverse permutation.
*/
TIdent CCustomerSelection::InversePermute(TIdent iLow, TIdent iHigh) {
// Extra mod to make the result always positive
//
return (((((613 * (iLow - 33 * (iHigh + 1))) % 1000) + 1000) % 1000));
}
/*
* Return scrambled inverse customer id in range of 0 to 999.
*/
UINT CCustomerSelection::GetInverseCID(TIdent C_ID) {
UINT iCHigh = (UINT)CHigh(C_ID);
UINT iInverseCID = (UINT)InversePermute(CLow(C_ID), iCHigh);
if (iInverseCID < 200) // Tier 1: value 0 to 199
{
return ((3 * iInverseCID + (iCHigh + 1)) % 200);
} else {
if (iInverseCID < 800) // Tier 2: value 200 to 799
{
return (((59 * iInverseCID + 47 * (iCHigh + 1)) % 600) + 200);
} else // Tier 3: value 800 to 999
{
return (((23 * iInverseCID + 17 * (iCHigh + 1)) % 200) + 800);
}
}
}
/*
* Return customer tier.
*/
eCustomerTier CCustomerSelection::GetTier(TIdent C_ID) {
TIdent iRevC_ID = InversePermute(CLow(C_ID), CHigh(C_ID));
if (iRevC_ID < 200) {
return eCustomerTierOne;
} else {
if (iRevC_ID < 800) {
return eCustomerTierTwo;
} else {
return eCustomerTierThree;
}
}
}
/*
* Return a non-uniform random customer and the associated tier.
*/
void CCustomerSelection::GenerateRandomCustomer(TIdent &C_ID, eCustomerTier &C_TIER) {
// Can't use this function if there is no external RNG.
//
if (m_pRND == NULL) {
return;
}
double fCW = m_pRND->RndDoubleIncrRange(0.0001, 2000, 0.000000001);
// Uniformly select the higher portion of the C_ID.
// Use "short-circuit" logic to avoid unnecessary call to RNG.
TIdent iCHigh;
if (m_bPartitionByCID && m_pRND->RndPercent(m_iPartitionPercent)) {
// Generate a load unit inside the partition.
iCHigh = (m_pRND->RndInt64Range(m_iMyStartFromCustomer,
m_iMyStartFromCustomer + m_iMyCustomerCount - 1) -
1) // minus 1 for the upper boundary case
/ 1000;
} else {
// Generate a load unit across the entire range
iCHigh = (m_pRND->RndInt64Range(m_iStartFromCustomer,
m_iStartFromCustomer + m_iCustomerCount - 1) -
1) // minus 1 for the upper boundary case
/ 1000;
}
// Non-uniformly select the lower portion of the C_ID.
//
int iCLow;
if (fCW <= 200) {
// tier one
//
iCLow = (int)ceil(sqrt(22500 + 500 * fCW) - 151);
C_TIER = eCustomerTierOne;
} else {
if (fCW <= 1400) {
// tier two
//
iCLow = (int)ceil(sqrt(290000 + 1000 * fCW) - 501);
C_TIER = eCustomerTierTwo;
} else {
// tier three
//
iCLow = (int)ceil(149 + sqrt(500 * fCW - 277500));
C_TIER = eCustomerTierThree;
}
}
C_ID = iCHigh * 1000 + Permute(iCLow, iCHigh) + 1;
}
/////////*
////////* Return a non-uniform random customer and tier.
////////*/
////////void CCustomerSelection::GenerateCustomerIdAndTier(TIdent &C_ID,
/// eCustomerTier &C_TIER, bool bAcrossEntireRange)
////////{
//////// // Can't use this function if there is no external RNG.
//////// //
//////// if (m_pRND == NULL)
//////// {
//////// return;
//////// }
////////
//////// double fCW = m_pRND->RndDoubleRange(0.0001, 2000);
////////
//////// // Select uniformly higher portion of the Customer ID.
//////// //
//////// TIdent iCHigh;
//////// if (bAcrossEntireRange)
//////// {
//////// // Generate a load unit across the entire range
//////// iCHigh = (m_pRND->RndInt64Range(1,
/// m_iAdjustedTotalCustomerCount) - 1) // minus 1 for the upper boundary case
//////// / 1000;
//////// if( iCHigh >= ( m_iStartFromCustomer / 1000 ))
//////// {
//////// iCHigh += ( m_iCustomerCount / 1000 );
//////// }
//////// }
//////// else
//////// {
//////// // Generate a load unit inside the parition.
//////// iCHigh = (m_pRND->RndInt64Range(m_iStartFromCustomer,
//////// m_iStartFromCustomer +
/// m_iCustomerCount - 1) - 1) // minus 1 for the upper boundary case
//////// / 1000;
//////// }
////////
//////// // Select non-uniformly the lower portion of the Customer ID.
//////// //
//////// int iCLow;
////////
//////// if (fCW <= 200)
//////// {
//////// // tier one
//////// //
//////// iCLow = (int) ceil( sqrt(22500 + 500 * fCW) - 151 );
////////
//////// C_TIER = eCustomerTierOne;
//////// }
//////// else
//////// {
//////// if (fCW <=1400)
//////// {
//////// // tier two
//////// //
//////// iCLow = (int) ceil( sqrt(290000 + 1000 * fCW) - 501 );
////////
//////// C_TIER = eCustomerTierTwo;
//////// }
//////// else
//////// {
//////// // tier three
//////// //
//////// iCLow = (int) ceil( 149 + sqrt(500 * fCW - 277500) );
////////
//////// C_TIER = eCustomerTierThree;
//////// }
//////// }
////////
//////// C_ID = iCHigh * 1000 + Permute(iCLow, iCHigh) + 1;
////////}

View File

@@ -0,0 +1,411 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy
* - Doug Johnson
*/
#include "main/EGenTables_stdafx.h"
using namespace TPCE;
namespace TPCE {
const char *szUSAreaCode = "011"; // USA/Canada phone area code
char EMAIL_DOMAINs[iNumEMAIL_DOMAINs][15] = {"@msn.com", "@hotmail.com", "@rr.com",
"@netzero.com", "@earthlink.com", "@attbi.com"};
} // namespace TPCE
// Percentages used when generating C_TIER
const int iPercentCustomersInC_TIER_1 = 20;
const int iPercentCustomersInC_TIER_2 = 60;
const int iPercentCustomersInC_TIER_3 = 100 - iPercentCustomersInC_TIER_1 - iPercentCustomersInC_TIER_2;
// Percentages used when generating C_DOB
const int iPercentUnder18 = 5;
const int iPercentBetween19And24 = 16;
const int iPercentBetween25And34 = 17;
const int iPercentBetween35And44 = 19;
const int iPercentBetween45And54 = 16;
const int iPercentBetween55And64 = 11;
const int iPercentBetween65And74 = 8;
const int iPercentBetween75And84 = 7;
const int iPercentOver85 = 1;
// Number of RNG calls to skip for one row in order
// to not use any of the random values from the previous row.
const int iRNGSkipOneRowCustomer = 35; // real max count in v3.5: 29
/*
* CCustomerTable constructor
*/
CCustomerTable::CCustomerTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer)
: TableTemplate<CUSTOMER_ROW>(), m_iRowsToGenerate(iCustomerCount), m_person(dfm, iStartFromCustomer, true),
m_Phones(dfm.AreaCodeDataFile()), m_iStartFromCustomer(iStartFromCustomer), m_iCustomerCount(iCustomerCount),
m_StatusTypeFile(dfm.StatusTypeDataFile()), m_CustomerSelection() {
m_iCompanyCount = dfm.CompanyFile().GetSize();
m_iExchangeCount = dfm.ExchangeDataFile().size();
}
/*
* Reset the state for the next load unit
*/
void CCustomerTable::InitNextLoadUnit() {
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault,
((RNGSEED)m_iLastRowNumber + m_iStartFromCustomer - 1) * iRNGSkipOneRowCustomer));
ClearRecord(); // this is needed for EGenTest to work
m_person.InitNextLoadUnit();
}
/*
* Generates only the next Customer ID value
*/
TIdent CCustomerTable::GenerateNextC_ID() {
if (m_iLastRowNumber % iDefaultLoadUnitSize == 0) {
InitNextLoadUnit();
}
++m_iLastRowNumber; // increment state info
m_bMoreRecords = m_iLastRowNumber < m_iRowsToGenerate;
m_row.C_ID = m_iLastRowNumber + m_iStartFromCustomer - 1 + iTIdentShift;
return m_row.C_ID;
}
/*
* Return current customer id.
*/
TIdent CCustomerTable::GetCurrentC_ID() {
return m_iLastRowNumber + m_iStartFromCustomer - 1 + iTIdentShift;
}
/*
* Generate tax id.
*/
void CCustomerTable::GetC_TAX_ID(TIdent C_ID, char *szOutput) {
m_person.GetTaxID(C_ID, szOutput);
}
/*
* Generate C_ST_ID.
*/
void CCustomerTable::GenerateC_ST_ID() {
strncpy(m_row.C_ST_ID, m_StatusTypeFile[eActive].ST_ID_CSTR(), sizeof(m_row.C_ST_ID));
}
/*
* Generate first, last name, and the gender.
*/
void CCustomerTable::GeneratePersonInfo() {
// Fill in the first name, last name, and the tax id
m_person.GetFirstLastAndTaxID(m_row.C_ID, m_row.C_F_NAME, m_row.C_L_NAME, m_row.C_TAX_ID);
// Fill in the gender
m_row.C_GNDR = m_person.GetGender(m_row.C_ID);
// Fill in the middle name
m_row.C_M_NAME[0] = m_person.GetMiddleName(m_row.C_ID);
m_row.C_M_NAME[1] = '\0';
}
/*
* Generate C_TIER.
*/
eCustomerTier CCustomerTable::GetC_TIER(TIdent C_ID) {
return m_CustomerSelection.GetTier(C_ID);
}
/*
* Generate date of birth.
*/
void CCustomerTable::GenerateC_DOB() {
// min and max age brackets limits in years
static int age_brackets[] = {10, 19, 25, 35, 45, 55, 65, 75, 85, 100};
int age_bracket;
int dob_daysno_min, dob_daysno_max; // min and max date of birth in days
int dob_in_days; // generated random date of birth in days
int iThreshold = m_rnd.RndGenerateIntegerPercentage();
// Determine customer age bracket according to the distribution.
if (iThreshold <= iPercentUnder18)
age_bracket = 0;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24)
age_bracket = 1;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24 + iPercentBetween25And34)
age_bracket = 2;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24 + iPercentBetween25And34 + iPercentBetween35And44)
age_bracket = 3;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24 + iPercentBetween25And34 + iPercentBetween35And44 +
iPercentBetween45And54)
age_bracket = 4;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24 + iPercentBetween25And34 + iPercentBetween35And44 +
iPercentBetween45And54 + iPercentBetween55And64)
age_bracket = 5;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24 + iPercentBetween25And34 + iPercentBetween35And44 +
iPercentBetween45And54 + iPercentBetween55And64 + iPercentBetween65And74)
age_bracket = 6;
else if (iThreshold <= iPercentUnder18 + iPercentBetween19And24 + iPercentBetween25And34 + iPercentBetween35And44 +
iPercentBetween45And54 + iPercentBetween55And64 + iPercentBetween65And74 +
iPercentBetween75And84)
age_bracket = 7;
else
age_bracket = 8;
assert(age_bracket < static_cast<int>(sizeof(age_brackets) / sizeof(age_brackets[0])));
// Determine the range of valid day numbers for this person's birthday.
dob_daysno_min = CDateTime::YMDtoDayno(InitialTradePopulationBaseYear - age_brackets[age_bracket + 1],
InitialTradePopulationBaseMonth, InitialTradePopulationBaseDay) +
1;
dob_daysno_max = CDateTime::YMDtoDayno(InitialTradePopulationBaseYear - age_brackets[age_bracket],
InitialTradePopulationBaseMonth, InitialTradePopulationBaseDay);
// Generate the random age expressed in days that falls into the particular
// range.
dob_in_days = m_rnd.RndIntRange(dob_daysno_min, dob_daysno_max);
m_row.C_DOB.Set(dob_in_days);
}
/*
* Generate C_AD_ID (address id).
*/
void CCustomerTable::GenerateC_AD_ID() {
// Generate address id sequentially, allowing space for Exchanges and
// Companies in the beggining of the address ids range.
m_row.C_AD_ID = m_iExchangeCount + m_iCompanyCount + GetCurrentC_ID();
}
/*
* Generate C_CTRY_1.
*/
void CCustomerTable::GenerateC_CTRY_1() {
strncpy(m_row.C_CTRY_1, szUSAreaCode, sizeof(m_row.C_CTRY_1));
}
/*
* Generate C_CTRY_2.
*/
void CCustomerTable::GenerateC_CTRY_2() {
strncpy(m_row.C_CTRY_2, szUSAreaCode, sizeof(m_row.C_CTRY_2));
}
/*
* Generate C_CTRY_3.
*/
void CCustomerTable::GenerateC_CTRY_3() {
strncpy(m_row.C_CTRY_3, szUSAreaCode, sizeof(m_row.C_CTRY_3));
}
/*
* Generate C_AREA_1
*/
void CCustomerTable::GenerateC_AREA_1() {
RNGSEED OldSeed;
int iThreshold;
OldSeed = m_rnd.GetSeed();
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseC_AREA_1, (RNGSEED)m_row.C_ID));
// generate Threshold up to the value of the last key (first member in a
// pair)
iThreshold = m_rnd.RndIntRange(0, m_Phones.size() - 1);
// copy the area code that corresponds to the Threshold
strncpy(m_row.C_AREA_1, m_Phones[iThreshold].AREA_CODE_CSTR(), sizeof(m_row.C_AREA_1));
m_rnd.SetSeed(OldSeed);
}
/*
* Generate C_AREA_2
*/
void CCustomerTable::GenerateC_AREA_2() {
RNGSEED OldSeed;
int iThreshold;
OldSeed = m_rnd.GetSeed();
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseC_AREA_2, (RNGSEED)m_row.C_ID));
// generate Threshold up to the value of the last key (first member in a
// pair)
iThreshold = m_rnd.RndIntRange(0, m_Phones.size() - 1);
// copy the area code that corresponds to the Threshold
strncpy(m_row.C_AREA_2, m_Phones[iThreshold].AREA_CODE_CSTR(), sizeof(m_row.C_AREA_2));
m_rnd.SetSeed(OldSeed);
}
/*
* Generate C_AREA_3
*/
void CCustomerTable::GenerateC_AREA_3() {
RNGSEED OldSeed;
int iThreshold;
OldSeed = m_rnd.GetSeed();
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseC_AREA_3, (RNGSEED)m_row.C_ID));
// generate Threshold up to the value of the last key (first member in a
// pair)
iThreshold = m_rnd.RndIntRange(0, m_Phones.size() - 1);
// copy the area code that corresponds to the Threshold
strncpy(m_row.C_AREA_3, m_Phones[iThreshold].AREA_CODE_CSTR(), sizeof(m_row.C_AREA_3));
m_rnd.SetSeed(OldSeed);
}
/*
* Generate C_LOCAL_1.
*/
void CCustomerTable::GenerateC_LOCAL_1() {
m_rnd.RndAlphaNumFormatted(m_row.C_LOCAL_1,
"nnnnnnn"); // 7-digit phone number
}
/*
* Generate C_LOCAL_2.
*/
void CCustomerTable::GenerateC_LOCAL_2() {
m_rnd.RndAlphaNumFormatted(m_row.C_LOCAL_2,
"nnnnnnn"); // 7-digit phone number
}
/*
* Generate C_LOCAL_3.
*/
void CCustomerTable::GenerateC_LOCAL_3() {
m_rnd.RndAlphaNumFormatted(m_row.C_LOCAL_3,
"nnnnnnn"); // 7-digit phone number
}
/*
* Generate C_EXT_1.
*/
void CCustomerTable::GenerateC_EXT_1() {
int iThreshold = m_rnd.RndGenerateIntegerPercentage();
if (iThreshold <= 25) {
m_rnd.RndAlphaNumFormatted(m_row.C_EXT_1,
"nnn"); // 3-digit phone extension
} else {
*m_row.C_EXT_1 = '\0'; // no extension
}
}
/*
* Generate C_EXT_2.
*/
void CCustomerTable::GenerateC_EXT_2() {
int iThreshold = m_rnd.RndGenerateIntegerPercentage();
if (iThreshold <= 15) {
m_rnd.RndAlphaNumFormatted(m_row.C_EXT_2,
"nnn"); // 3-digit phone extension
} else {
*m_row.C_EXT_2 = '\0'; // no extension
}
}
/*
* Generate C_EXT_3.
*/
void CCustomerTable::GenerateC_EXT_3() {
int iThreshold = m_rnd.RndGenerateIntegerPercentage();
if (iThreshold <= 5) {
m_rnd.RndAlphaNumFormatted(m_row.C_EXT_3,
"nnn"); // 3-digit phone extension
} else {
*m_row.C_EXT_3 = '\0'; // no extension
}
}
/*
* Generate Email 1 and Email 2 that are guaranteed to be different.
*/
void CCustomerTable::GenerateC_EMAIL_1_and_C_EMAIL_2() {
size_t iLen;
int iEmail1Index;
iEmail1Index = m_rnd.RndIntRange(0, iNumEMAIL_DOMAINs - 1);
// Generate EMAIL_1
iLen = strlen(m_row.C_L_NAME);
m_row.C_EMAIL_1[0] = m_row.C_F_NAME[0]; // first char of the first name
strncpy(&m_row.C_EMAIL_1[1], m_row.C_L_NAME, // last name
sizeof(m_row.C_EMAIL_1) - 1);
strncpy(&m_row.C_EMAIL_1[1 + iLen],
EMAIL_DOMAINs[iEmail1Index], // domain name
sizeof(m_row.C_EMAIL_1) - iLen - 1);
// Generate EMAIL_2 that is different from EMAIL_1
m_row.C_EMAIL_2[0] = m_row.C_F_NAME[0]; // first char of the first name
strncpy(&m_row.C_EMAIL_2[1], m_row.C_L_NAME,
sizeof(m_row.C_EMAIL_2) - 1); // last name
strncpy(&m_row.C_EMAIL_2[1 + iLen],
EMAIL_DOMAINs[m_rnd.RndIntRangeExclude(0, iNumEMAIL_DOMAINs - 1, iEmail1Index)], // domain name
sizeof(m_row.C_EMAIL_2) - iLen - 1);
}
/*
* Generates all column values for the next row
*/
bool CCustomerTable::GenerateNextRecord() {
GenerateNextC_ID();
GenerateC_ST_ID();
GeneratePersonInfo(); // generate last name, first name, gender and tax ID.
m_row.C_TIER = (char)GetC_TIER(m_row.C_ID);
GenerateC_DOB();
GenerateC_AD_ID();
GenerateC_CTRY_1();
GenerateC_AREA_1();
GenerateC_LOCAL_1();
GenerateC_EXT_1();
GenerateC_CTRY_2();
GenerateC_AREA_2();
GenerateC_LOCAL_2();
GenerateC_EXT_2();
GenerateC_CTRY_3();
GenerateC_AREA_3();
GenerateC_LOCAL_3();
GenerateC_EXT_3();
GenerateC_EMAIL_1_and_C_EMAIL_2();
// Return false if all the rows have been generated
return MoreRecords();
}

View File

@@ -0,0 +1,268 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson, Matt Emmerton
*/
/******************************************************************************
* Description: Implementation of the DM class.
* See DM.h for a description.
******************************************************************************/
#include "main/DM.h"
#include "main/StatusTypeIDs.h"
using namespace TPCE;
const INT32 iDataMaintenanceTableCount = 12;
static const char *DataMaintenanceTableName[iDataMaintenanceTableCount] = {
"ACCOUNT_PERMISSION", "ADDRESS", "COMPANY", "CUSTOMER", "CUSTOMER_TAXRATE", "DAILY_MARKET",
"EXCHANGE", "FINANCIAL", "NEWS_ITEM", "SECURITY", "TAXRATE", "WATCH_ITEM"};
// Automatically generate unique RNG seeds.
// The CRandom class uses an unsigned 64-bit value for the seed.
// This routine automatically generates two unique seeds. One is used for
// the TxnInput generator RNG, and the other is for the TxnMixGenerator RNG.
// The 64 bits are used as follows.
//
// Bits 0 - 31 Caller provided unique unsigned 32-bit id.
// Bit 32 0
// Bits 33 - 43 Number of days since the base time. The base time
// is set to be January 1 of the most recent year that is
// a multiple of 5. This allows enough space for the last
// field, and it makes the algorithm "timeless" by resetting
// the generated values every 5 years.
// Bits 44 - 63 Current time of day measured in 1/10's of a second.
//
void CDM::AutoSetRNGSeeds(UINT32 UniqueId) {
CDateTime Now;
INT32 BaseYear;
INT32 Tmp1, Tmp2;
Now.GetYMD(&BaseYear, &Tmp1, &Tmp2);
// Set the base year to be the most recent year that was a multiple of 5.
BaseYear -= (BaseYear % 5);
CDateTime Base(BaseYear, 1, 1); // January 1st in the BaseYear
// Initialize the seed with the current time of day measured in 1/10's of a
// second. This will use up to 20 bits.
RNGSEED Seed;
Seed = Now.MSec() / 100;
// Now add in the number of days since the base time.
// The number of days in the 5 year period requires 11 bits.
// So shift up by that much to make room in the "lower" bits.
Seed <<= 11;
Seed += (RNGSEED)((INT64)Now.DayNo() - (INT64)Base.DayNo());
// So far, we've used up 31 bits.
// Save the "last" bit of the "upper" 32 for the RNG id. In
// this case, it is always 0 since we don't have a second
// RNG in this class.
// In addition, make room for the caller's 32-bit unique id.
// So shift a total of 33 bits.
Seed <<= 33;
// Now the "upper" 32-bits have been set with a value for RNG 0.
// Add in the sponsor's unique id for the "lower" 32-bits.
Seed += UniqueId;
// Set the RNG to the unique seed.
m_rnd.SetSeed(Seed);
m_DriverDMSettings.cur.RNGSeed = Seed;
}
void CDM::Initialize(void) {
m_pLogger->SendToLogger(m_DriverGlobalSettings);
m_iSecurityCount = m_Securities.GetActiveSecurityCount();
m_iCompanyCount = m_Companies.GetActiveCompanyCount();
m_iStartFromCompany = m_Companies.GetCompanyId(0);
m_iDivisionTaxCount = m_TaxRatesDivision.size(m_TaxRatesDivision.BucketsOnly);
m_iStartFromCustomer = iDefaultStartFromCustomer + iTIdentShift;
}
CDM::CDM(CDMSUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iDaysOfInitialTrades, UINT32 UniqueId)
: m_DriverGlobalSettings(iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor, iDaysOfInitialTrades),
m_DriverDMSettings(UniqueId, 0), m_CustomerSelection(&m_rnd, iDefaultStartFromCustomer, iActiveCustomerCount),
m_AccsAndPerms(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Securities(dfm.SecurityFile()), m_Companies(dfm.CompanyFile()),
m_TaxRatesDivision(dfm.TaxRateDivisionDataFile()), m_StatusType(dfm.StatusTypeDataFile()), m_iDivisionTaxCount(0),
m_DataMaintenanceTableNum(0), m_pSUT(pSUT), m_pLogger(pLogger) {
m_pLogger->SendToLogger("DM object constructed using constructor 1 (valid "
"for publication: YES).");
Initialize();
AutoSetRNGSeeds(UniqueId);
m_pLogger->SendToLogger(m_DriverDMSettings); // log the RNG seeds
}
CDM::CDM(CDMSUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm, TIdent iConfiguredCustomerCount,
TIdent iActiveCustomerCount, INT32 iScaleFactor, INT32 iDaysOfInitialTrades, UINT32 UniqueId, RNGSEED RNGSeed)
: m_DriverGlobalSettings(iConfiguredCustomerCount, iActiveCustomerCount, iScaleFactor, iDaysOfInitialTrades),
m_DriverDMSettings(UniqueId, RNGSeed), m_rnd(RNGSeed),
m_CustomerSelection(&m_rnd, iDefaultStartFromCustomer, iActiveCustomerCount),
m_AccsAndPerms(dfm, iDefaultLoadUnitSize, iActiveCustomerCount, iDefaultStartFromCustomer),
m_Securities(dfm.SecurityFile()), m_Companies(dfm.CompanyFile()),
m_TaxRatesDivision(dfm.TaxRateDivisionDataFile()), m_StatusType(dfm.StatusTypeDataFile()), m_iDivisionTaxCount(0),
m_DataMaintenanceTableNum(0), m_pSUT(pSUT), m_pLogger(pLogger) {
m_pLogger->SendToLogger("DM object constructed using constructor 2 (valid "
"for publication: NO).");
Initialize();
m_pLogger->SendToLogger(m_DriverDMSettings); // log the RNG seeds
}
CDM::~CDM() {
m_pLogger->SendToLogger("DM object destroyed.");
}
TIdent CDM::GenerateRandomCustomerId() {
return m_rnd.RndInt64Range(m_iStartFromCustomer,
m_iStartFromCustomer + m_DriverGlobalSettings.cur.iActiveCustomerCount - 1);
}
TIdent CDM::GenerateRandomCustomerAccountId() {
TIdent iCustomerId;
eCustomerTier iCustomerTier;
m_CustomerSelection.GenerateRandomCustomer(iCustomerId, iCustomerTier);
return (m_AccsAndPerms.GenerateRandomAccountId(m_rnd, iCustomerId, iCustomerTier));
}
TIdent CDM::GenerateRandomCompanyId() {
return m_rnd.RndInt64Range(m_iStartFromCompany, m_iStartFromCompany + m_iCompanyCount - 1);
}
TIdent CDM::GenerateRandomSecurityId() {
return m_rnd.RndInt64Range(0, m_iSecurityCount - 1);
}
RNGSEED CDM::GetRNGSeed(void) {
return (m_rnd.GetSeed());
}
void CDM::DoTxn(void) {
m_TxnInput.Clear();
strncpy(m_TxnInput.table_name, DataMaintenanceTableName[m_DataMaintenanceTableNum], sizeof(m_TxnInput.table_name));
switch (m_DataMaintenanceTableNum) {
case 0: // ACCOUNT_PERMISSION
m_TxnInput.acct_id = GenerateRandomCustomerAccountId();
break;
case 1: // ADDRESS
if (m_rnd.RndPercent(67)) {
m_TxnInput.c_id = GenerateRandomCustomerId();
} else {
m_TxnInput.co_id = GenerateRandomCompanyId();
}
break;
case 2: // COMPANY
m_TxnInput.co_id = GenerateRandomCompanyId();
break;
case 3: // CUSTOMER
m_TxnInput.c_id = GenerateRandomCustomerId();
break;
case 4: // CUSTOMER_TAXRATE
m_TxnInput.c_id = GenerateRandomCustomerId();
break;
case 5: // DAILY_MARKET
m_Securities.CreateSymbol(GenerateRandomSecurityId(), m_TxnInput.symbol,
static_cast<int>(sizeof(m_TxnInput.symbol)));
m_TxnInput.day_of_month = m_rnd.RndIntRange(1, 31);
m_TxnInput.vol_incr = m_rnd.RndIntRange(-2, 3);
if (m_TxnInput.vol_incr == 0) // don't want 0 as increment
{
m_TxnInput.vol_incr = -3;
}
break;
case 6: // EXCHANGE
break;
case 7: // FINANCIAL
m_TxnInput.co_id = GenerateRandomCompanyId();
break;
case 8: // NEWS_ITEM
m_TxnInput.co_id = GenerateRandomCompanyId();
break;
case 9: // SECURITY
m_Securities.CreateSymbol(GenerateRandomSecurityId(), m_TxnInput.symbol,
static_cast<int>(sizeof(m_TxnInput.symbol)));
break;
case 10: // TAXRATE
{
UINT bucketIdx = static_cast<UINT>(m_rnd.RndIntRange(0, m_iDivisionTaxCount - 1));
UINT recordIdx = static_cast<UINT>(m_rnd.RndIntRange(0, m_TaxRatesDivision[bucketIdx].size() - 1));
strncpy(m_TxnInput.tx_id, m_TaxRatesDivision[bucketIdx][recordIdx].TX_ID_CSTR(), sizeof(m_TxnInput.tx_id));
} break;
case 11: // WATCH_ITEM
m_TxnInput.c_id = GenerateRandomCustomerId();
break;
default:
assert(false); // should never happen
}
m_pSUT->DataMaintenance(&m_TxnInput);
m_DataMaintenanceTableNum = (m_DataMaintenanceTableNum + 1) % iDataMaintenanceTableCount;
}
void CDM::DoCleanupTxn(void) {
memset(&m_CleanupTxnInput, 0, sizeof(m_CleanupTxnInput));
// Compute Starting Trade ID (Copied from CETxnInputGenerator.cpp)
m_CleanupTxnInput.start_trade_id =
(TTrade)((m_DriverGlobalSettings.cur.iDaysOfInitialTrades * (TTrade)HoursPerWorkDay * (TTrade)SecondsPerHour *
(m_DriverGlobalSettings.cur.iConfiguredCustomerCount / m_DriverGlobalSettings.cur.iScaleFactor)) *
iAbortTrade / 100) +
1 + iTTradeShift; // 1.01 to account for rollbacks, +1 to get first
// runtime trade
// Copy the status type id's from the flat file
strncpy(m_CleanupTxnInput.st_pending_id, m_StatusType[ePending].ST_ID_CSTR(),
sizeof(m_CleanupTxnInput.st_pending_id));
strncpy(m_CleanupTxnInput.st_submitted_id, m_StatusType[eSubmitted].ST_ID_CSTR(),
sizeof(m_CleanupTxnInput.st_submitted_id));
strncpy(m_CleanupTxnInput.st_canceled_id, m_StatusType[eCanceled].ST_ID_CSTR(),
sizeof(m_CleanupTxnInput.st_canceled_id));
// Execute Transaction
m_pSUT->TradeCleanup(&m_CleanupTxnInput);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,575 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy, Matt Emmerton, Doug Johnson
*/
//
// Defines the entry point for the console application.
//
#include <string>
#include "main/EGenLoader_stdafx.h"
#include "input/DataFileManager.h"
using namespace TPCE;
// Driver Defaults
TIdent iStartFromCustomer = iDefaultStartFromCustomer;
TIdent iCustomerCount = iDefaultCustomerCount; // # of customers for this instance
TIdent iTotalCustomerCount = iDefaultCustomerCount; // total number of customers in the database
UINT iLoadUnitSize = iDefaultLoadUnitSize; // # of customers in one load unit
UINT iScaleFactor = 500; // # of customers for 1 tpsE
UINT iDaysOfInitialTrades = 300;
// These flags are used to control which tables get generated and loaded.
bool bTableGenerationFlagNotSpecified = true; // assume no flag is specified.
bool bGenerateFixedTables = false;
bool bGenerateGrowingTables = false;
bool bGenerateScalingTables = false;
bool bGenerateUsingCache = true;
char szInDir[iMaxPath];
#ifdef COMPILE_FLAT_FILE_LOAD
char szOutDir[iMaxPath];
FlatFileOutputModes FlatFileOutputMode;
#endif
#ifdef COMPILE_ODBC_LOAD
char szServer[iMaxHostname];
char szDB[iMaxDBName];
#endif
#if defined(COMPILE_ODBC_LOAD) || defined(COMPILE_CUSTOM_LOAD)
char szLoaderParms[1024];
#endif
#ifndef FLAT_IN_PATH
#define FLAT_IN_PATH "flat_in/"
#endif
#ifndef FLAT_OUT_PATH
#define FLAT_OUT_PATH "flat_out/"
#endif
enum eLoadImplementation {
NULL_LOAD = 0, // no load - generate data only
FLAT_FILE_LOAD,
ODBC_LOAD,
CUSTOM_LOAD // sponsor-provided load mechanism
};
#if defined(DEFAULT_LOAD_TYPE)
eLoadImplementation LoadType = DEFAULT_LOAD_TYPE;
#elif defined(COMPILE_FLAT_FILE_LOAD)
eLoadImplementation LoadType = FLAT_FILE_LOAD;
#elif defined(COMPILE_ODBC_LOAD)
eLoadImplementation LoadType = ODBC_LOAD;
#elif defined(COMPILE_CUSTOM_LOAD)
eLoadImplementation LoadType = CUSTOM_LOAD;
#else
eLoadImplementation LoadType = NULL_LOAD;
#endif
/*
* Prints program usage to std error.
*/
void Usage() {
fprintf(stderr, "Usage:\n");
fprintf(stderr, "EGenLoader [options] \n\n");
fprintf(stderr, " Where\n");
fprintf(stderr, " Option Default Description\n");
fprintf(stderr, " -b number %" PRId64 " Beginning customer ordinal position\n",
iStartFromCustomer);
fprintf(stderr, " -c number %" PRId64 " Number of customers (for this instance)\n",
iCustomerCount);
fprintf(stderr, " -t number %" PRId64 " Number of customers (total in the database)\n",
iTotalCustomerCount);
fprintf(stderr,
" -f number %d Scale factor (customers "
"per 1 tpsE)\n",
iScaleFactor);
fprintf(stderr,
" -w number %d Number of Workdays "
"(8-hour days) of \n",
iDaysOfInitialTrades);
fprintf(stderr, " initial trades "
"to populate\n");
fprintf(stderr, " -i dir %-11s Directory for input files\n", FLAT_IN_PATH);
fprintf(stderr, " -l [FLAT|ODBC|CUSTOM|NULL] FLAT Type of load\n");
#ifdef COMPILE_FLAT_FILE_LOAD
fprintf(stderr, " -m [APPEND|OVERWRITE] OVERWRITE Flat File output mode\n");
fprintf(stderr, " -o dir %-11s Directory for output files\n", FLAT_OUT_PATH);
#endif
#ifdef COMPILE_ODBC_LOAD
fprintf(stderr, " -s string localhost Database server\n");
fprintf(stderr, " -d string tpce Database name\n");
#endif
#if defined(COMPILE_ODBC_LOAD) || defined(COMPILE_CUSTOM_LOAD)
fprintf(stderr, " -p string Additional "
"parameters to loader\n");
#endif
fprintf(stderr, "\n");
fprintf(stderr, " -x -x Generate all tables\n");
fprintf(stderr, " -xf Generate all "
"fixed-size tables\n");
fprintf(stderr, " -xd Generate all "
"scaling and growing tables\n");
fprintf(stderr, " (equivalent to -xs -xg)\n");
fprintf(stderr, " -xs Generate scaling tables\n");
fprintf(stderr, " (except BROKER)\n");
fprintf(stderr, " -xg Generate "
"growing tables and BROKER\n");
fprintf(stderr, " -g Disable "
"caching when generating growing tables\n");
}
void ParseCommandLine(int argc, char *argv[]) {
int arg;
char *sp;
char *vp;
/*
* Scan the command line arguments
*/
for (arg = 1; arg < argc; ++arg) {
/*
* Look for a switch
*/
sp = argv[arg];
if (*sp == '-') {
++sp;
}
*sp = (char)tolower(*sp);
/*
* Find the switch's argument. It is either immediately after the
* switch or in the next argv
*/
vp = sp + 1;
// Allow for switched that don't have any parameters.
// Need to check that the next argument is in fact a parameter
// and not the next switch that starts with '-'.
//
if ((*vp == 0) && ((arg + 1) < argc) && (argv[arg + 1][0] != '-')) {
vp = argv[++arg];
}
/*
* Parse the switch
*/
switch (*sp) {
case 'b':
sscanf(vp, "%" PRId64, &iStartFromCustomer);
if (iStartFromCustomer <= 0) { // set back to default
// either number parsing was unsuccessful
// or a bad value was specified
iStartFromCustomer = iDefaultStartFromCustomer;
}
break;
case 'c':
sscanf(vp, "%" PRId64, &iCustomerCount);
break;
case 't':
sscanf(vp, "%" PRId64, &iTotalCustomerCount);
break;
case 'f':
iScaleFactor = (UINT)atoi(vp);
break;
case 'w':
iDaysOfInitialTrades = (UINT)atoi(vp);
break;
case 'i': // Location of input files.
strncpy(szInDir, vp, sizeof(szInDir));
if (('/' != szInDir[strlen(szInDir) - 1]) && ('\\' != szInDir[strlen(szInDir) - 1])) {
strncat(szInDir, "/", sizeof(szInDir) - strlen(szInDir) - 1);
}
break;
case 'l': // Load type.
#ifdef COMPILE_FLAT_FILE_LOAD
if (0 == strcmp(vp, "FLAT")) {
LoadType = FLAT_FILE_LOAD;
break;
}
#endif
#ifdef COMPILE_ODBC_LOAD
if (0 == strcmp(vp, "ODBC")) {
LoadType = ODBC_LOAD;
break;
}
#endif
if (0 == strcmp(vp, "NULL")) {
LoadType = NULL_LOAD;
break;
}
#ifdef COMPILE_CUSTOM_LOAD
if (0 == strcmp(vp, "CUSTOM")) {
LoadType = CUSTOM_LOAD;
break;
}
#endif
Usage();
exit(ERROR_BAD_OPTION);
break;
#ifdef COMPILE_FLAT_FILE_LOAD
case 'm': // Mode for output of flat files.
if (0 == strcmp(vp, "APPEND")) {
FlatFileOutputMode = FLAT_FILE_OUTPUT_APPEND;
} else if (0 == strcmp(vp, "OVERWRITE")) {
FlatFileOutputMode = FLAT_FILE_OUTPUT_OVERWRITE;
} else {
Usage();
exit(ERROR_BAD_OPTION);
}
break;
case 'o': // Location for output files.
strncpy(szOutDir, vp, sizeof(szOutDir));
if (('/' != szOutDir[strlen(szOutDir) - 1]) && ('\\' != szOutDir[strlen(szOutDir) - 1])) {
strncat(szOutDir, "/", sizeof(szOutDir) - strlen(szOutDir) - 1);
}
break;
#endif
#ifdef COMPILE_ODBC_LOAD
case 's': // Database server name.
strncpy(szServer, vp, sizeof(szServer));
break;
case 'd': // Database name.
strncpy(szDB, vp, sizeof(szDB));
break;
#endif
#if defined(COMPILE_ODBC_LOAD) || defined(COMPILE_CUSTOM_LOAD)
case 'p': // Loader Parameters
strncpy(szLoaderParms, vp, sizeof(szLoaderParms));
break;
#endif
case 'g': // Disable Cache for Growing Tables (CTradeGen)
bGenerateUsingCache = false;
break;
case 'x': // Table Generation
bTableGenerationFlagNotSpecified = false; // A -x flag has been used
if (NULL == vp || *vp == '\0') {
bGenerateFixedTables = true;
bGenerateGrowingTables = true;
bGenerateScalingTables = true;
} else if (0 == strcmp(vp, "f")) {
bGenerateFixedTables = true;
} else if (0 == strcmp(vp, "g")) {
bGenerateGrowingTables = true;
} else if (0 == strcmp(vp, "s")) {
bGenerateScalingTables = true;
} else if (0 == strcmp(vp, "d")) {
bGenerateGrowingTables = true;
bGenerateScalingTables = true;
} else {
Usage();
exit(ERROR_BAD_OPTION);
}
break;
default:
Usage();
fprintf(stderr, "Error: Unrecognized option: %s\n", sp);
exit(ERROR_BAD_OPTION);
}
}
}
/*
* This function validates EGenLoader parameters that may have been
* specified on the command line. It's purpose is to prevent passing of
* parameter values that would cause the loader to produce incorrect data.
*
* Condition: needs to be called after ParseCommandLine.
*
* PARAMETERS:
* NONE
*
* RETURN:
* true - if all parameters are valid
* false - if at least one parameter is invalid
*/
bool ValidateParameters() {
bool bRet = true;
// Starting customer must be a non-zero integral multiple of load unit size
// + 1.
//
if ((iStartFromCustomer % iLoadUnitSize) != 1) {
cout << "The specified starting customer (-b " << iStartFromCustomer
<< ") must be a non-zero integral multiple of the load unit size (" << iLoadUnitSize << ") + 1." << endl;
bRet = false;
}
// Total number of customers in the database cannot be less
// than the number of customers for this loader instance
//
if (iTotalCustomerCount < iStartFromCustomer + iCustomerCount - 1) {
iTotalCustomerCount = iStartFromCustomer + iCustomerCount - 1;
}
// Customer count must be a non-zero integral multiple of load unit size.
//
if ((iLoadUnitSize > iCustomerCount) || (0 != iCustomerCount % iLoadUnitSize)) {
cout << "The specified customer count (-c " << iCustomerCount
<< ") must be a non-zero integral multiple of the load unit size (" << iLoadUnitSize << ")." << endl;
bRet = false;
}
// Total customer count must be a non-zero integral multiple of load unit
// size.
//
if ((iLoadUnitSize > iTotalCustomerCount) || (0 != iTotalCustomerCount % iLoadUnitSize)) {
cout << "The total customer count (-t " << iTotalCustomerCount
<< ") must be a non-zero integral multiple of the load unit size (" << iLoadUnitSize << ")." << endl;
bRet = false;
}
// Completed trades in 8 hours must be a non-zero integral multiple of 100
// so that exactly 1% extra trade ids can be assigned to simulate aborts.
//
if ((INT64)(HoursPerWorkDay * SecondsPerHour * iLoadUnitSize / iScaleFactor) % 100 != 0) {
cout << "Incompatible value for Scale Factor (-f) specified." << endl;
cout << HoursPerWorkDay << " * " << SecondsPerHour << " * Load Unit Size (" << iLoadUnitSize
<< ") / Scale Factor (" << iScaleFactor << ") must be integral multiple of 100." << endl;
bRet = false;
}
if (iDaysOfInitialTrades == 0) {
cout << "The specified number of 8-Hour Workdays (-w " << (iDaysOfInitialTrades) << ") must be non-zero."
<< endl;
bRet = false;
}
return bRet;
}
/*
* Create loader class factory corresponding to the
* selected load type.
*/
CBaseLoaderFactory *CreateLoaderFactory(eLoadImplementation eLoadType) {
switch (eLoadType) {
case NULL_LOAD:
return new CNullLoaderFactory();
#ifdef COMPILE_ODBC_LOAD
case ODBC_LOAD:
return new CODBCLoaderFactory(szServer, szDB, szLoaderParms);
#endif // #ifdef COMPILE_ODBC_LOAD
#ifdef COMPILE_FLAT_FILE_LOAD
case FLAT_FILE_LOAD:
return new CFlatLoaderFactory(szOutDir, FlatFileOutputMode);
#endif //#ifdef COMPILE_FLAT_FILE_LOAD
#ifdef COMPILE_CUSTOM_LOAD
case CUSTOM_LOAD:
return new CCustomLoaderFactory(szLoaderParms);
#endif //#ifdef COMPILE_CUSTOM_FILE_LOAD
default:
assert(false); // this should never happen
}
return NULL; // should never happen
}
int main(int argc, char *argv[]) {
CBaseLoaderFactory *pLoaderFactory; // class factory that creates table loaders
CGenerateAndLoadStandardOutput Output;
CGenerateAndLoad *pGenerateAndLoad;
CDateTime StartTime, EndTime, LoadTime; // to time the database load
// Output EGen version
PrintEGenVersion();
// Establish defaults for command line options.
#ifdef COMPILE_ODBC_LOAD
strncpy(szServer, "localhost", sizeof(szServer));
strncpy(szDB, "tpce", sizeof(szDB));
#endif
strncpy(szInDir, FLAT_IN_PATH, sizeof(szInDir));
#ifdef COMPILE_FLAT_FILE_LOAD
strncpy(szOutDir, FLAT_OUT_PATH, sizeof(szOutDir));
FlatFileOutputMode = FLAT_FILE_OUTPUT_OVERWRITE;
#endif
// Get command line options.
//
ParseCommandLine(argc, argv);
// Validate global parameters that may have been modified on
// the command line.
//
if (!ValidateParameters()) {
return ERROR_INVALID_OPTION_VALUE; // exit from the loader returning a
// non-zero code
}
// Let the user know what settings will be used.
cout << endl << endl << "Using the following settings." << endl << endl;
switch (LoadType) {
#ifdef COMPILE_ODBC_LOAD
case ODBC_LOAD:
cout << "\tLoad Type:\t\tODBC" << endl;
cout << "\tServer Name:\t\t" << szServer << endl;
cout << "\tDatabase:\t\t" << szDB << endl;
break;
#endif
#ifdef COMPILE_FLAT_FILE_LOAD
case FLAT_FILE_LOAD:
cout << "\tLoad Type:\t\tFlat File" << endl;
switch (FlatFileOutputMode) {
case FLAT_FILE_OUTPUT_APPEND:
cout << "\tOutput Mode:\t\tAPPEND" << endl;
break;
case FLAT_FILE_OUTPUT_OVERWRITE:
cout << "\tOutput Mode:\t\tOVERWRITE" << endl;
break;
}
cout << "\tOut Directory:\t\t" << szOutDir << endl;
break;
#endif
#ifdef COMPILE_CUSTOM_LOAD
case CUSTOM_LOAD:
cout << "\tLoad Type:\t\tCustom" << endl;
cout << "\tLoader Parms:\t\t" << szLoaderParms << endl;
break;
#endif
case NULL_LOAD:
default:
cout << "\tLoad Type:\t\tNull load (generation only)" << endl;
break;
}
cout << "\tIn Directory:\t\t" << szInDir << endl;
cout << "\tStart From Customer:\t" << iStartFromCustomer << endl;
cout << "\tCustomer Count:\t\t" << iCustomerCount << endl;
cout << "\tTotal customers:\t" << iTotalCustomerCount << endl;
cout << "\tLoad Unit:\t\t" << iLoadUnitSize << endl;
cout << "\tScale Factor:\t\t" << iScaleFactor << endl;
cout << "\tInitial Trade Days:\t" << iDaysOfInitialTrades << endl;
cout << "\tCaching Enabled:\t" << (bGenerateUsingCache ? "true" : "false") << endl;
cout << endl << endl;
// Know the load type => create the loader factory.
//
pLoaderFactory = CreateLoaderFactory(LoadType);
try {
// Create a unique log name for this loader instance.
// Simultaneous loader instances are to be run with
// disjoint customer ranges, so use this fact to
// construct a unique name.
//
char szLogFileName[64];
snprintf(&szLogFileName[0], sizeof(szLogFileName), "EGenLoaderFrom%" PRId64 "To%" PRId64 ".log",
iStartFromCustomer, (iStartFromCustomer + iCustomerCount) - 1);
// Create log formatter and logger instance
CLogFormatTab fmt;
CEGenLogger logger(eDriverEGenLoader, 0, szLogFileName, &fmt);
// Set up data file manager for lazy load.
const DataFileManager dfm(std::string(szInDir), iTotalCustomerCount, iTotalCustomerCount);
// Create the main class instance
pGenerateAndLoad = new CGenerateAndLoad(dfm, iCustomerCount, iStartFromCustomer, iTotalCustomerCount,
iLoadUnitSize, iScaleFactor, iDaysOfInitialTrades, pLoaderFactory,
&logger, &Output, szInDir, bGenerateUsingCache);
// The generate and load phase starts here.
//
StartTime.Set();
// Generate static tables if appropriate.
if ((bTableGenerationFlagNotSpecified && (iStartFromCustomer == iDefaultStartFromCustomer)) ||
bGenerateFixedTables) {
pGenerateAndLoad->GenerateAndLoadFixedTables();
}
// Generate dynamic scaling tables if appropriate.
if (bTableGenerationFlagNotSpecified || bGenerateScalingTables) {
pGenerateAndLoad->GenerateAndLoadScalingTables();
}
// Generate dynamic trade tables if appropriate.
if (bTableGenerationFlagNotSpecified || bGenerateGrowingTables) {
pGenerateAndLoad->GenerateAndLoadGrowingTables();
}
// The generate and load phase ends here.
//
EndTime.Set();
LoadTime.Set(0); // clear time
LoadTime.Add(0, (int)((EndTime - StartTime) * MsPerSecond)); // add ms
cout << endl << "Generate and load time: " << LoadTime.ToStr(01) << endl << endl;
delete pGenerateAndLoad; // don't really need to do that, but just for
// good style
delete pLoaderFactory; // don't really need to do that, but just for
// good style
} catch (CBaseErr &err) {
cout << endl << "Error " << err.ErrorNum() << ": " << err.ErrorText();
if (err.ErrorLoc()) {
cout << " at " << err.ErrorLoc() << endl;
} else {
cout << endl;
}
return 1;
}
// operator new will throw std::bad_alloc exception if there is no
// sufficient memory for the request.
//
catch (std::bad_alloc &) {
cout << endl << endl << "*** Out of memory ***" << endl;
return 2;
} catch (std::exception &err) {
cout << endl << endl << "Caught Exception: " << err.what() << endl;
} catch (...) {
cout << endl << endl << "Caught Unknown Exception" << endl;
}
return 0;
}

View File

@@ -0,0 +1,422 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Matt Emmerton
*/
/******************************************************************************
* Description: This file implements the methods for formatting
* log entries in TSV or CSV format.
******************************************************************************/
#include "main/EGenLogFormatterTab.h"
#include "main/DriverTypes.h"
using namespace TPCE;
////////////////////////////////////////////////////////////////
// CE Transaction Settings
////////////////////////////////////////////////////////////////
string CLogFormatTab::GetLogOutput(CBrokerVolumeSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Broker Volume Parameters: NONE" << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CCustomerPositionSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Customer Position Parameters:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "By Cust ID: " << parms.dft.by_cust_id << "\t" << parms.cur.by_cust_id << "\t"
<< (parms.state.by_cust_id ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "By Tax ID: " << parms.dft.by_tax_id << "\t" << parms.cur.by_tax_id << "\t"
<< (parms.state.by_tax_id ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Get History: " << parms.dft.get_history << "\t" << parms.cur.get_history << "\t"
<< (parms.state.get_history ? "YES" : "NO") << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CMarketWatchSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Market Watch Parameters:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "By Account ID: " << parms.dft.by_acct_id << "\t" << parms.cur.by_acct_id << "\t"
<< (parms.state.by_acct_id ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "By Industry: " << parms.dft.by_industry << "\t" << parms.cur.by_industry << "\t"
<< (parms.state.by_industry ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "By Watch List: " << parms.dft.by_watch_list << "\t" << parms.cur.by_watch_list
<< "\t" << (parms.state.by_watch_list ? "YES" : "NO") << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CSecurityDetailSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Security Detail Parameters:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "LOB Access Pct: " << parms.dft.LOBAccessPercentage << "\t"
<< parms.cur.LOBAccessPercentage << "\t" << (parms.state.LOBAccessPercentage ? "YES" : "NO") << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CTradeLookupSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Trade Lookup Parameters:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Frame 1 Pct:" << parms.dft.do_frame1 << "\t" << parms.cur.do_frame1 << "\t"
<< (parms.state.do_frame1 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 2 Pct:" << parms.dft.do_frame2 << "\t" << parms.cur.do_frame2 << "\t"
<< (parms.state.do_frame2 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 3 Pct:" << parms.dft.do_frame3 << "\t" << parms.cur.do_frame3 << "\t"
<< (parms.state.do_frame3 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 4 Pct:" << parms.dft.do_frame4 << "\t" << parms.cur.do_frame4 << "\t"
<< (parms.state.do_frame4 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 1 MaxRows:" << parms.dft.MaxRowsFrame1 << "\t" << parms.cur.MaxRowsFrame1
<< "\t" << (parms.state.MaxRowsFrame1 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 2 MaxRows:" << parms.dft.MaxRowsFrame2 << "\t" << parms.cur.MaxRowsFrame2
<< "\t" << (parms.state.MaxRowsFrame2 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 3 MaxRows:" << parms.dft.MaxRowsFrame3 << "\t" << parms.cur.MaxRowsFrame3
<< "\t" << (parms.state.MaxRowsFrame3 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 4 MaxRows:" << parms.dft.MaxRowsFrame4 << "\t" << parms.cur.MaxRowsFrame4
<< "\t" << (parms.state.MaxRowsFrame4 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "BackOffFromEndTimeFrame2:" << parms.dft.BackOffFromEndTimeFrame2 << "\t"
<< parms.cur.BackOffFromEndTimeFrame2 << "\t" << (parms.state.BackOffFromEndTimeFrame2 ? "YES" : "NO")
<< endl;
logmsg << left << setw(40) << "BackOffFromEndTimeFrame3:" << parms.dft.BackOffFromEndTimeFrame3 << "\t"
<< parms.cur.BackOffFromEndTimeFrame3 << "\t" << (parms.state.BackOffFromEndTimeFrame3 ? "YES" : "NO")
<< endl;
logmsg << left << setw(40) << "BackOffFromEndTimeFrame4:" << parms.dft.BackOffFromEndTimeFrame4 << "\t"
<< parms.cur.BackOffFromEndTimeFrame4 << "\t" << (parms.state.BackOffFromEndTimeFrame4 ? "YES" : "NO")
<< endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CTradeOrderSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Trade Order Parameters:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Market Trade Pct:" << parms.dft.market << "\t" << parms.cur.market << "\t"
<< (parms.state.market ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Limit Trade Pct:" << parms.dft.limit << "\t" << parms.cur.limit << "\t"
<< (parms.state.limit ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Stop Loss Pct:" << parms.dft.stop_loss << "\t" << parms.cur.stop_loss << "\t"
<< (parms.state.stop_loss ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Security by Name Pct:" << parms.dft.security_by_name << "\t"
<< parms.cur.security_by_name << "\t" << (parms.state.security_by_name ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Security by Symbol Pct:" << parms.dft.security_by_symbol << "\t"
<< parms.cur.security_by_symbol << "\t" << (parms.state.security_by_symbol ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Buy Order Pct:" << parms.dft.buy_orders << "\t" << parms.cur.buy_orders << "\t"
<< (parms.state.buy_orders ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Sell Order Pct:" << parms.dft.sell_orders << "\t" << parms.cur.sell_orders << "\t"
<< (parms.state.sell_orders ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "LIFO Pct:" << parms.dft.lifo << "\t" << parms.cur.lifo << "\t"
<< (parms.state.lifo ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Margin Trade Pct:" << parms.dft.type_is_margin << "\t" << parms.cur.type_is_margin
<< "\t" << (parms.state.type_is_margin ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Executor as Owner Pct:" << parms.dft.exec_is_owner << "\t" << parms.cur.exec_is_owner
<< "\t" << (parms.state.exec_is_owner ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Rollback Pct:" << parms.dft.rollback << "\t" << parms.cur.rollback << "\t"
<< (parms.state.rollback ? "YES" : "NO") << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CTradeUpdateSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Trade Update Parameters:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Frame 1 Pct:" << parms.dft.do_frame1 << "\t" << parms.cur.do_frame1 << "\t"
<< (parms.state.do_frame1 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 2 Pct:" << parms.dft.do_frame2 << "\t" << parms.cur.do_frame2 << "\t"
<< (parms.state.do_frame2 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 3 Pct:" << parms.dft.do_frame3 << "\t" << parms.cur.do_frame3 << "\t"
<< (parms.state.do_frame3 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 1 MaxRows:" << parms.dft.MaxRowsFrame1 << "\t" << parms.cur.MaxRowsFrame1
<< "\t" << (parms.state.MaxRowsFrame1 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 2 MaxRows:" << parms.dft.MaxRowsFrame2 << "\t" << parms.cur.MaxRowsFrame2
<< "\t" << (parms.state.MaxRowsFrame2 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 3 MaxRows:" << parms.dft.MaxRowsFrame3 << "\t" << parms.cur.MaxRowsFrame3
<< "\t" << (parms.state.MaxRowsFrame3 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 1 MaxRowsToUpdate:" << parms.dft.MaxRowsToUpdateFrame1 << "\t"
<< parms.cur.MaxRowsToUpdateFrame1 << "\t" << (parms.state.MaxRowsToUpdateFrame1 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 2 MaxRowsToUpdate:" << parms.dft.MaxRowsToUpdateFrame2 << "\t"
<< parms.cur.MaxRowsToUpdateFrame2 << "\t" << (parms.state.MaxRowsToUpdateFrame2 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Frame 3 MaxRowsToUpdate:" << parms.dft.MaxRowsToUpdateFrame3 << "\t"
<< parms.cur.MaxRowsToUpdateFrame3 << "\t" << (parms.state.MaxRowsToUpdateFrame3 ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "BackOffFromEndTimeFrame2:" << parms.dft.BackOffFromEndTimeFrame2 << "\t"
<< parms.cur.BackOffFromEndTimeFrame2 << "\t" << (parms.state.BackOffFromEndTimeFrame2 ? "YES" : "NO")
<< endl;
logmsg << left << setw(40) << "BackOffFromEndTimeFrame3:" << parms.dft.BackOffFromEndTimeFrame3 << "\t"
<< parms.cur.BackOffFromEndTimeFrame3 << "\t" << (parms.state.BackOffFromEndTimeFrame3 ? "YES" : "NO")
<< endl;
// Send String to Logger
return (logmsg.str());
}
////////////////////////////////////////////////////////////////
// CE Transaction Mix Settings
////////////////////////////////////////////////////////////////
string CLogFormatTab::GetLogOutput(CTxnMixGeneratorSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Transaction Mixes:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Broker Volume: " << parms.dft.BrokerVolumeMixLevel << "\t"
<< parms.cur.BrokerVolumeMixLevel << "\t" << (parms.state.BrokerVolumeMixLevel ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Customer Position: " << parms.dft.CustomerPositionMixLevel << "\t"
<< parms.cur.CustomerPositionMixLevel << "\t" << (parms.state.CustomerPositionMixLevel ? "YES" : "NO")
<< endl;
logmsg << left << setw(40) << "Market Watch: " << parms.dft.MarketWatchMixLevel << "\t"
<< parms.cur.MarketWatchMixLevel << "\t" << (parms.state.MarketWatchMixLevel ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Security Detail: " << parms.dft.SecurityDetailMixLevel << "\t"
<< parms.cur.SecurityDetailMixLevel << "\t" << (parms.state.SecurityDetailMixLevel ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Trade Lookup: " << parms.dft.TradeLookupMixLevel << "\t"
<< parms.cur.TradeLookupMixLevel << "\t" << (parms.state.TradeLookupMixLevel ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Trade Order: " << parms.dft.TradeOrderMixLevel << "\t"
<< parms.cur.TradeOrderMixLevel << "\t" << (parms.state.TradeOrderMixLevel ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Trade Status: " << parms.dft.TradeStatusMixLevel << "\t"
<< parms.cur.TradeStatusMixLevel << "\t" << (parms.state.TradeStatusMixLevel ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Trade Update: " << parms.dft.TradeUpdateMixLevel << "\t"
<< parms.cur.TradeUpdateMixLevel << "\t" << (parms.state.TradeUpdateMixLevel ? "YES" : "NO") << endl;
// Send String to Logger
return (logmsg.str());
}
////////////////////////////////////////////////////////////////
// Loader Settings
////////////////////////////////////////////////////////////////
string CLogFormatTab::GetLogOutput(CLoaderSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Loader Settings:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Configured Customers:" << parms.dft.iConfiguredCustomerCount << "\t"
<< parms.cur.iConfiguredCustomerCount << endl;
if (parms.cur.iConfiguredCustomerCount != parms.cur.iActiveCustomerCount) {
logmsg << left << setw(40) << "Active Customers:" << parms.dft.iActiveCustomerCount << "\t"
<< parms.cur.iActiveCustomerCount << endl;
}
logmsg << left << setw(40) << "Starting Customer:" << parms.dft.iStartingCustomer << "\t"
<< parms.cur.iStartingCustomer << endl;
logmsg << left << setw(40) << "Customer Count:" << parms.dft.iCustomerCount << "\t" << parms.cur.iCustomerCount
<< endl;
logmsg << left << setw(40) << "Scale Factor:" << parms.dft.iScaleFactor << "\t" << parms.cur.iScaleFactor << "\t"
<< (parms.state.iScaleFactor ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Days of Initial Trades:" << parms.dft.iDaysOfInitialTrades << "\t"
<< parms.cur.iDaysOfInitialTrades << "\t" << (parms.state.iDaysOfInitialTrades ? "YES" : "NO") << endl;
return (logmsg.str());
}
////////////////////////////////////////////////////////////////
// Driver Settings
////////////////////////////////////////////////////////////////
string CLogFormatTab::GetLogOutput(CDriverGlobalSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Driver Global Settings:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Configured Customers:" << parms.dft.iConfiguredCustomerCount << "\t"
<< parms.cur.iConfiguredCustomerCount << endl;
logmsg << left << setw(40) << "Active Customers:" << parms.dft.iActiveCustomerCount << "\t"
<< parms.cur.iActiveCustomerCount << endl;
logmsg << left << setw(40) << "Scale Factor:" << parms.dft.iScaleFactor << "\t" << parms.cur.iScaleFactor << "\t"
<< (parms.state.iScaleFactor ? "YES" : "NO") << endl;
logmsg << left << setw(40) << "Days of Initial Trades:" << parms.dft.iDaysOfInitialTrades << "\t"
<< parms.cur.iDaysOfInitialTrades << "\t" << (parms.state.iDaysOfInitialTrades ? "YES" : "NO") << endl;
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CDriverCESettings &parms) {
// Construct Log String
logmsg.str(emptyString);
logmsg << "Driver CE Settings:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Value" << endl;
logmsg << left << setw(40) << "Unique ID:" << parms.cur.UniqueId << endl;
logmsg << left << setw(40) << "Txn Mix RNGSeed:" << parms.cur.TxnMixRNGSeed << endl;
logmsg << left << setw(40) << "Txn Input RNGSeed:" << parms.cur.TxnInputRNGSeed << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CDriverCEPartitionSettings &parms) {
// Compare against defaults
parms.CheckDefaults();
// Construct Log String
logmsg.str(emptyString);
logmsg << "Driver CE Partition Settings:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Default"
<< "\t"
<< "Current"
<< "\t"
<< "Default?" << endl;
logmsg << left << setw(40) << "Partition Starting Customer ID:" << parms.dft.iMyStartingCustomerId << "\t"
<< parms.cur.iMyStartingCustomerId << endl;
logmsg << left << setw(40) << "Partition Customer Count:" << parms.dft.iMyCustomerCount << "\t"
<< parms.cur.iMyCustomerCount << endl;
logmsg << left << setw(40) << "Partition Percent:" << parms.dft.iPartitionPercent << "\t"
<< parms.cur.iPartitionPercent << "\t" << (parms.state.iPartitionPercent ? "YES" : "NO") << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CDriverMEESettings &parms) {
// Construct Log String
logmsg.str(emptyString);
logmsg << "Driver MEE Settings:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Value" << endl;
logmsg << left << setw(40) << "Unique ID:" << parms.cur.UniqueId << endl;
logmsg << left << setw(40) << "Ticker Tape RNGSeed:" << parms.cur.TickerTapeRNGSeed << endl;
logmsg << left << setw(40) << "Trading Floor RNGSeed:" << parms.cur.TradingFloorRNGSeed << endl;
// Send String to Logger
return (logmsg.str());
}
string CLogFormatTab::GetLogOutput(CDriverDMSettings &parms) {
// Construct Log String
logmsg.str(emptyString);
logmsg << "Driver DM Settings:" << endl;
logmsg << left << setw(40) << "Parameter"
<< "Value" << endl;
logmsg << left << setw(40) << "Unique ID:" << parms.cur.UniqueId << endl;
logmsg << left << setw(40) << "RNGSeed:" << parms.cur.RNGSeed << endl;
// Send String to Logger
return (logmsg.str());
}

View File

@@ -0,0 +1,323 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Christopher Chan-Nui
*/
/*
* - 0.3 - Tue Oct 3 23:39:48 CDT 2006
* Extracted BucketSimulator class
* Extracted string parsing and format functions
* Re-vamped to use new threading
*
* - 0.2 - Mon Sep 11 09:06:35 CDT 2006
* Incorporated Matthew Emmerton's suggestions:
* Fixed calculation of simorders (was off by 60)
* Base GlobalLock on CSyncLock
*
* - 0.1 - Fri Sep 8 14:26:00 CDT 2006
* Initial release
*/
#include "utilities/threading.h"
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include "main/EGenLoader_stdafx.h"
#include "utilities/DateTime.h"
#include "main/progressmeter.h"
#include "main/bucketsimulator.h"
#include "main/strutil.h"
using TPCE::int64totimestr;
using TPCE::strtodbl;
using TPCE::strtoint64;
using TPCE::timestrtoint64;
using TPCE::CCustomerSelection;
using TPCE::CRandom;
using TPCE::eCustomerTier;
using TPCE::iDefaultLoadUnitSize;
using TPCE::RNGSEED;
using std::cout;
using std::endl;
// Helper class to contain the run configuration options
class BucketSimOptions {
public:
int verbose;
int helplevel;
RNGSEED base_seed;
TIdent cust_count;
double tpse;
bool use_stddev;
double stddev;
INT64 run_length;
UINT sim_count;
UINT sim_first;
UINT num_threads;
UINT interval_time;
// Calculate the number orders for this simulation
INT64 calc_simorders() {
return static_cast<INT64>(tpse * static_cast<double>(run_length));
}
BucketSimOptions()
: verbose(0), helplevel(0), base_seed(TPCE::RNGSeedBaseTxnInputGenerator), cust_count(0), tpse(10),
use_stddev(false), stddev(0), run_length(7200), sim_count(10000), sim_first(0), num_threads(1),
interval_time(10) {
}
};
// Usage message
void usage(const char *progname, BucketSimOptions &options, bool usage_error = true) {
cout << "Usage: " << progname << " [options] stddev custcount [TPS-E] [runtime]" << endl
<< " -h This help message (-hh for more options)" << endl
<< " -v Increase verbosity" << endl
<< " -c num Number of customers to simulate (" << options.cust_count << ")" << endl
<< " -r runtime Runtime to simulate (" << options.run_length << ")" << endl
<< " -e tpsE tpsE to simulate (" << options.tpse << ")" << endl
<< " -s stddev Standard Deviation to check against (none)" << endl
<< " -t threads Number of threads to use (" << options.num_threads << ")" << endl;
if (options.helplevel > 1) {
cout << " -S seed Base Seed for random number generation (" << options.base_seed << ")" << endl
<< " -n num Number of simulations to perform (" << options.sim_count << ")" << endl
<< " -i num Initial simulation number to start with (" << options.sim_first << ")" << endl
<< " -u num Progress report interval (" << options.interval_time << ")" << endl;
}
exit(usage_error ? ERROR_BAD_OPTION : 0);
}
// Parse command line, put discovered values into the options parameter
void parseCommandLine(int argc, const char *argv[], BucketSimOptions &options) {
char flag = '-';
try {
bool tpse_set = false;
options.tpse = 0;
int argnum;
for (argnum = 1; argnum < argc; ++argnum) {
const char *ptr = argv[argnum];
if (*ptr++ != '-') {
break;
}
while (*ptr) {
flag = *ptr++;
// Prefetch an "argument" for the option in case it is needed
// later
bool use_arg = true;
int arg_advance = 0;
const char *arg = ptr;
// If the argument is not bundled with the options' switch we
// use the next argument.
if (*ptr == '\0') {
arg_advance = 1;
arg = argv[argnum + 1];
if (arg == NULL) {
// If there wasn't an argument pretend it was just an
// empty string
arg = "";
}
}
switch (flag) {
case 'v':
use_arg = false;
options.verbose += 1;
break;
case '?':
case 'h':
use_arg = false;
options.helplevel += 1;
break;
case 'S':
options.base_seed = (RNGSEED)strtoint64(arg);
break;
case 'c':
options.cust_count = strtoint64(arg);
break;
case 'n':
options.sim_count = static_cast<UINT>(strtoint64(arg));
break;
case 'i':
options.sim_first = static_cast<UINT>(strtoint64(arg));
break;
case 'r':
options.run_length = timestrtoint64(arg);
break;
case 'e':
tpse_set = true;
options.tpse = strtodbl(arg);
break;
case 't':
options.num_threads = static_cast<UINT>(strtoint64(arg));
break;
case 's':
options.use_stddev = true;
options.stddev = strtodbl(arg);
break;
case 'u':
options.interval_time = static_cast<UINT>(timestrtoint64(arg));
options.verbose += 1;
break;
default:
std::ostringstream strm;
throw std::runtime_error(std::string("Unknown option"));
}
// If we used an argument we need to consume it
if (use_arg) {
argnum += arg_advance;
break;
}
}
}
// After all the switches are processed we consume the rest of the
// command line as positional options
if (argnum < argc) {
options.use_stddev = true;
options.stddev = strtodbl(argv[argnum++]);
}
if (argnum < argc) {
flag = 'c';
options.cust_count = strtoint64(argv[argnum++]);
}
if (argnum < argc) {
flag = 't';
tpse_set = true;
options.tpse = strtodbl(argv[argnum++]);
}
if (argnum < argc) {
flag = 'r';
options.run_length = static_cast<UINT>(timestrtoint64(argv[argnum++]));
}
if (argnum < argc) {
cout << "Too many command line arguments!" << endl;
usage(argv[0], options);
}
if (!tpse_set) {
options.tpse = options.cust_count / 500.0; // 500 is scale factor
}
// If no customers were specified that probably means the user
// didn't know how to invoke us.
if (options.helplevel || options.cust_count == 0 || !options.use_stddev) {
usage(argv[0], options, false);
}
} catch (std::exception &e) {
cout << "Error parsing command line option '" << flag << "': " << e.what() << endl;
usage(argv[0], options);
exit(ERROR_BAD_OPTION);
}
}
int main(int argc, const char *argv[]) {
try {
TPCE::CDateTime start_time;
BucketSimOptions options;
std::vector<TPCE::Thread<TPCE::BucketSimulator> *> threads;
// Output EGen version
TPCE::PrintEGenVersion();
parseCommandLine(argc, argv, options);
TPCE::BucketProgress progress(options.stddev, options.sim_count, options.verbose);
progress.set_display_interval(options.interval_time);
// Start up simulation threads
unsigned int sim_idx = 0;
unsigned int sims_per_thread = options.sim_count / options.num_threads + 1;
while (sim_idx < options.sim_count) {
// Last thread only processes however many are left over
if (sims_per_thread > options.sim_count - sim_idx) {
sims_per_thread = options.sim_count - sim_idx;
}
TPCE::Thread<TPCE::BucketSimulator> *thr =
new TPCE::Thread<TPCE::BucketSimulator>(std::unique_ptr<TPCE::BucketSimulator>(
new TPCE::BucketSimulator(options.sim_first + sim_idx, sims_per_thread, options.cust_count,
options.calc_simorders(), options.base_seed, progress)));
;
thr->start();
threads.push_back(thr);
sim_idx += sims_per_thread;
}
// Wait for all threads and find maximum standard deviation
while (!threads.empty()) {
TPCE::Thread<TPCE::BucketSimulator> *thr = threads.back();
threads.pop_back();
thr->stop();
delete thr;
}
TPCE::CDateTime now;
cout << "Maximum Standard Deviation = " << progress.max_stddev() << endl;
cout << "Requested Standard Deviation = " << options.stddev << endl;
cout << "Customer Count = " << options.cust_count << endl;
cout << "Iteration Count = " << options.sim_count << endl;
cout << "Iteration Start = " << options.sim_first << endl;
cout << "Iterations Completed = " << progress.current() << endl;
cout << "Base Seed = " << options.base_seed << endl;
cout << "Simulation Duration = " << options.run_length << endl;
cout << "tpsE = " << options.tpse << endl;
cout << "Simulation Duration = " << int64totimestr(now.DiffInMilliSeconds(start_time) / 1000) << endl;
cout << "Simulation completed at = " << now.ToStr(11) << endl;
cout << endl;
// Test against supplied standard deviation
if (progress.max_stddev() < options.stddev) {
cout << "Failed!" << endl;
exit(4); // Need a constant for this
} else {
cout << "Passed!" << endl;
}
// Successful run, exit nicely
return 0;
} catch (std::exception &e) {
cout << "Caught exception: " << e.what() << endl;
} catch (...) {
cout << "Caught unknown exception" << endl;
}
// Failed run make sure we exit with an error
exit(1);
}

View File

@@ -0,0 +1,80 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/ExchangeTable.h"
#include <cstring>
#include "utilities/MiscConsts.h"
using namespace TPCE;
void CExchangeTable::ComputeNumSecurities(TIdent iCustomerCount) {
// There are 685 securities per Load Unit. The flat_in/Security.txt contains
// 10 LUs worth of securities. This array is a pre-computation of the
// cumulative number of securities each excahnge has in the first 10 LUs.
const int iSecurityCounts[4][11] = {{0, 153, 307, 491, 688, 859, 1028, 1203, 1360, 1532, 1704},
{0, 173, 344, 498, 658, 848, 1006, 1191, 1402, 1572, 1749},
{0, 189, 360, 534, 714, 875, 1023, 1174, 1342, 1507, 1666},
{0, 170, 359, 532, 680, 843, 1053, 1227, 1376, 1554, 1731}};
INT32 numLU = static_cast<INT32>(iCustomerCount / 1000);
INT32 numLU_Tens = numLU / 10;
INT32 numLU_Ones = numLU % 10;
for (int i = 0; i < 4; i++) {
securityCount[i] = iSecurityCounts[i][10] * numLU_Tens + iSecurityCounts[i][numLU_Ones];
}
}
CExchangeTable::CExchangeTable(const ExchangeDataFile_t &dataFile, TIdent configuredCustomers)
: FixedTable<ExchangeDataFile_t, EXCHANGE_ROW>(dataFile) {
ComputeNumSecurities(configuredCustomers);
}
CExchangeTable::~CExchangeTable() {
}
void CExchangeTable::LoadTableRow() {
const ExchangeDataFileRecord &dataRecord(df[recordIdx]);
tableRow.EX_AD_ID = dataRecord.EX_AD_ID() + iTIdentShift;
tableRow.EX_CLOSE = dataRecord.EX_CLOSE();
strncpy(tableRow.EX_DESC, dataRecord.EX_DESC_CSTR(), sizeof(tableRow.EX_DESC));
strncpy(tableRow.EX_ID, dataRecord.EX_ID_CSTR(), sizeof(tableRow.EX_ID));
strncpy(tableRow.EX_NAME, dataRecord.EX_NAME_CSTR(), sizeof(tableRow.EX_NAME));
tableRow.EX_NUM_SYMB = securityCount[recordIdx];
tableRow.EX_OPEN = dataRecord.EX_OPEN();
}

View File

@@ -0,0 +1,76 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/FlatFileLoad_stdafx.h"
#include "main/TableTypes.h"
using namespace TPCE;
namespace TPCE {
// Explicit Instantiation to generate code
// template class CFlatFileLoader<ACCOUNT_PERMISSION_ROW>;
// template class CFlatFileLoader<ADDRESS_ROW>;
// template class CFlatFileLoader<BROKER_ROW>;
// template class CFlatFileLoader<CASH_TRANSACTION_ROW>;
// template class CFlatFileLoader<ChargeTableRecord_t>;
// template class CFlatFileLoader<CommissionRateTableRecord_t>;
// template class CFlatFileLoader<COMPANY_ROW>;
// template class CFlatFileLoader<COMPANY_COMPETITOR_ROW>;
// template class CFlatFileLoader<CUSTOMER_ROW>;
// template class CFlatFileLoader<CUSTOMER_ACCOUNT_ROW>;
// template class CFlatFileLoader<CUSTOMER_TAXRATE_ROW>;
// template class CFlatFileLoader<DAILY_MARKET_ROW>;
// template class CFlatFileLoader<FINANCIAL_ROW>;
// template class CFlatFileLoader<HOLDING_ROW>;
// template class CFlatFileLoader<HOLDING_HISTORY_ROW>;
// template class CFlatFileLoader<HOLDING_SUMMARY_ROW>;
// template class CFlatFileLoader<IndustryTableRecord_t>;
// template class CFlatFileLoader<LAST_TRADE_ROW>;
// template class CFlatFileLoader<NEWS_ITEM_ROW>;
// template class CFlatFileLoader<NEWS_XREF_ROW>;
// template class CFlatFileLoader<SectorTableRecord_t>;
// template class CFlatFileLoader<SECURITY_ROW>;
// template class CFlatFileLoader<SETTLEMENT_ROW>;
// template class CFlatFileLoader<StatusTypeTableRecord_t>;
// template class CFlatFileLoader<TaxRateTableRecord_t>;
// template class CFlatFileLoader<TRADE_ROW>;
// template class CFlatFileLoader<TRADE_HISTORY_ROW>;
// template class CFlatFileLoader<TRADE_REQUEST_ROW>;
// template class CFlatFileLoader<TradeTypeTableRecord_t>;
// template class CFlatFileLoader<WATCH_ITEM_ROW>;
// template class CFlatFileLoader<WATCH_LIST_ROW>;
} // namespace TPCE

View File

@@ -0,0 +1,56 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/IndustryTable.h"
#include <cstring>
using namespace TPCE;
CIndustryTable::CIndustryTable(const IndustryDataFile_t &dataFile)
: FixedTable<IndustryDataFile_t, INDUSTRY_ROW>(dataFile) {
}
CIndustryTable::~CIndustryTable() {
}
void CIndustryTable::LoadTableRow() {
const IndustryDataFileRecord &dataRecord(df[recordIdx]);
strncpy(tableRow.IN_ID, dataRecord.IN_ID_CSTR(), sizeof(tableRow.IN_ID));
strncpy(tableRow.IN_NAME, dataRecord.IN_NAME_CSTR(), sizeof(tableRow.IN_NAME));
strncpy(tableRow.IN_SC_ID, dataRecord.IN_SC_ID_CSTR(), sizeof(tableRow.IN_SC_ID));
}

View File

@@ -0,0 +1,181 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson, Matt Emmerton
*/
/******************************************************************************
* Description: Implementation of the MEE class.
* See MEE.h for a description.
******************************************************************************/
#include "main/MEE.h"
using namespace TPCE;
// Automatically generate unique RNG seeds.
// The CRandom class uses an unsigned 64-bit value for the seed.
// This routine automatically generates two unique seeds. One is used for
// the TxnInput generator RNG, and the other is for the TxnMixGenerator RNG.
// The 64 bits are used as follows.
//
// Bits 0 - 31 Caller provided unique unsigned 32-bit id.
// Bit 32 0 for TxnInputGenerator, 1 for TxnMixGenerator
// Bits 33 - 43 Number of days since the base time. The base time
// is set to be January 1 of the most recent year that is
// a multiple of 5. This allows enough space for the last
// field, and it makes the algorithm "timeless" by resetting
// the generated values every 5 years.
// Bits 44 - 63 Current time of day measured in 1/10's of a second.
//
void CMEE::AutoSetRNGSeeds(UINT32 UniqueId) {
CDateTime Now;
INT32 BaseYear;
INT32 Tmp1, Tmp2;
Now.GetYMD(&BaseYear, &Tmp1, &Tmp2);
// Set the base year to be the most recent year that was a multiple of 5.
BaseYear -= (BaseYear % 5);
CDateTime Base(BaseYear, 1, 1); // January 1st in the BaseYear
// Initialize the seed with the current time of day measured in 1/10's of a
// second. This will use up to 20 bits.
RNGSEED Seed;
Seed = Now.MSec() / 100;
// Now add in the number of days since the base time.
// The number of days in the 5 year period requires 11 bits.
// So shift up by that much to make room in the "lower" bits.
Seed <<= 11;
Seed += (RNGSEED)((INT64)Now.DayNo() - (INT64)Base.DayNo());
// So far, we've used up 31 bits.
// Save the "last" bit of the "upper" 32 for the RNG id.
// In addition, make room for the caller's 32-bit unique id.
// So shift a total of 33 bits.
Seed <<= 33;
// Now the "upper" 32-bits have been set with a value for RNG 0.
// Add in the sponsor's unique id for the "lower" 32-bits.
Seed += UniqueId;
// Set the Ticker Tape RNG to the unique seed.
m_TickerTape.SetRNGSeed(Seed);
m_DriverMEESettings.cur.TickerTapeRNGSeed = Seed;
// Set the RNG Id to 1 for the Trading Floor.
Seed |= UINT64_CONST(0x0000000100000000);
m_TradingFloor.SetRNGSeed(Seed);
m_DriverMEESettings.cur.TradingFloorRNGSeed = Seed;
}
// Constructor - automatic RNG seed generation
CMEE::CMEE(INT32 TradingTimeSoFar, CMEESUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm,
UINT32 UniqueId)
: m_DriverMEESettings(UniqueId, 0, 0, 0), m_pSUT(pSUT), m_pLogger(pLogger),
m_PriceBoard(TradingTimeSoFar, &m_BaseTime, &m_CurrentTime, dfm),
m_TickerTape(pSUT, &m_PriceBoard, &m_BaseTime, &m_CurrentTime, dfm),
m_TradingFloor(pSUT, &m_PriceBoard, &m_TickerTape, &m_BaseTime, &m_CurrentTime), m_MEELock() {
m_pLogger->SendToLogger("MEE object constructed using c'tor 1 (valid for publication: YES).");
AutoSetRNGSeeds(UniqueId);
m_pLogger->SendToLogger(m_DriverMEESettings);
}
// Constructor - RNG seed provided
CMEE::CMEE(INT32 TradingTimeSoFar, CMEESUTInterface *pSUT, CBaseLogger *pLogger, const DataFileManager &dfm,
UINT32 UniqueId, RNGSEED TickerTapeRNGSeed, RNGSEED TradingFloorRNGSeed)
: m_DriverMEESettings(UniqueId, 0, TickerTapeRNGSeed, TradingFloorRNGSeed), m_pSUT(pSUT), m_pLogger(pLogger),
m_PriceBoard(TradingTimeSoFar, &m_BaseTime, &m_CurrentTime, dfm),
m_TickerTape(pSUT, &m_PriceBoard, &m_BaseTime, &m_CurrentTime, TickerTapeRNGSeed, dfm),
m_TradingFloor(pSUT, &m_PriceBoard, &m_TickerTape, &m_BaseTime, &m_CurrentTime, TradingFloorRNGSeed),
m_MEELock() {
m_pLogger->SendToLogger("MEE object constructed using c'tor 2 (valid for publication: NO).");
m_pLogger->SendToLogger(m_DriverMEESettings);
}
CMEE::~CMEE(void) {
m_pLogger->SendToLogger("MEE object destroyed.");
}
RNGSEED CMEE::GetTickerTapeRNGSeed(void) {
return (m_TickerTape.GetRNGSeed());
}
RNGSEED CMEE::GetTradingFloorRNGSeed(void) {
return (m_TradingFloor.GetRNGSeed());
}
void CMEE::SetBaseTime(void) {
m_MEELock.lock();
m_BaseTime.Set();
m_MEELock.unlock();
}
bool CMEE::DisableTickerTape(void) {
bool Result;
m_MEELock.lock();
Result = m_TickerTape.DisableTicker();
m_MEELock.unlock();
return (Result);
}
bool CMEE::EnableTickerTape(void) {
bool Result;
m_MEELock.lock();
Result = m_TickerTape.EnableTicker();
m_MEELock.unlock();
return (Result);
}
INT32 CMEE::GenerateTradeResult(void) {
INT32 NextTime;
m_MEELock.lock();
m_CurrentTime.Set();
NextTime = m_TradingFloor.GenerateTradeResult();
m_MEELock.unlock();
return (NextTime);
}
INT32 CMEE::SubmitTradeRequest(PTradeRequest pTradeRequest) {
INT32 NextTime;
m_MEELock.lock();
m_CurrentTime.Set();
NextTime = m_TradingFloor.SubmitTradeRequest(pTradeRequest);
m_MEELock.unlock();
return (NextTime);
}

View File

@@ -0,0 +1,112 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
/******************************************************************************
* Description: Implemenation of the MEEPriceBoard class.
* See MEEPriceBoad.h for a description.
******************************************************************************/
#include "main/MEEPriceBoard.h"
using namespace TPCE;
CMEEPriceBoard::CMEEPriceBoard(INT32 TradingTimeSoFar, CDateTime *pBaseTime, CDateTime *pCurrentTime,
const DataFileManager &dfm)
: m_fMeanInTheMoneySubmissionDelay(1.0), m_Security(), m_SecurityFile(dfm.SecurityFile()),
m_iNumberOfSecurities(0) {
// Number of securities is based on "active" customers, as per sub-committee
// decision to have a scaled-down database look as much as possible as the
// smaller database.
// Note that this decision will ensure that some percentage of Trade-Order
// transactions will *not* be subject to lock contention when accessing the
// LAST_TRADE table, since they are "outside" of the active range that is
// updated by the MEE via the Market-Feed transaction. This may provide an
// incentive for sponsors to over-build and under-scale at run-time, to the
// detriment of the benchmark. If this is the case, then we should require
// the MEE to run using "configured" securities.
m_iNumberOfSecurities = m_SecurityFile.GetActiveSecurityCount();
m_Security.Init(TradingTimeSoFar, pBaseTime, pCurrentTime, m_fMeanInTheMoneySubmissionDelay);
m_SecurityFile.LoadSymbolToIdMap();
}
CMEEPriceBoard::~CMEEPriceBoard(void) {
}
void CMEEPriceBoard::GetSymbol(TIdent SecurityIndex,
char *szOutput, // output buffer
size_t iOutputLen) // size of the output buffer (including null));
{
return (m_SecurityFile.CreateSymbol(SecurityIndex, szOutput, iOutputLen));
}
CMoney CMEEPriceBoard::GetMinPrice() {
return (m_Security.GetMinPrice());
}
CMoney CMEEPriceBoard::GetMaxPrice() {
return (m_Security.GetMaxPrice());
}
CMoney CMEEPriceBoard::GetCurrentPrice(TIdent SecurityIndex) {
return (m_Security.GetCurrentPrice(SecurityIndex));
}
CMoney CMEEPriceBoard::GetCurrentPrice(char *pSecuritySymbol) {
return (m_Security.GetCurrentPrice(m_SecurityFile.GetIndex(pSecuritySymbol)));
}
CMoney CMEEPriceBoard::CalculatePrice(char *pSecuritySymbol, double fTime) {
return (m_Security.CalculatePrice(m_SecurityFile.GetIndex(pSecuritySymbol), fTime));
}
double CMEEPriceBoard::GetSubmissionTime(char *pSecuritySymbol, double fPendingTime, CMoney fLimitPrice,
eTradeTypeID TradeType) {
return (
m_Security.GetSubmissionTime(m_SecurityFile.GetIndex(pSecuritySymbol), fPendingTime, fLimitPrice, TradeType));
}
double CMEEPriceBoard::GetSubmissionTime(TIdent SecurityIndex, double fPendingTime, CMoney fLimitPrice,
eTradeTypeID TradeType) {
return (m_Security.GetSubmissionTime(SecurityIndex, fPendingTime, fLimitPrice, TradeType));
}
double CMEEPriceBoard::GetCompletionTime(TIdent SecurityIndex, double fSubmissionTime,
CMoney *pCompletionPrice // output parameter
) {
return (m_Security.GetCompletionTime(SecurityIndex, fSubmissionTime, pCompletionPrice));
}

View File

@@ -0,0 +1,351 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy, Doug Johnson
*/
/******************************************************************************
* Description: Implementation of the MEESecurity class.
* See MEESecurity.h for a description.
******************************************************************************/
#include <cmath>
#include "main/MEESecurity.h"
using namespace TPCE;
// Period of security price change (in seconds)
// e.g. when the price will repeat.
//
const int iSecPricePeriod = 900; // 15 minutes
// Mean delay between Submission and Completion times
//
const double fMeanCompletionTimeDelay = 1.0;
// Delay added to the clipped MEE Completion delay
// to simulate SUT-to-MEE and MEE-to-SUT processing delays.
//
const double fCompletionSUTDelay = 1.0; // seconds
/*
* Constructor.
* Initializes the class using RNG and constants.
*
* PARAMETERS:
* none.
*
* RETURNS:
* not applicable.
*/
CMEESecurity::CMEESecurity()
: m_rnd(RNGSeedBaseMEESecurity), m_fRangeLow(fMinSecPrice), m_fRangeHigh(fMaxSecPrice),
m_fRange(fMaxSecPrice - fMinSecPrice), m_iPeriod(iSecPricePeriod), m_TradingTimeSoFar(0), m_pBaseTime(NULL),
m_pCurrentTime(NULL) {
}
/*
* Initialize before the first use.
* Separated from constructor in order to have default (no-parameters)
* constructor.
*
* PARAMETERS:
* IN Index - unique security index to
* generate a unique starting price IN TradeTimeSoFar - point
* where we last left off on the price curve IN pBaseTime - wall clock time
* corresponding to the initial time for all securities IN pCurrentTime -
* current time for the security (determines current price) IN
* fMeanInTheMoneySubmissionDelay - Mean delay between Pending and Submission
* times for an immediatelly triggered (in-the-money) limit order.
*
* RETURNS:
* none
*/
void CMEESecurity::Init(INT32 TradingTimeSoFar, // for picking up where we last
// left off on the price curve
CDateTime *pBaseTime, CDateTime *pCurrentTime,
// Mean delay between Pending and Submission times
// for an immediatelly triggered (in-the-money) limit
// order.
//
// The actual delay is randomly calculated in the range
// [0.5 * Mean .. 1.5 * Mean]
//
double fMeanInTheMoneySubmissionDelay) {
m_TradingTimeSoFar = TradingTimeSoFar;
m_pBaseTime = pBaseTime;
m_pCurrentTime = pCurrentTime;
m_fMeanInTheMoneySubmissionDelay = fMeanInTheMoneySubmissionDelay;
// Reset the RNG seed so that loading in multiple EGenLoader instances
// results in the same database as running just one EGenLoader.
//
m_rnd.SetSeed(RNGSeedBaseMEESecurity);
}
/*
* Calculate the "unique" starting offset
* in the price curve based on the security ID (0-based)
* 0 corresponds to m_fRangeLow price,
* m_fPeriod/2 corresponds to m_fRangeHigh price,
* m_fPeriod corresponds again to m_fRangeLow price
*
* PARAMETERS:
* IN SecurityIndex - unique security index to generate a unique
* starting price
*
* RETURNS:
* time from which to calculate initial price
*/
inline double CMEESecurity::InitialTime(TIdent SecurityIndex) {
INT32 MsPerPeriod = iSecPricePeriod * MsPerSecond;
TIdent SecurityFactor = SecurityIndex * 556237 + 253791;
TIdent TradingFactor = (TIdent)m_TradingTimeSoFar * MsPerSecond; // Cast to avoid truncation
return (((TradingFactor + SecurityFactor) % MsPerPeriod) / MsPerSecondDivisor);
}
/*
* Negative exponential distribution.
*
* PARAMETERS:
* IN fMean - mean value of the distribution
*
* RETURNS:
* random value according to the negative
* exponential distribution with the given mean.
*/
inline double CMEESecurity::NegExp(double fMean) {
return RoundToNearestNsec(m_rnd.RndDoubleNegExp(fMean));
}
/*
* Calculate current price for the security identified by its index (0-based).
*
* PARAMETERS:
* IN SecurityIndex - unique identifier for the security.
*
* RETURNS:
* price at this point in time given with integer number of cents.
*/
CMoney CMEESecurity::GetCurrentPrice(TIdent SecurityIndex) {
return (CalculatePrice(SecurityIndex, *m_pCurrentTime - *m_pBaseTime));
}
/*
* Return minimum price on the price curve for any security.
*
* PARAMETERS:
* none.
*
* RETURNS:
* minimum price given with integer number of cents.
*/
CMoney CMEESecurity::GetMinPrice(void) {
return (m_fRangeLow);
}
/*
* Return maximum price on the price curve for any security.
*
* PARAMETERS:
* none.
*
* RETURNS:
* maximum price given with integer number of cents.
*/
CMoney CMEESecurity::GetMaxPrice(void) {
return (m_fRangeHigh);
}
/*
* Calculate price at a certain point in time.
*
* PARAMETERS:
* IN SecurityIndex - unique security index to generate a unique
* starting price IN fTime - seconds from initial time
*
* RETURNS:
* price according to the triangular function
* that will be achived at the given time
*/
CMoney CMEESecurity::CalculatePrice(TIdent SecurityIndex, double fTime) {
double fPeriodTime = (fTime + InitialTime(SecurityIndex)) / (double)m_iPeriod;
double fTimeWithinPeriod = (fPeriodTime - (int)fPeriodTime) * (double)m_iPeriod;
double fPricePosition; // 0..1 corresponding to m_fRangeLow..m_fRangeHigh
CMoney PriceCents;
if (fTimeWithinPeriod < m_iPeriod / 2) {
fPricePosition = fTimeWithinPeriod / (m_iPeriod / 2);
} else {
fPricePosition = (m_iPeriod - fTimeWithinPeriod) / (m_iPeriod / 2);
}
PriceCents = m_fRangeLow + m_fRange * fPricePosition;
return PriceCents;
}
/*
* Calculate time required to move between certain prices
* with certain initial direction of price change.
*
* PARAMETERS:
* IN fStartPrice - price at the start of the time interval
* IN fEndPrice - price at the end of the time interval
* IN iStartDirection - direction (up or down) on the price curve at
* the start of the time interval
*
* RETURNS:
* seconds required to move from the start price to the end price
*/
double CMEESecurity::CalculateTime(CMoney fStartPrice, CMoney fEndPrice, int iStartDirection) {
int iHalfPeriod = m_iPeriod / 2;
// Distance on the price curve from StartPrice to EndPrice (in dollars)
//
CMoney fDistance;
// Amount of time (in seconds) needed to move $1 on the price curve.
// In half a period the price moves over the entire price range.
//
double fSpeed = iHalfPeriod / m_fRange.DollarAmount();
if (fEndPrice > fStartPrice) {
if (iStartDirection > 0) {
fDistance = fEndPrice - fStartPrice;
} else {
fDistance = (fStartPrice - m_fRangeLow) + (fEndPrice - m_fRangeLow);
}
} else {
if (iStartDirection > 0) {
fDistance = (m_fRangeHigh - fStartPrice) + (m_fRangeHigh - fEndPrice);
} else {
fDistance = fStartPrice - fEndPrice;
}
}
return fDistance.DollarAmount() * fSpeed;
}
/*
* Calculate triggering time for limit orders.
*
* PARAMETERS:
* IN SecurityIndex - unique security index to generate a unique
* starting price IN fPendingTime - pending time of the order, in seconds
* from time 0 IN fLimitPrice - limit price of the order IN TradeType -
* order trade type
*
* RETURNS:
* the expected submission time
*/
double CMEESecurity::GetSubmissionTime(TIdent SecurityIndex,
double fPendingTime, // in seconds from time 0
CMoney fLimitPrice, eTradeTypeID TradeType) {
CMoney fPriceAtPendingTime = CalculatePrice(SecurityIndex, fPendingTime);
int iDirectionAtPendingTime;
double fSubmissionTimeFromPending; // Submission - Pending time difference
// Check if the order is already in the money
// e.g. if the current price is less than the buy price
// or the current price is more than the sell price.
//
if (((TradeType == eLimitBuy || TradeType == eStopLoss) && fPriceAtPendingTime <= fLimitPrice) ||
((TradeType == eLimitSell) && fPriceAtPendingTime >= fLimitPrice)) {
// Order is in-the-money. Trigger immediatelly.
//
fSubmissionTimeFromPending = m_rnd.RndDoubleIncrRange(0.5 * m_fMeanInTheMoneySubmissionDelay,
1.5 * m_fMeanInTheMoneySubmissionDelay, 0.001);
} else {
if ((int)(fPendingTime + InitialTime(SecurityIndex)) % m_iPeriod < m_iPeriod / 2) {
// In the first half of the period => price is going up
//
iDirectionAtPendingTime = 1;
} else {
// In the second half of the period => price is going down
//
iDirectionAtPendingTime = -1;
}
fSubmissionTimeFromPending = CalculateTime(fPriceAtPendingTime, fLimitPrice, iDirectionAtPendingTime);
}
return fPendingTime + fSubmissionTimeFromPending;
}
/*
* Return the expected completion time and the completion price.
* Completion time is between 0 and 5 seconds
* with 1 sec mean.
*
* Used to calculate completion time for
* both limit (first must get submission time)
* and market orders.
*
* Equivalent of MEE function sequence
* 'receive trade' then 'complete the trade request'.
*
* PARAMETERS:
* IN SecurityIndex - unique security index to generate a
* unique starting price IN fSubmissionTime - time when the order was
* submitted, in seconds from time 0 OUT pCompletionPrice - completion price
* of the order
*
* RETURNS:
* the approximated completion time for the trade
*
*/
double CMEESecurity::GetCompletionTime(TIdent SecurityIndex,
double fSubmissionTime, // in seconds from time 0
CMoney *pCompletionPrice // out
) {
double fCompletionDelay = NegExp(fMeanCompletionTimeDelay);
// Clip at 5 seconds to prevent rare, but really long delays
//
if (fCompletionDelay > 5.0) {
fCompletionDelay = 5.0;
}
if (pCompletionPrice != NULL) {
*pCompletionPrice = CalculatePrice(SecurityIndex, fSubmissionTime + fCompletionDelay);
}
return fSubmissionTime + fCompletionDelay + fCompletionSUTDelay;
}

View File

@@ -0,0 +1,251 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
/******************************************************************************
* Description: Implementation of the MEETickerTape class.
* See MEETickerTape.h for a description.
******************************************************************************/
#include "main/MEETickerTape.h"
#include "main/StatusTypeIDs.h"
using namespace TPCE;
const int CMEETickerTape::LIMIT_TRIGGER_TRADE_QTY = 375;
const int CMEETickerTape::RANDOM_TRADE_QTY_1 = 325;
const int CMEETickerTape::RANDOM_TRADE_QTY_2 = 425;
RNGSEED CMEETickerTape::GetRNGSeed(void) {
return (m_rnd.GetSeed());
}
void CMEETickerTape::SetRNGSeed(RNGSEED RNGSeed) {
m_rnd.SetSeed(RNGSeed);
}
void CMEETickerTape::Initialize(void) {
// Set up status and trade types for Market-Feed input
//
// Submitted
strncpy(m_TxnInput.StatusAndTradeType.status_submitted, m_StatusType[eSubmitted].ST_ID_CSTR(),
sizeof(m_TxnInput.StatusAndTradeType.status_submitted));
// Limit-Buy
strncpy(m_TxnInput.StatusAndTradeType.type_limit_buy, m_TradeType[eLimitBuy].TT_ID_CSTR(),
sizeof(m_TxnInput.StatusAndTradeType.type_limit_buy));
// Limit-Sell
strncpy(m_TxnInput.StatusAndTradeType.type_limit_sell, m_TradeType[eLimitSell].TT_ID_CSTR(),
sizeof(m_TxnInput.StatusAndTradeType.type_limit_sell));
// Stop-Loss
strncpy(m_TxnInput.StatusAndTradeType.type_stop_loss, m_TradeType[eStopLoss].TT_ID_CSTR(),
sizeof(m_TxnInput.StatusAndTradeType.type_stop_loss));
}
// Constructor - use default RNG seed
CMEETickerTape::CMEETickerTape(CMEESUTInterface *pSUT, CMEEPriceBoard *pPriceBoard, CDateTime *pBaseTime,
CDateTime *pCurrentTime, const DataFileManager &dfm)
: m_pSUT(pSUT), m_pPriceBoard(pPriceBoard), m_BatchIndex(0), m_BatchDuplicates(0), m_rnd(RNGSeedBaseMEETickerTape),
m_Enabled(true), m_pBaseTime(pBaseTime), m_pCurrentTime(pCurrentTime), m_StatusType(dfm.StatusTypeDataFile()),
m_TradeType(dfm.TradeTypeDataFile()) {
Initialize();
}
// Constructor - RNG seed provided
CMEETickerTape::CMEETickerTape(CMEESUTInterface *pSUT, CMEEPriceBoard *pPriceBoard, CDateTime *pBaseTime,
CDateTime *pCurrentTime, RNGSEED RNGSeed, const DataFileManager &dfm)
: m_pSUT(pSUT), m_pPriceBoard(pPriceBoard), m_BatchIndex(0), m_BatchDuplicates(0), m_rnd(RNGSeed), m_Enabled(true),
m_pBaseTime(pBaseTime), m_pCurrentTime(pCurrentTime), m_StatusType(dfm.StatusTypeDataFile()),
m_TradeType(dfm.TradeTypeDataFile()) {
Initialize();
}
CMEETickerTape::~CMEETickerTape(void) {
}
bool CMEETickerTape::DisableTicker(void) {
m_Enabled = false;
return (!m_Enabled);
}
bool CMEETickerTape::EnableTicker(void) {
m_Enabled = true;
return (m_Enabled);
}
void CMEETickerTape::AddEntry(PTickerEntry pTickerEntry) {
if (m_Enabled) {
AddToBatch(pTickerEntry);
AddArtificialEntries();
}
}
void CMEETickerTape::PostLimitOrder(PTradeRequest pTradeRequest) {
eTradeTypeID eTradeType;
double CurrentPrice = -1.0;
PTickerEntry pNewEntry = new TTickerEntry;
eTradeType = ConvertTradeTypeIdToEnum(pTradeRequest->trade_type_id);
pNewEntry->price_quote = pTradeRequest->price_quote;
strncpy(pNewEntry->symbol, pTradeRequest->symbol, sizeof(pNewEntry->symbol));
pNewEntry->trade_qty = LIMIT_TRIGGER_TRADE_QTY;
CurrentPrice = m_pPriceBoard->GetCurrentPrice(pTradeRequest->symbol).DollarAmount();
if (((eTradeType == eLimitBuy || eTradeType == eStopLoss) && CurrentPrice <= pTradeRequest->price_quote) ||
((eTradeType == eLimitSell) && CurrentPrice >= pTradeRequest->price_quote)) {
// Limit Order is in-the-money.
pNewEntry->price_quote = CurrentPrice;
// Make sure everything is up to date.
m_LimitOrderTimers.ProcessExpiredTimers();
// Now post the incoming entry.
m_InTheMoneyLimitOrderQ.push(pNewEntry);
} else {
// Limit Order is not in-the-money.
pNewEntry->price_quote = pTradeRequest->price_quote;
double TriggerTimeDelay;
double fCurrentTime = *m_pCurrentTime - *m_pBaseTime;
// GetSubmissionTime returns a value relative to time 0, so we
// need to substract off the value for the current time to get
// the delay time relative to now.
TriggerTimeDelay =
m_pPriceBoard->GetSubmissionTime(pNewEntry->symbol, fCurrentTime, pNewEntry->price_quote, eTradeType) -
fCurrentTime;
m_LimitOrderTimers.StartTimer(TriggerTimeDelay, this, &CMEETickerTape::AddLimitTrigger, pNewEntry);
}
}
void CMEETickerTape::AddLimitTrigger(PTickerEntry pTickerEntry) {
m_InTheMoneyLimitOrderQ.push(pTickerEntry);
}
void CMEETickerTape::AddArtificialEntries(void) {
TIdent SecurityIndex;
TTickerEntry TickerEntry;
int TotalEntryCount = 0;
static const int PaddingLimit =
(max_feed_len / 10) - 1; // NOTE: 10 here represents the ratio of TR to MF transactions
static const int PaddingLimitForAll = PaddingLimit; // MAX (trigger+artificial) entries
static const int PaddingLimitForTriggers = PaddingLimit; // MAX (triggered) entries
while (TotalEntryCount < PaddingLimitForTriggers && !m_InTheMoneyLimitOrderQ.empty()) {
PTickerEntry pEntry = m_InTheMoneyLimitOrderQ.front();
AddToBatch(pEntry);
delete pEntry;
m_InTheMoneyLimitOrderQ.pop();
TotalEntryCount++;
}
while (TotalEntryCount < PaddingLimitForAll) {
TickerEntry.trade_qty = (m_rnd.RndPercent(50)) ? RANDOM_TRADE_QTY_1 : RANDOM_TRADE_QTY_2;
SecurityIndex = m_rnd.RndInt64Range(0, m_pPriceBoard->m_iNumberOfSecurities - 1);
TickerEntry.price_quote = (m_pPriceBoard->GetCurrentPrice(SecurityIndex)).DollarAmount();
m_pPriceBoard->GetSymbol(SecurityIndex, TickerEntry.symbol, static_cast<INT32>(sizeof(TickerEntry.symbol)));
AddToBatch(&TickerEntry);
TotalEntryCount++;
}
}
void CMEETickerTape::AddToBatch(PTickerEntry pTickerEntry) {
// Check to see if this symbol already exists in the batch
for (int i = 0; i < m_BatchIndex; i++) {
if (strncmp(pTickerEntry->symbol, m_TxnInput.Entries[i].symbol, cSYMBOL_len) == 0) {
m_BatchDuplicates++;
break;
}
}
// Add the ticker to the batch
m_TxnInput.Entries[m_BatchIndex++] = *pTickerEntry;
// Buffer is full, time for Market-Feed.
if (max_feed_len == m_BatchIndex) {
m_TxnInput.unique_symbols = (max_feed_len - m_BatchDuplicates);
m_pSUT->MarketFeed(&m_TxnInput);
m_BatchIndex = 0;
m_BatchDuplicates = 0;
}
}
eTradeTypeID CMEETickerTape::ConvertTradeTypeIdToEnum(char *pTradeType) {
// Convert character trade type to enumeration
switch (pTradeType[0]) {
case 'T':
switch (pTradeType[1]) {
case 'L':
switch (pTradeType[2]) {
case 'B':
return (eLimitBuy);
case 'S':
return (eLimitSell);
default:
break;
}
break;
case 'M':
switch (pTradeType[2]) {
case 'B':
return (eMarketBuy);
case 'S':
return (eMarketSell);
default:
break;
}
break;
case 'S':
switch (pTradeType[2]) {
case 'L':
return (eStopLoss);
default:
break;
}
break;
default:
break;
}
break;
default:
break;
}
// Throw exception - should never get here
assert(false); // this should never happen
return eMarketBuy; // silence compiler warning about not all control paths
// returning a value
}

View File

@@ -0,0 +1,155 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
/******************************************************************************
* Description: Implemenation of the MEETradingFloor class.
* See MEETradingFloor.h for a description.
******************************************************************************/
#include "main/MEETradingFloor.h"
using namespace TPCE;
RNGSEED CMEETradingFloor::GetRNGSeed(void) {
return (m_rnd.GetSeed());
}
void CMEETradingFloor::SetRNGSeed(RNGSEED RNGSeed) {
m_rnd.SetSeed(RNGSeed);
}
// Constructor - use default RNG seed
CMEETradingFloor::CMEETradingFloor(CMEESUTInterface *pSUT, CMEEPriceBoard *pPriceBoard, CMEETickerTape *pTickerTape,
CDateTime *pBaseTime, CDateTime *pCurrentTime)
: m_pSUT(pSUT), m_pPriceBoard(pPriceBoard), m_pTickerTape(pTickerTape), m_pBaseTime(pBaseTime),
m_pCurrentTime(pCurrentTime), m_rnd(RNGSeedBaseMEETradingFloor), m_OrderProcessingDelayMean(1.0) {
}
// Constructor - RNG seed provided
CMEETradingFloor::CMEETradingFloor(CMEESUTInterface *pSUT, CMEEPriceBoard *pPriceBoard, CMEETickerTape *pTickerTape,
CDateTime *pBaseTime, CDateTime *pCurrentTime, RNGSEED RNGSeed)
: m_pSUT(pSUT), m_pPriceBoard(pPriceBoard), m_pTickerTape(pTickerTape), m_pBaseTime(pBaseTime),
m_pCurrentTime(pCurrentTime), m_rnd(RNGSeed), m_OrderProcessingDelayMean(1.0) {
}
CMEETradingFloor::~CMEETradingFloor(void) {
}
inline double CMEETradingFloor::GenProcessingDelay(double Mean) {
double Result = RoundToNearestNsec(m_rnd.RndDoubleNegExp(Mean));
if (Result > m_MaxOrderProcessingDelay) {
return (m_MaxOrderProcessingDelay);
} else {
return (Result);
}
}
INT32 CMEETradingFloor::SubmitTradeRequest(PTradeRequest pTradeRequest) {
switch (pTradeRequest->eAction) {
case eMEEProcessOrder: { // Use {...} to keep compiler from complaining that
// other cases/default skip initialization of
// pNewOrder.
// This is either a market order or a limit order that has been
// triggered, so it gets traded right away. Make a copy in storage under
// our control.
PTradeRequest pNewOrder = new TTradeRequest;
*pNewOrder = *pTradeRequest;
return (m_OrderTimers.StartTimer(GenProcessingDelay(m_OrderProcessingDelayMean), this,
&CMEETradingFloor::SendTradeResult, pNewOrder));
} // Use {...} to keep compiler from complaining that other cases/default
// skip initialization of pNewOrder.
case eMEESetLimitOrderTrigger:
// This is a limit order
m_pTickerTape->PostLimitOrder(pTradeRequest);
return (m_OrderTimers.ProcessExpiredTimers());
default:
// Throw and exception - SHOULD NEVER GET HERE!
return (m_OrderTimers.ProcessExpiredTimers());
}
}
INT32 CMEETradingFloor::GenerateTradeResult(void) {
return (m_OrderTimers.ProcessExpiredTimers());
}
void CMEETradingFloor::SendTradeResult(PTradeRequest pTradeRequest) {
eTradeTypeID eTradeType;
TTradeResultTxnInput TxnInput;
TTickerEntry TickerEntry;
double CurrentPrice = -1.0;
eTradeType = m_pTickerTape->ConvertTradeTypeIdToEnum(pTradeRequest->trade_type_id);
CurrentPrice = m_pPriceBoard->GetCurrentPrice(pTradeRequest->symbol).DollarAmount();
// Populate Trade-Result inputs, and send to SUT
TxnInput.trade_id = pTradeRequest->trade_id;
// Make sure the Trade-Result has the right price based on the type of
// trade.
if ((eTradeType == eLimitBuy && pTradeRequest->price_quote < CurrentPrice) ||
(eTradeType == eLimitSell && pTradeRequest->price_quote > CurrentPrice)) {
TxnInput.trade_price = pTradeRequest->price_quote;
} else {
TxnInput.trade_price = CurrentPrice;
}
m_pSUT->TradeResult(&TxnInput);
// Populate Ticker Entry information
strncpy(TickerEntry.symbol, pTradeRequest->symbol, sizeof(TickerEntry.symbol));
TickerEntry.trade_qty = pTradeRequest->trade_qty;
// Note that the Trade-Result sent out above does not always use
// the current price. We're about to "lie" by setting the ticker entry
// price to the current price regardless of how the Trade-Result
// price was actually set. We do this to preserve the continuity
// of the price curve. This is important because the ticker prices
// are used by transactions to make decisions. It is possible for
// the Trade-Result price to be out of sync with the price curve,
// and putting this price into the ticker stream will alter the
// behavior of other transactions. If you're having a guilt-attack
// about this lie (or are just plain curious), comment out the
// assignment using CurrentPrice and uncomment the assignment
// using TxnInput.trade_price.
//
TickerEntry.price_quote = CurrentPrice;
// TickerEntry.price_quote = TxnInput.trade_price;
m_pTickerTape->AddEntry(&TickerEntry);
delete pTradeRequest;
}

View File

@@ -0,0 +1,200 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Sergey Vasilevskiy
* - Doug Johnson
*/
#include "main/EGenTables_stdafx.h"
using namespace TPCE;
// Percentages used in determining gender.
const int iPercentGenderIsMale = 49;
/*
* Initializes in-memory representation of names files.
*/
CPerson::CPerson(const DataFileManager &dfm, TIdent iStartFromCustomer, bool bCacheEnabled)
: m_LastNames(dfm.LastNameDataFile()), m_MaleFirstNames(dfm.MaleFirstNameDataFile()),
m_FemaleFirstNames(dfm.FemaleFirstNameDataFile()), m_bCacheEnabled(bCacheEnabled), m_iCacheSize(0),
m_iCacheOffset(0), INVALID_NAME_CACHE_ENTRY(-1), INVALID_GENDER_CACHE_ENTRY('X') {
if (m_bCacheEnabled) {
m_iCacheSize = iDefaultLoadUnitSize;
m_iCacheOffset = iTIdentShift + iStartFromCustomer;
m_FirstNameCache = new int[m_iCacheSize];
m_LastNameCache = new int[m_iCacheSize];
m_GenderCache = new char[m_iCacheSize];
for (int i = 0; i < m_iCacheSize; i++) {
m_FirstNameCache[i] = INVALID_NAME_CACHE_ENTRY;
m_LastNameCache[i] = INVALID_NAME_CACHE_ENTRY;
m_GenderCache[i] = INVALID_GENDER_CACHE_ENTRY;
}
}
}
/*
* Deallocate in-memory representation of names files.
*/
CPerson::~CPerson() {
if (m_bCacheEnabled) {
delete[] m_FirstNameCache;
delete[] m_LastNameCache;
delete[] m_GenderCache;
}
}
/*
* Resets the cache.
*/
void CPerson::InitNextLoadUnit(TIdent iCacheOffsetIncrement) {
if (m_bCacheEnabled) {
m_iCacheOffset += iCacheOffsetIncrement;
for (int i = 0; i < m_iCacheSize; i++) {
m_FirstNameCache[i] = INVALID_NAME_CACHE_ENTRY;
m_LastNameCache[i] = INVALID_NAME_CACHE_ENTRY;
m_GenderCache[i] = INVALID_GENDER_CACHE_ENTRY;
}
}
}
/*
* Returns the last name for a particular customer id.
* It'll always be the same for the same customer id.
*/
const string &CPerson::GetLastName(TIdent CID) {
return getName<LastNameDataFile_t>(CID, m_LastNames, m_LastNameCache, RNGSeedBaseLastName);
}
/*
* Returns the first name for a particular customer id.
* Determines gender first.
*/
const string &CPerson::GetFirstName(TIdent CID) {
if (IsMaleGender(CID)) {
return getName<MaleFirstNameDataFile_t>(CID, m_MaleFirstNames, m_FirstNameCache, RNGSeedBaseFirstName);
} else {
return getName<FemaleFirstNameDataFile_t>(CID, m_FemaleFirstNames, m_FirstNameCache, RNGSeedBaseFirstName);
}
}
/*
* Returns the middle name.
*/
char CPerson::GetMiddleName(TIdent CID) {
RNGSEED OldSeed;
char cMiddleInitial[2];
OldSeed = m_rnd.GetSeed();
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseMiddleInitial, (RNGSEED)CID));
cMiddleInitial[1] = '\0';
m_rnd.RndAlphaNumFormatted(cMiddleInitial, "a");
m_rnd.SetSeed(OldSeed);
return (cMiddleInitial[0]);
}
/*
* Returns the gender character for a particular customer id.
*/
char CPerson::GetGender(TIdent CID) {
RNGSEED OldSeed;
char cGender;
// It is possible (and expected) to get CID values that are oustide the
// current load unit. For example, AccountPermission CIDs and Broker IDs
// can be outside the current load unit. These "out of bounds" CIDs are not
// cached so we need to account for this.
TIdent index = CID - m_iCacheOffset;
bool bCheckCache = (index >= 0 && index < m_iCacheSize);
// Use the cache if we can.
if (m_bCacheEnabled && bCheckCache && (INVALID_GENDER_CACHE_ENTRY != m_GenderCache[index])) {
return m_GenderCache[index];
}
// We couldn't use the cache.
OldSeed = m_rnd.GetSeed();
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseGender, (RNGSEED)CID));
// Find out gender
if (m_rnd.RndPercent(iPercentGenderIsMale)) {
cGender = 'M';
} else {
cGender = 'F';
}
// Cache the result if appropriate.
if (m_bCacheEnabled && bCheckCache) {
m_GenderCache[index] = cGender;
}
// Restore the RNG
m_rnd.SetSeed(OldSeed);
return (cGender);
}
/*
* Returns TRUE is a customer id is male
*/
bool CPerson::IsMaleGender(TIdent CID) {
return GetGender(CID) == 'M';
}
/*
* Generate tax id
*/
void CPerson::GetTaxID(TIdent CID, char *buf) {
RNGSEED OldSeed;
OldSeed = m_rnd.GetSeed();
// NOTE: the call to RndAlphaNumFormatted "consumes" an RNG value
// for EACH character in the format string. Therefore, to avoid getting
// tax ID's that overlap N-1 out of N characters, multiply the offset into
// the sequence by N to get a unique range of values.
m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedBaseTaxID, ((RNGSEED)CID * TaxIDFmt_len)));
m_rnd.RndAlphaNumFormatted(buf, TaxIDFmt);
m_rnd.SetSeed(OldSeed);
}
/*
* Get first name, last name, and tax id.
*/
void CPerson::GetFirstLastAndTaxID(TIdent C_ID, char *szFirstName, char *szLastName, char *szTaxID) {
// Fill in the last name
strncpy(szLastName, GetLastName(C_ID).c_str(), cL_NAME_len);
// Fill in the first name
strncpy(szFirstName, GetFirstName(C_ID).c_str(), cF_NAME_len);
// Fill in the tax id
GetTaxID(C_ID, szTaxID);
}

View File

@@ -0,0 +1,54 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/SectorTable.h"
#include <cstring>
using namespace TPCE;
CSectorTable::CSectorTable(const SectorDataFile_t &dataFile) : FixedTable<SectorDataFile_t, SECTOR_ROW>(dataFile) {
}
CSectorTable::~CSectorTable() {
}
void CSectorTable::LoadTableRow() {
const SectorDataFileRecord &dataRecord(df[recordIdx]);
strncpy(tableRow.SC_ID, dataRecord.SC_ID_CSTR(), sizeof(tableRow.SC_ID));
strncpy(tableRow.SC_NAME, dataRecord.SC_NAME_CSTR(), sizeof(tableRow.SC_NAME));
}

View File

@@ -0,0 +1,55 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/StatusTypeTable.h"
#include <cstring>
using namespace TPCE;
CStatusTypeTable::CStatusTypeTable(const StatusTypeDataFile_t &dataFile)
: FixedTable<StatusTypeDataFile_t, STATUS_TYPE_ROW>(dataFile) {
}
CStatusTypeTable::~CStatusTypeTable() {
}
void CStatusTypeTable::LoadTableRow() {
const StatusTypeDataFileRecord &dataRecord(df[recordIdx]);
strncpy(tableRow.ST_ID, dataRecord.ST_ID_CSTR(), sizeof(tableRow.ST_ID));
strncpy(tableRow.ST_NAME, dataRecord.ST_NAME_CSTR(), sizeof(tableRow.ST_NAME));
}

View File

@@ -0,0 +1,55 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/TaxRateTable.h"
#include <cstring>
using namespace TPCE;
TaxRateTable::TaxRateTable(const CTaxRateFile &dataFile) : FixedTable<CTaxRateFile, TAX_RATE_ROW>(dataFile) {
}
TaxRateTable::~TaxRateTable() {
}
void TaxRateTable::LoadTableRow() {
const ITaxRateFileRecord &dataRecord(df[recordIdx]);
strncpy(tableRow.TX_ID, dataRecord.TX_ID_CSTR(), sizeof(tableRow.TX_ID));
strncpy(tableRow.TX_NAME, dataRecord.TX_NAME_CSTR(), sizeof(tableRow.TX_NAME));
tableRow.TX_RATE = dataRecord.TX_RATE();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include "main/TradeTypeTable.h"
#include <cstring>
using namespace TPCE;
CTradeTypeTable::CTradeTypeTable(const TradeTypeDataFile_t &dataFile)
: FixedTable<TradeTypeDataFile_t, TRADE_TYPE_ROW>(dataFile) {
}
CTradeTypeTable::~CTradeTypeTable() {
}
void CTradeTypeTable::LoadTableRow() {
const TradeTypeDataFileRecord &dataRecord(df[recordIdx]);
strncpy(tableRow.TT_ID, dataRecord.TT_ID_CSTR(), sizeof(tableRow.TT_ID));
tableRow.TT_IS_MRKT = dataRecord.TT_IS_MRKT();
tableRow.TT_IS_SELL = dataRecord.TT_IS_SELL();
strncpy(tableRow.TT_NAME, dataRecord.TT_NAME_CSTR(), sizeof(tableRow.TT_NAME));
}

View File

@@ -0,0 +1,129 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
/******************************************************************************
* Description: Implementation of the CWheelTime class.
* See WheelTime.h for a high level description.
******************************************************************************/
#include "main/WheelTime.h"
using namespace TPCE;
CWheelTime::CWheelTime(PWheelConfig pWheelConfig) : m_pWheelConfig(pWheelConfig), m_Cycles(0), m_Index(0) {
}
CWheelTime::CWheelTime(PWheelConfig pWheelConfig, INT32 cycles, INT32 index)
: m_pWheelConfig(pWheelConfig), m_Cycles(cycles), m_Index(index) {
}
CWheelTime::CWheelTime(PWheelConfig pWheelConfig, CDateTime &Base, CDateTime &Now, INT32 offset)
: m_pWheelConfig(pWheelConfig) {
Set(Base, Now);
Add(offset);
}
CWheelTime::~CWheelTime(void) {
}
void CWheelTime::Add(INT32 Interval) {
// DJ - should throw error if Interval >= m_pWheelConfig->WheelSize?
m_Cycles += Interval / m_pWheelConfig->WheelSize;
m_Index += Interval % m_pWheelConfig->WheelSize;
if (m_Index >= m_pWheelConfig->WheelSize) {
// Handle wrapping in the wheel - assume we don't allow multi-cycle
// intervals
m_Cycles++;
m_Index -= m_pWheelConfig->WheelSize;
}
}
INT32 CWheelTime::Offset(const CWheelTime &Time) {
INT32 Interval;
Interval = (m_Cycles - Time.m_Cycles) * m_pWheelConfig->WheelSize;
Interval += (m_Index - Time.m_Index);
return (Interval);
}
void CWheelTime::Set(INT32 cycles, INT32 index) {
m_Cycles = cycles;
m_Index = index; // DJ - should throw error if Index >= m_pWheelConfig->WheelSize
}
// Set is overloaded. This version is used by the timer wheel.
void CWheelTime::Set(CDateTime &Base, CDateTime &Now) {
INT32 offset; // offset from BaseTime in milliseconds
// DJ - If Now < Base, then we should probably throw an exception
offset = Now.DiffInMilliSeconds(Base) / m_pWheelConfig->WheelResolution; // convert based on wheel resolution
m_Cycles = offset / m_pWheelConfig->WheelSize;
m_Index = offset % m_pWheelConfig->WheelSize;
}
// Set is overloaded. This version is used by the event wheel.
void CWheelTime::Set(CDateTime *pBase, CDateTime *pNow) {
INT32 offset; // offset from BaseTime in milliseconds
// DJ - If Now < Base, then we should probably throw an exception
offset = pNow->DiffInMilliSeconds(pBase) / m_pWheelConfig->WheelResolution; // convert based on wheel resolution
m_Cycles = offset / m_pWheelConfig->WheelSize;
m_Index = offset % m_pWheelConfig->WheelSize;
}
bool CWheelTime::operator<(const CWheelTime &Time) {
return (m_Cycles == Time.m_Cycles) ? (m_Index < Time.m_Index) : (m_Cycles < Time.m_Cycles);
}
CWheelTime &CWheelTime::operator=(const CWheelTime &Time) {
m_pWheelConfig = Time.m_pWheelConfig;
m_Cycles = Time.m_Cycles;
m_Index = Time.m_Index;
return *this;
}
CWheelTime &CWheelTime::operator+=(const INT32 &Interval) {
Add(Interval);
return *this;
}
CWheelTime CWheelTime::operator++(INT32) {
Add(1);
return *this;
}

View File

@@ -0,0 +1,60 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Doug Johnson
*/
#include <cstring>
#include "main/ZipCodeTable.h"
using namespace TPCE;
CZipCodeTable::CZipCodeTable(const ZipCodeDataFile_t &dataFile)
: FixedTable<ZipCodeDataFile_t, ZIP_CODE_ROW>(dataFile) {
}
CZipCodeTable::~CZipCodeTable() {
}
unsigned int CZipCodeTable::MaxRecordIdx() const {
return df.size(df.UniqueRecordsOnly); // unique records only
}
void CZipCodeTable::LoadTableRow() {
const ZipCodeDataFileRecord &dataRecord(df.getUniqueRecord(recordIdx));
strncpy(tableRow.ZC_CODE, dataRecord.ZC_CODE_CSTR(), sizeof(tableRow.ZC_CODE));
strncpy(tableRow.ZC_DIV, dataRecord.ZC_DIV_CSTR(), sizeof(tableRow.ZC_DIV));
strncpy(tableRow.ZC_TOWN, dataRecord.ZC_TOWN_CSTR(), sizeof(tableRow.ZC_TOWN));
}

View File

@@ -0,0 +1,156 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Christopher Chan-Nui
* - Cecil Reames
*/
#include "utilities/threading.h"
#include "main/unusedflag.h"
#include <stdexcept>
#include <iomanip>
#include "main/bucketsimulator.h"
namespace TPCE {
BucketSimulator::BucketSimulator(int iterstart, int itercount, TIdent iCustomerCount, INT64 simorders,
TPCE::RNGSEED base_seed, BucketProgress &progress)
: m_rnd(), m_buckets(NULL), m_custcount(iCustomerCount), m_iterstart(iterstart), m_itercount(itercount),
m_baseseed(base_seed), m_simorders(simorders),
m_maxbucket(static_cast<int>(iCustomerCount / iDefaultLoadUnitSize)), m_progress(progress) {
if (iCustomerCount % iDefaultLoadUnitSize != 0) {
throw std::range_error("The customer count must be an integral "
"multiple of the load unit size!");
}
if (m_maxbucket < 2) {
throw std::range_error("Bucket simulator must have at least 2 buckets!");
}
m_buckets = new INT64[m_maxbucket];
}
BucketSimulator::~BucketSimulator() {
delete[] m_buckets;
}
// Calculate the standard deviation of the current bucket
// Use straightforward method rather than sum of squares...
double BucketSimulator::calc_stddev() {
double sum = 0;
for (int i = 0; i < m_maxbucket; ++i) {
sum += m_buckets[i];
}
double mean = sum / (double)m_maxbucket;
double sumdev2 = 0;
for (int i = 0; i < m_maxbucket; ++i) {
sumdev2 += (m_buckets[i] - mean) * (m_buckets[i] - mean);
}
double stddev = sqrt(sumdev2 / (double)(m_maxbucket - 1));
return stddev;
}
// Simulates one run and returns the standard deviation of the buckets
// iterations - Number of "orders" to simulate (note that we don't take into
// account the 1% rollbacks)
double BucketSimulator::simulate_onerun(INT64 iorders) {
int bucket;
memset(m_buckets, 0, sizeof(m_buckets[0]) * m_maxbucket);
for (INT64 i = 0; i < iorders; ++i) {
bucket = m_rnd.RndIntRange(0, static_cast<int>((m_custcount - 1) / static_cast<TIdent>(iDefaultLoadUnitSize)));
m_buckets[bucket] += 1;
}
return calc_stddev();
}
// Perform all of the simulations this instance was constructed with and return
// the maximum standard deviation
double BucketSimulator::simulate() {
double max_stddev = 0;
TPCE::RNGSEED seed = m_rnd.RndNthElement(m_baseseed, (RNGSEED)(m_iterstart * m_simorders * RND_STEP_PER_ORDER));
m_rnd.SetSeed(seed);
for (int i = 0; i < m_itercount; ++i) {
TPCE::RNGSEED current_seed = m_rnd.GetSeed();
double stddev = simulate_onerun(m_simorders);
std::ostringstream strm;
strm << "StdDev for run " << i + m_iterstart << " is " << std::setprecision(3) << std::fixed << stddev
<< ", seed was " << current_seed;
m_progress.message(strm.str(), 1);
if (max_stddev < stddev) {
max_stddev = stddev;
}
if (!m_progress.report(stddev)) {
break;
}
}
return max_stddev;
}
// Entry point to be run as a thread
void BucketSimulator::run(void *thread UNUSED) {
simulate();
}
//////////////////////////////////////////////////////////////////////////////
BucketProgress::BucketProgress(double acceptable_stddev, int total_in, int verbosity, std::ostream *output)
: ProgressMeter(total_in, verbosity, output), acceptable_stddev_(acceptable_stddev), max_stddev_(0) {
}
void BucketProgress::display_message(std::ostream &out) const {
ProgressMeter::display_message(out);
out << " stddev=" << max_stddev_;
}
bool BucketProgress::report(double stddev) {
inc();
TPCE::Locker<ProgressMeter> locker(*this);
if (max_stddev_ < stddev) {
max_stddev_ = stddev;
}
return (max_stddev_ < acceptable_stddev_);
}
double BucketProgress::max_stddev() {
TPCE::Locker<ProgressMeter> locker(*this);
return max_stddev_;
}
} // namespace TPCE

View File

@@ -0,0 +1,136 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Christopher Chan-Nui
*/
#include "utilities/threading.h"
#include <iostream>
#include "main/progressmeter.h"
#include "main/strutil.h"
namespace TPCE {
// total - The total number of tasks to complete before the job is done.
ProgressMeter::ProgressMeter(int total_in, int verbosity, std::ostream *output)
: m_total(total_in), m_current(0), m_display_interval(10), m_start_time(), m_last_time(m_start_time),
m_output(output), m_verbosity(verbosity), m_mutex() {
}
// val - minimum number of seconds between automatic display updates
// set to -1 to disable automatic displays
void ProgressMeter::set_display_interval(int val) {
TPCE::Locker<ProgressMeter> locker(*this);
m_display_interval = val;
}
int ProgressMeter::display_interval() const {
TPCE::Locker<const ProgressMeter> locker(*this);
return m_display_interval;
}
// Displays the current progress and an estimated time to finish
void ProgressMeter::display() const {
TPCE::Locker<const ProgressMeter> locker(*this);
display_message(*m_output);
(*m_output) << std::endl;
}
// Displays a progress message to the specified output stream
// Lock progress meter before calling this function!
//
// output - output stream to display progress to
void ProgressMeter::display_message(std::ostream &out) const {
CDateTime now;
INT32 elapsed_in_ms = now.DiffInMilliSeconds(m_start_time);
double rate = static_cast<double>(elapsed_in_ms) / static_cast<double>(m_current) / 1000.0;
out << m_current << "/" << m_total << " (" << m_current * 100 / m_total << "%)"
<< " [Remain: " << int64totimestr((int)(rate * (double)(m_total - m_current))) << ", "
<< "Elapsed: " << int64totimestr(elapsed_in_ms / 1000) << "]";
}
// Notifies the progress meter that some tasks have been completed. If there
// hasn't been a display update within display_interval seconds then an update
// will be emitted to the output stream.
//
// count - number of tasks completed
// output - output stream to display progress to
void ProgressMeter::inc(int count) {
CDateTime now;
{
TPCE::Locker<ProgressMeter> locker(*this);
m_current += count;
if (m_verbosity <= 0 || m_display_interval < 0 ||
now.DiffInMilliSeconds(m_last_time) <= m_display_interval * 1000) {
return;
}
m_last_time.Set();
}
display();
}
// Return current count
int ProgressMeter::current() const {
TPCE::Locker<const ProgressMeter> locker(*this);
return m_current;
}
// Return total count
int ProgressMeter::total() const {
TPCE::Locker<const ProgressMeter> locker(*this);
return m_total;
}
// Display a message if the verbosity level is greater than message level
//
// mesg - message to display
// level - verbosity level to display at
void ProgressMeter::message(const std::string &mesg, int level) {
TPCE::Locker<ProgressMeter> locker(*this);
if (level >= m_verbosity) {
return;
}
(*m_output) << mesg << std::endl;
}
void ProgressMeter::lock() const {
m_mutex.lock();
}
void ProgressMeter::unlock() const {
m_mutex.unlock();
}
} // namespace TPCE

View File

@@ -0,0 +1,55 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Christopher Chan-Nui
*/
#include "main/progressmeterinterface.h"
#include "main/unusedflag.h"
namespace TPCE {
// Dummy implementation in case someone wants to have a null progress meter
ProgressMeterInterface::~ProgressMeterInterface() {
}
void ProgressMeterInterface::display() const {
}
void ProgressMeterInterface::inc(int count UNUSED) {
}
void ProgressMeterInterface::message(const std::string &mesg UNUSED, int level UNUSED) {
}
} // namespace TPCE

View File

@@ -0,0 +1,178 @@
/*
* Legal Notice
*
* This document and associated source code (the "Work") is a part of a
* benchmark specification maintained by the TPC.
*
* The TPC reserves all right, title, and interest to the Work as provided
* under U.S. and international laws, including without limitation all patent
* and trademark rights therein.
*
* No Warranty
*
* 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
* CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
* AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
* WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
* INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
* DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
* PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
* WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
* ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
* QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
* WITH REGARD TO THE WORK.
* 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
* ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
* COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
* OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
* INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
* OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
* RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
* ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
*
* Contributors
* - Christopher Chan-Nui
*/
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <cstdlib>
#include <cerrno>
#include <stdlib.h> // needed for strtoull which is not in the C++ headers
#include "utilities/EGenStandardTypes.h"
#ifdef WIN32
#define strtoull _strtoui64
#endif
using std::strtod;
using std::strtoul;
namespace TPCE {
// Converts an ASCII string into a 64 bit integer. Accepts a scaling factor of
// 'K', 'M', or 'G' on values.
// ptr - string to convert
// Returns the integral 64 bit representation
INT64 strtoint64(const char *ptr) {
INT64 val;
char *endp;
errno = 0;
val = strtoull(ptr, &endp, 0);
if (errno != 0) {
std::ostringstream strm;
strm << "Unable to parse integer '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
switch (*endp) {
case 'G':
val *= 1000 * 1000 * 1000;
break;
case 'M':
val *= 1000 * 1000;
break;
case 'K':
val *= 1000;
break;
case '\0':
endp--;
break;
default:
std::ostringstream strm;
strm << "Unable to parse invalid scale factor on integer '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
if (*++endp != '\0') {
std::ostringstream strm;
strm << "Unable to parse trailing characters on integer '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
return val;
}
// Converts an ASCII string into a double. Accepts a scaling factor of
// 'K', 'M', or 'G' on values.
// ptr - string to convert
// Returns the double representation
double strtodbl(const char *ptr) {
double val;
char *endp;
errno = 0;
val = strtod(ptr, &endp);
if (errno != 0) {
std::ostringstream strm;
strm << "Unable to parse floating point number '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
switch (*endp) {
case 'G':
val *= 1000.0 * 1000.0 * 1000.0;
break;
case 'M':
val *= 1000.0 * 1000.0;
break;
case 'K':
val *= 1000.0;
break;
case '\0':
endp--;
break;
default:
std::ostringstream strm;
strm << "Unable to parse invalid scale factor on floating point number '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
if (*++endp != '\0') {
std::ostringstream strm;
strm << "Unable to parse trailing characters on floating point number '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
return val;
}
// Converts an ASCII string in "HH:MM:SS" form into a INT64. HH: or HH:MM:
// may be omitted.
// ptr - string to convert
// Returns the 64 bit integer representation
INT64 timestrtoint64(const char *ptr) {
INT64 val;
char *endp;
errno = 0;
val = strtoul(ptr, &endp, 0);
if (*endp == ':') {
val = val * 60 + strtoul(endp + 1, &endp, 0);
if (*endp == ':') {
val = val * 60 + strtoul(endp + 1, &endp, 0);
}
}
if (errno != 0 || *endp != '\0') {
std::ostringstream strm;
strm << "Unable to parse time '" << ptr << "'" << std::endl;
throw std::runtime_error(strm.str());
}
return val;
}
// Converts a 64 bit integer into an HH:MM:SS string
// val - integer to convert
// Returns a string containing the formatted value.
std::string int64totimestr(INT64 val) {
std::ostringstream strm;
int sec = static_cast<int>(val % 60);
val /= 60;
int min = static_cast<int>(val % 60);
int hrs = static_cast<int>(val / 60);
strm << std::setfill('0');
if (hrs) {
strm << std::setw(2) << hrs << ":";
}
strm << std::setw(2) << min << ":" << std::setw(2) << sec;
return strm.str();
}
} // namespace TPCE