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 * - Sergey Vasilevskiy
35 * - Doug Johnson
36 */
37
38/*
39 * Class representing the Watch Lists table and Watch Items table.
40 */
41#ifndef WATCH_LIST_AND_ITEMS_TABLE_H
42#define WATCH_LIST_AND_ITEMS_TABLE_H
43
44#include "EGenTables_common.h"
45#include "CustomerTable.h"
46
47#include "input/DataFileManager.h"
48
49namespace TPCE {
50
51// Range of security ids indexes
52const UINT iMinSecIdx = 0; // this should always be 0
53
54// Min number of items in one watch list
55const UINT iMinItemsInWL = 50;
56
57// Max number of items in one watch list
58const UINT iMaxItemsInWL = 150;
59
60// Percentage of customers that have watch lists
61const UINT iPercentWatchList = 100;
62
63// Note: these parameters are dependent on the load unit size
64static const UINT iWatchListIdPrime = 631;
65static const UINT iWatchListIdOffset = 97;
66
67// Number of RNG calls to skip for one row in order
68// to not use any of the random values from the previous row.
69const UINT iRNGSkipOneRowWatchListAndWatchItem = 15; // real max count in v3.5: 13
70
71// Structure combining watch list row and watch items rows.
72typedef struct WATCH_LIST_AND_ITEM_ROW {
73 WATCH_LIST_ROW m_watch_list;
74 WATCH_ITEM_ROW m_watch_items[iMaxItemsInWL + 1];
75} * PWATCH_LIST_AND_ITEM_ROW;
76
77typedef set<TIdent> IntSet; // set of integers with 'less' comparison function
78
79class CWatchListsAndItemsTable : public TableTemplate<WATCH_LIST_AND_ITEM_ROW> {
80 UINT m_iRowsToGenForWL;
81 UINT m_iRowsGeneratedForWL;
82 CCustomerTable m_cust;
83 IntSet m_set; // needed to generate random unique security ids
84 UINT m_iWICount; //# of items for the last list
85 TIdent m_iMinSecIdx;
86 TIdent m_iMaxSecIdx;
87 const CSecurityFile &m_SecurityFile;
88 bool m_bInitNextLoadUnit;
89
90 /*
91 * Generate next Watch List ID
92 */
93 void GenerateNextWL_ID() {
94 TIdent iCustomerIdForCalc = m_cust.GetCurrentC_ID() - iDefaultStartFromCustomer;
95
96 m_row.m_watch_list.WL_ID =
97 (iCustomerIdForCalc / iDefaultLoadUnitSize) * iDefaultLoadUnitSize + // strip last 3 digits
98 (iCustomerIdForCalc * iWatchListIdPrime + iWatchListIdOffset) % iDefaultLoadUnitSize +
99 iDefaultStartFromCustomer;
100 }
101
102 /*
103 * Reset the state for the next load unit
104 */
105 void InitNextLoadUnit() {
106 m_rnd.SetSeed(m_rnd.RndNthElement(RNGSeedTableDefault,
107 (RNGSEED)m_cust.GetCurrentC_ID() * iRNGSkipOneRowWatchListAndWatchItem));
108
109 ClearRecord(); // this is needed for EGenTest to work
110 }
111
112public:
113 CWatchListsAndItemsTable(const DataFileManager &dfm, TIdent iCustomerCount, TIdent iStartFromCustomer)
114 : TableTemplate<WATCH_LIST_AND_ITEM_ROW>(), m_iRowsToGenForWL(0), m_iRowsGeneratedForWL(0),
115 m_cust(dfm, iCustomerCount, iStartFromCustomer), m_iWICount(0), m_iMinSecIdx(iMinSecIdx),
116 m_SecurityFile(dfm.SecurityFile()), m_bInitNextLoadUnit(false) {
117 m_iMaxSecIdx = m_SecurityFile.GetConfiguredSecurityCount() - 1; // -1 because security indexes are 0-based
118
119 // Initialize customer for the starting watch list id.
120 // Iterate through customers to find the next one with a watch list
121 do {
122 if (m_cust.GetCurrentC_ID() % iDefaultLoadUnitSize == 0) {
123 m_bInitNextLoadUnit = true; // delay calling InitNextLoadUnit until the start of
124 // the row generation
125 }
126
127 m_cust.GenerateNextC_ID();
128
129 } while (!m_rnd.RndPercent(iPercentWatchList) && m_cust.MoreRecords());
130 };
131
132 /*
133 * Generates all column values for the next row.
134 */
135 bool GenerateNextRecord() {
136 TIdent iCustomerId;
137 bool bRet = false;
138
139 if (m_bInitNextLoadUnit) {
140 InitNextLoadUnit();
141
142 m_bInitNextLoadUnit = false;
143 }
144
145 ++m_iLastRowNumber;
146
147 iCustomerId = m_cust.GetCurrentC_ID();
148
149 GenerateNextWL_ID();
150
151 // Fill the customer ID
152 m_row.m_watch_list.WL_C_ID = iCustomerId;
153
154 // Now generate Watch Items for this Watch List
155 m_iWICount = (UINT)m_rnd.RndIntRange(iMinItemsInWL,
156 iMaxItemsInWL); // number of items in the watch list
157 for (m_set.clear(); m_set.size() < m_iWICount;) {
158 // Generate random security id and insert into the set
159 TIdent iSecurityIndex = m_rnd.RndInt64Range(m_iMinSecIdx, m_iMaxSecIdx);
160 m_set.insert(iSecurityIndex);
161 }
162
163 int i;
164 IntSet::iterator pos;
165 // Now remove from the set and fill watch items rows
166 for (i = 0, pos = m_set.begin(); pos != m_set.end(); ++i, ++pos) {
167 m_row.m_watch_items[i].WI_WL_ID = m_row.m_watch_list.WL_ID; // same watch list id for all items
168 // get the next element from the set
169 m_SecurityFile.CreateSymbol(*pos, m_row.m_watch_items[i].WI_S_SYMB,
170 static_cast<int>(sizeof(m_row.m_watch_items[i].WI_S_SYMB)));
171 }
172
173 bRet = false; // initialize for the case of currently processing the
174 // last customer
175
176 // Iterate through customers to find the next one with a watch list
177 while (!bRet && m_cust.MoreRecords()) {
178 if (m_cust.GetCurrentC_ID() % iDefaultLoadUnitSize == 0) {
179 m_bInitNextLoadUnit = true; // delay calling InitNextLoadUnit until the start of
180 // the row generation
181 }
182
183 m_cust.GenerateNextC_ID();
184
185 bRet = m_rnd.RndPercent(iPercentWatchList);
186 }
187
188 // If the new customer has a watch list, bRet was set to true.
189 // If there are no more customers, bRet was initialized to false.
190 if (bRet) {
191 m_bMoreRecords = true;
192 } else {
193 m_bMoreRecords = false;
194 }
195
196 // Return false if all the rows have been generated
197 return (MoreRecords());
198 }
199
200 const WATCH_LIST_ROW &GetWLRow() {
201 return m_row.m_watch_list;
202 }
203 const WATCH_ITEM_ROW &GetWIRow(UINT i) {
204 if (i < m_iWICount)
205 return (m_row.m_watch_items[i]);
206 else
207 throw std::range_error("Watch Item row index out of bounds.");
208 }
209 UINT GetWICount() {
210 return m_iWICount;
211 }
212};
213
214} // namespace TPCE
215
216#endif // WATCH_LIST_AND_ITEMS_TABLE_H
217