1 | /* |
2 | * Legal Notice |
3 | * |
4 | * This document and associated source code (the "Work") is a part of a |
5 | * benchmark specification maintained by the TPC. |
6 | * |
7 | * The TPC reserves all right, title, and interest to the Work as provided |
8 | * under U.S. and international laws, including without limitation all patent |
9 | * and trademark rights therein. |
10 | * |
11 | * No Warranty |
12 | * |
13 | * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION |
14 | * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE |
15 | * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER |
16 | * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, |
17 | * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, |
18 | * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR |
19 | * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF |
20 | * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE. |
21 | * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, |
22 | * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT |
23 | * WITH REGARD TO THE WORK. |
24 | * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO |
25 | * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE |
26 | * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS |
27 | * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, |
28 | * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY, |
29 | * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT |
30 | * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD |
31 | * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. |
32 | * |
33 | * Contributors |
34 | * - Gregory Dake, Cecil Reames, Doug Johnson, Matt Emmerton |
35 | */ |
36 | |
37 | /****************************************************************************** |
38 | * Description: Implementation of CTxnGeneration class. |
39 | * See TxnMixGenerator.h for description. |
40 | ******************************************************************************/ |
41 | |
42 | #include "main/CETxnMixGenerator.h" |
43 | |
44 | using namespace TPCE; |
45 | |
46 | CCETxnMixGenerator::CCETxnMixGenerator(const PDriverCETxnSettings pDriverCETxnSettings, CBaseLogger *pLogger) |
47 | : m_pDriverCETxnSettings(pDriverCETxnSettings), m_rnd(RNGSeedBaseTxnMixGenerator) // initialize with default seed |
48 | , |
49 | m_pLogger(pLogger), m_iTxnArrayCurrentIndex(0), m_pTxnArray(NULL) { |
50 | // UpdateTunables() is called from CCE constructor (Initialize) |
51 | } |
52 | |
53 | CCETxnMixGenerator::CCETxnMixGenerator(const PDriverCETxnSettings pDriverCETxnSettings, RNGSEED RNGSeed, |
54 | CBaseLogger *pLogger) |
55 | : m_pDriverCETxnSettings(pDriverCETxnSettings), m_rnd(RNGSeed) // seed is provided for us |
56 | , |
57 | m_pLogger(pLogger), m_iTxnArrayCurrentIndex(0), m_pTxnArray(NULL) { |
58 | // UpdateTunables() is called from CCE constructor (Initialize) |
59 | } |
60 | |
61 | RNGSEED CCETxnMixGenerator::GetRNGSeed(void) { |
62 | return (m_rnd.GetSeed()); |
63 | } |
64 | |
65 | void CCETxnMixGenerator::SetRNGSeed(RNGSEED RNGSeed) { |
66 | m_rnd.SetSeed(RNGSeed); |
67 | } |
68 | |
69 | CCETxnMixGenerator::~CCETxnMixGenerator() { |
70 | if (m_pTxnArray != NULL) { |
71 | delete[] m_pTxnArray; |
72 | m_pTxnArray = NULL; |
73 | } |
74 | } |
75 | |
76 | void CCETxnMixGenerator::UpdateTunables(void) { |
77 | INT32 i; |
78 | INT32 BrokerVolumeMixLimit; |
79 | INT32 CustomerPositionMixLimit; |
80 | INT32 MarketWatchMixLimit; |
81 | INT32 SecurityDetailMixLimit; |
82 | INT32 TradeLookupMixLimit; |
83 | INT32 TradeOrderMixLimit; |
84 | INT32 TradeStatusMixLimit; |
85 | INT32 TradeUpdateMixLimit; |
86 | |
87 | // Add all the weights together |
88 | m_CETransactionMixTotal = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.BrokerVolumeMixLevel + |
89 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.CustomerPositionMixLevel + |
90 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.MarketWatchMixLevel + |
91 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.SecurityDetailMixLevel + |
92 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeLookupMixLevel + |
93 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeOrderMixLevel + |
94 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeStatusMixLevel + |
95 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeUpdateMixLevel; |
96 | |
97 | TradeStatusMixLimit = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeStatusMixLevel; |
98 | MarketWatchMixLimit = |
99 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.MarketWatchMixLevel + TradeStatusMixLimit; |
100 | SecurityDetailMixLimit = |
101 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.SecurityDetailMixLevel + MarketWatchMixLimit; |
102 | CustomerPositionMixLimit = |
103 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.CustomerPositionMixLevel + SecurityDetailMixLimit; |
104 | TradeOrderMixLimit = |
105 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeOrderMixLevel + CustomerPositionMixLimit; |
106 | TradeLookupMixLimit = m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeLookupMixLevel + TradeOrderMixLimit; |
107 | TradeUpdateMixLimit = |
108 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.TradeUpdateMixLevel + TradeLookupMixLimit; |
109 | BrokerVolumeMixLimit = |
110 | m_pDriverCETxnSettings->TxnMixGenerator_settings.cur.BrokerVolumeMixLevel + TradeUpdateMixLimit; |
111 | |
112 | // Reset the random transaction array. |
113 | // |
114 | if (m_pTxnArray != NULL) { |
115 | delete[] m_pTxnArray; |
116 | m_pTxnArray = NULL; |
117 | } |
118 | |
119 | m_pTxnArray = new char[m_CETransactionMixTotal]; |
120 | |
121 | // Initialize the array with transaction types. |
122 | // |
123 | for (i = 0; i < TradeStatusMixLimit; ++i) { |
124 | m_pTxnArray[i] = TRADE_STATUS; |
125 | } |
126 | for (; i < MarketWatchMixLimit; ++i) { |
127 | m_pTxnArray[i] = MARKET_WATCH; |
128 | } |
129 | for (; i < SecurityDetailMixLimit; ++i) { |
130 | m_pTxnArray[i] = SECURITY_DETAIL; |
131 | } |
132 | for (; i < CustomerPositionMixLimit; ++i) { |
133 | m_pTxnArray[i] = CUSTOMER_POSITION; |
134 | } |
135 | for (; i < TradeOrderMixLimit; ++i) { |
136 | m_pTxnArray[i] = TRADE_ORDER; |
137 | } |
138 | for (; i < TradeLookupMixLimit; ++i) { |
139 | m_pTxnArray[i] = TRADE_LOOKUP; |
140 | } |
141 | for (; i < TradeUpdateMixLimit; ++i) { |
142 | m_pTxnArray[i] = TRADE_UPDATE; |
143 | } |
144 | for (; i < BrokerVolumeMixLimit; ++i) { |
145 | m_pTxnArray[i] = BROKER_VOLUME; |
146 | } |
147 | |
148 | m_iTxnArrayCurrentIndex = 0; // reset the current element index |
149 | |
150 | // Log Tunables |
151 | m_pLogger->SendToLogger(m_pDriverCETxnSettings->TxnMixGenerator_settings); |
152 | } |
153 | |
154 | int CCETxnMixGenerator::GenerateNextTxnType() { |
155 | // Select the next transaction type using the "card deck shuffle" |
156 | // algorithm (also Knuth algorithm) that guarantees a certain number |
157 | // of transactions of each type is returned. |
158 | // |
159 | // 1) Get a 32-bit random number. |
160 | // 2) Use random number to select next transaction type from m_pTxnArray |
161 | // in the range [m_iTxnArrayCurrentIndex, m_CETransactionMixTotal). |
162 | // 3) Swap the selected random element in m_pTxnArray |
163 | // with m_pTxnArray[m_iTxnArrayCurrentIndex]. |
164 | // 4) Increment m_iTxnArrayCurrentIndex to remove the returned |
165 | // transaction type from further consideration. |
166 | // |
167 | INT32 rnd = m_rnd.RndIntRange(m_iTxnArrayCurrentIndex, m_CETransactionMixTotal - 1); |
168 | |
169 | char iTxnType = m_pTxnArray[rnd]; |
170 | |
171 | // Swap two array entries. |
172 | // |
173 | m_pTxnArray[rnd] = m_pTxnArray[m_iTxnArrayCurrentIndex]; |
174 | m_pTxnArray[m_iTxnArrayCurrentIndex] = iTxnType; |
175 | |
176 | m_iTxnArrayCurrentIndex = (m_iTxnArrayCurrentIndex + 1) % m_CETransactionMixTotal; |
177 | |
178 | return iTxnType; |
179 | } |
180 | |