1 | #include <stdio.h> |
2 | #include <string.h> |
3 | #ifndef VMS |
4 | #include <sys/types.h> |
5 | #endif |
6 | #if defined(SUN) |
7 | #include <unistd.h> |
8 | #endif |
9 | #include "dss.h" |
10 | #include "dsstypes.h" |
11 | |
12 | #include <math.h> |
13 | #ifdef ADHOC |
14 | #include "adhoc.h" |
15 | extern adhoc_t adhocs[]; |
16 | #endif /* ADHOC */ |
17 | #include "rng64.h" |
18 | |
19 | #define LEAP_ADJ(yr, mnth) ((LEAP(yr) && (mnth) >= 2) ? 1 : 0) |
20 | #define JDAY_BASE 8035 /* start from 1/1/70 a la unix */ |
21 | #define JMNTH_BASE (-70 * 12) /* start from 1/1/70 a la unix */ |
22 | #define JDAY(date) ((date)-STARTDATE + JDAY_BASE + 1) |
23 | #define PART_SUPP_BRIDGE(tgt, p, s) \ |
24 | { \ |
25 | DSS_HUGE tot_scnt = tdefs[SUPP].base * scale; \ |
26 | tgt = (p + s * (tot_scnt / SUPP_PER_PART + (long)((p - 1) / tot_scnt))) % tot_scnt + 1; \ |
27 | } |
28 | #define V_STR(avg, sd, tgt) a_rnd((int)(avg * V_STR_LOW), (int)(avg * V_STR_HGH), sd, tgt) |
29 | #define TEXT(avg, sd, tgt) dbg_text(tgt, (int)(avg * V_STR_LOW), (int)(avg * V_STR_HGH), sd) |
30 | static void gen_phone PROTO((DSS_HUGE ind, char *target, long seed)); |
31 | |
32 | DSS_HUGE |
33 | rpb_routine(DSS_HUGE p) { |
34 | DSS_HUGE price; |
35 | |
36 | price = 90000; |
37 | price += (p / 10) % 20001; /* limit contribution to $200 */ |
38 | price += (p % 1000) * 100; |
39 | |
40 | return (price); |
41 | } |
42 | |
43 | static void gen_phone(DSS_HUGE ind, char *target, long seed) { |
44 | DSS_HUGE acode, exchg, number; |
45 | |
46 | RANDOM(acode, 100, 999, seed); |
47 | RANDOM(exchg, 100, 999, seed); |
48 | RANDOM(number, 1000, 9999, seed); |
49 | |
50 | sprintf(target, "%02d" , (int)(10 + (ind % NATIONS_MAX))); |
51 | sprintf(target + 3, "%03d" , (int)acode); |
52 | sprintf(target + 7, "%03d" , (int)exchg); |
53 | sprintf(target + 11, "%04d" , (int)number); |
54 | target[2] = target[6] = target[10] = '-'; |
55 | |
56 | return; |
57 | } |
58 | |
59 | long mk_cust(DSS_HUGE n_cust, customer_t *c) { |
60 | DSS_HUGE i; |
61 | static int bInit = 0; |
62 | static char szFormat[100]; |
63 | |
64 | if (!bInit) { |
65 | sprintf(szFormat, C_NAME_FMT, 9, HUGE_FORMAT + 1); |
66 | bInit = 1; |
67 | } |
68 | c->custkey = n_cust; |
69 | sprintf(c->name, szFormat, C_NAME_TAG, n_cust); |
70 | V_STR(C_ADDR_LEN, C_ADDR_SD, c->address); |
71 | c->alen = (int)strlen(c->address); |
72 | RANDOM(i, 0, (nations.count - 1), C_NTRG_SD); |
73 | c->nation_code = i; |
74 | gen_phone(i, c->phone, (long)C_PHNE_SD); |
75 | RANDOM(c->acctbal, C_ABAL_MIN, C_ABAL_MAX, C_ABAL_SD); |
76 | pick_str(&c_mseg_set, C_MSEG_SD, c->mktsegment); |
77 | TEXT(C_CMNT_LEN, C_CMNT_SD, c->comment); |
78 | c->clen = (int)strlen(c->comment); |
79 | |
80 | return (0); |
81 | } |
82 | |
83 | /* |
84 | * generate the numbered order and its associated lineitems |
85 | */ |
86 | void mk_sparse(DSS_HUGE i, DSS_HUGE *ok, long seq) { |
87 | long low_bits; |
88 | |
89 | *ok = i; |
90 | low_bits = (long)(i & ((1 << SPARSE_KEEP) - 1)); |
91 | *ok = *ok >> SPARSE_KEEP; |
92 | *ok = *ok << SPARSE_BITS; |
93 | *ok += seq; |
94 | *ok = *ok << SPARSE_KEEP; |
95 | *ok += low_bits; |
96 | |
97 | return; |
98 | } |
99 | |
100 | long mk_order(DSS_HUGE index, order_t *o, long upd_num) { |
101 | DSS_HUGE lcnt; |
102 | DSS_HUGE rprice; |
103 | long ocnt; |
104 | DSS_HUGE tmp_date; |
105 | DSS_HUGE s_date; |
106 | DSS_HUGE r_date; |
107 | DSS_HUGE c_date; |
108 | DSS_HUGE clk_num; |
109 | DSS_HUGE supp_num; |
110 | static char **asc_date = NULL; |
111 | char tmp_str[2]; |
112 | char **mk_ascdate PROTO((void)); |
113 | int delta = 1; |
114 | static int bInit = 0; |
115 | static char szFormat[100]; |
116 | |
117 | if (!bInit) { |
118 | sprintf(szFormat, O_CLRK_FMT, 9, HUGE_FORMAT + 1); |
119 | bInit = 1; |
120 | } |
121 | if (asc_date == NULL) |
122 | asc_date = mk_ascdate(); |
123 | mk_sparse(index, &o->okey, (upd_num == 0) ? 0 : 1 + upd_num / (10000 / UPD_PCT)); |
124 | if (scale >= 30000) |
125 | RANDOM64(o->custkey, O_CKEY_MIN, O_CKEY_MAX, O_CKEY_SD); |
126 | else |
127 | RANDOM(o->custkey, O_CKEY_MIN, O_CKEY_MAX, O_CKEY_SD); |
128 | while (o->custkey % CUST_MORTALITY == 0) { |
129 | o->custkey += delta; |
130 | o->custkey = MIN(o->custkey, O_CKEY_MAX); |
131 | delta *= -1; |
132 | } |
133 | |
134 | RANDOM(tmp_date, O_ODATE_MIN, O_ODATE_MAX, O_ODATE_SD); |
135 | strcpy(o->odate, asc_date[tmp_date - STARTDATE]); |
136 | |
137 | pick_str(&o_priority_set, O_PRIO_SD, o->opriority); |
138 | RANDOM(clk_num, 1, MAX((scale * O_CLRK_SCL), O_CLRK_SCL), O_CLRK_SD); |
139 | sprintf(o->clerk, szFormat, O_CLRK_TAG, clk_num); |
140 | TEXT(O_CMNT_LEN, O_CMNT_SD, o->comment); |
141 | o->clen = (int)strlen(o->comment); |
142 | #ifdef DEBUG |
143 | if (o->clen > O_CMNT_MAX) |
144 | fprintf(stderr, "comment error: O%d\n" , index); |
145 | #endif /* DEBUG */ |
146 | o->spriority = 0; |
147 | |
148 | o->totalprice = 0; |
149 | o->orderstatus = 'O'; |
150 | ocnt = 0; |
151 | |
152 | RANDOM(o->lines, O_LCNT_MIN, O_LCNT_MAX, O_LCNT_SD); |
153 | for (lcnt = 0; lcnt < o->lines; lcnt++) { |
154 | o->l[lcnt].okey = o->okey; |
155 | ; |
156 | o->l[lcnt].lcnt = lcnt + 1; |
157 | RANDOM(o->l[lcnt].quantity, L_QTY_MIN, L_QTY_MAX, L_QTY_SD); |
158 | RANDOM(o->l[lcnt].discount, L_DCNT_MIN, L_DCNT_MAX, L_DCNT_SD); |
159 | RANDOM(o->l[lcnt].tax, L_TAX_MIN, L_TAX_MAX, L_TAX_SD); |
160 | pick_str(&l_instruct_set, L_SHIP_SD, o->l[lcnt].shipinstruct); |
161 | pick_str(&l_smode_set, L_SMODE_SD, o->l[lcnt].shipmode); |
162 | TEXT(L_CMNT_LEN, L_CMNT_SD, o->l[lcnt].comment); |
163 | o->l[lcnt].clen = (int)strlen(o->l[lcnt].comment); |
164 | if (scale >= 30000) |
165 | RANDOM64(o->l[lcnt].partkey, L_PKEY_MIN, L_PKEY_MAX, L_PKEY_SD); |
166 | else |
167 | RANDOM(o->l[lcnt].partkey, L_PKEY_MIN, L_PKEY_MAX, L_PKEY_SD); |
168 | rprice = rpb_routine(o->l[lcnt].partkey); |
169 | RANDOM(supp_num, 0, 3, L_SKEY_SD); |
170 | PART_SUPP_BRIDGE(o->l[lcnt].suppkey, o->l[lcnt].partkey, supp_num); |
171 | o->l[lcnt].eprice = rprice * o->l[lcnt].quantity; |
172 | |
173 | o->totalprice += ((o->l[lcnt].eprice * ((long)100 - o->l[lcnt].discount)) / (long)PENNIES) * |
174 | ((long)100 + o->l[lcnt].tax) / (long)PENNIES; |
175 | |
176 | RANDOM(s_date, L_SDTE_MIN, L_SDTE_MAX, L_SDTE_SD); |
177 | s_date += tmp_date; |
178 | RANDOM(c_date, L_CDTE_MIN, L_CDTE_MAX, L_CDTE_SD); |
179 | c_date += tmp_date; |
180 | RANDOM(r_date, L_RDTE_MIN, L_RDTE_MAX, L_RDTE_SD); |
181 | r_date += s_date; |
182 | |
183 | strcpy(o->l[lcnt].sdate, asc_date[s_date - STARTDATE]); |
184 | strcpy(o->l[lcnt].cdate, asc_date[c_date - STARTDATE]); |
185 | strcpy(o->l[lcnt].rdate, asc_date[r_date - STARTDATE]); |
186 | |
187 | if (julian(r_date) <= CURRENTDATE) { |
188 | pick_str(&l_rflag_set, L_RFLG_SD, tmp_str); |
189 | o->l[lcnt].rflag[0] = *tmp_str; |
190 | } else |
191 | o->l[lcnt].rflag[0] = 'N'; |
192 | |
193 | if (julian(s_date) <= CURRENTDATE) { |
194 | ocnt++; |
195 | o->l[lcnt].lstatus[0] = 'F'; |
196 | } else |
197 | o->l[lcnt].lstatus[0] = 'O'; |
198 | } |
199 | |
200 | if (ocnt > 0) |
201 | o->orderstatus = 'P'; |
202 | if (ocnt == o->lines) |
203 | o->orderstatus = 'F'; |
204 | |
205 | return (0); |
206 | } |
207 | |
208 | long mk_part(DSS_HUGE index, part_t *p) { |
209 | DSS_HUGE temp; |
210 | long snum; |
211 | DSS_HUGE brnd; |
212 | static int bInit = 0; |
213 | static char szFormat[100]; |
214 | static char szBrandFormat[100]; |
215 | |
216 | if (!bInit) { |
217 | sprintf(szFormat, P_MFG_FMT, 1, HUGE_FORMAT + 1); |
218 | sprintf(szBrandFormat, P_BRND_FMT, 2, HUGE_FORMAT + 1); |
219 | bInit = 1; |
220 | } |
221 | p->partkey = index; |
222 | agg_str(&colors, (long)P_NAME_SCL, (long)P_NAME_SD, p->name); |
223 | RANDOM(temp, P_MFG_MIN, P_MFG_MAX, P_MFG_SD); |
224 | sprintf(p->mfgr, szFormat, P_MFG_TAG, temp); |
225 | RANDOM(brnd, P_BRND_MIN, P_BRND_MAX, P_BRND_SD); |
226 | sprintf(p->brand, szBrandFormat, P_BRND_TAG, (temp * 10 + brnd)); |
227 | p->tlen = pick_str(&p_types_set, P_TYPE_SD, p->type); |
228 | p->tlen = (int)strlen(p_types_set.list[p->tlen].text); |
229 | RANDOM(p->size, P_SIZE_MIN, P_SIZE_MAX, P_SIZE_SD); |
230 | pick_str(&p_cntr_set, P_CNTR_SD, p->container); |
231 | p->retailprice = rpb_routine(index); |
232 | TEXT(P_CMNT_LEN, P_CMNT_SD, p->comment); |
233 | p->clen = (int)strlen(p->comment); |
234 | |
235 | for (snum = 0; snum < SUPP_PER_PART; snum++) { |
236 | p->s[snum].partkey = p->partkey; |
237 | PART_SUPP_BRIDGE(p->s[snum].suppkey, index, snum); |
238 | RANDOM(p->s[snum].qty, PS_QTY_MIN, PS_QTY_MAX, PS_QTY_SD); |
239 | RANDOM(p->s[snum].scost, PS_SCST_MIN, PS_SCST_MAX, PS_SCST_SD); |
240 | TEXT(PS_CMNT_LEN, PS_CMNT_SD, p->s[snum].comment); |
241 | p->s[snum].clen = (int)strlen(p->s[snum].comment); |
242 | } |
243 | return (0); |
244 | } |
245 | |
246 | long mk_supp(DSS_HUGE index, supplier_t *s) { |
247 | DSS_HUGE i, bad_press, noise, offset, type; |
248 | static int bInit = 0; |
249 | static char szFormat[100]; |
250 | |
251 | if (!bInit) { |
252 | sprintf(szFormat, S_NAME_FMT, 9, HUGE_FORMAT + 1); |
253 | bInit = 1; |
254 | } |
255 | s->suppkey = index; |
256 | sprintf(s->name, szFormat, S_NAME_TAG, index); |
257 | V_STR(S_ADDR_LEN, S_ADDR_SD, s->address); |
258 | s->alen = (int)strlen(s->address); |
259 | RANDOM(i, 0, nations.count - 1, S_NTRG_SD); |
260 | s->nation_code = i; |
261 | gen_phone(i, s->phone, S_PHNE_SD); |
262 | RANDOM(s->acctbal, S_ABAL_MIN, S_ABAL_MAX, S_ABAL_SD); |
263 | |
264 | TEXT(S_CMNT_LEN, S_CMNT_SD, s->comment); |
265 | s->clen = (int)strlen(s->comment); |
266 | /* |
267 | * these calls should really move inside the if stmt below, but this |
268 | * will simplify seedless parallel load |
269 | */ |
270 | RANDOM(bad_press, 1, 10000, BBB_CMNT_SD); |
271 | RANDOM(type, 0, 100, BBB_TYPE_SD); |
272 | RANDOM(noise, 0, (s->clen - BBB_CMNT_LEN), BBB_JNK_SD); |
273 | RANDOM(offset, 0, (s->clen - (BBB_CMNT_LEN + noise)), BBB_OFFSET_SD); |
274 | if (bad_press <= S_CMNT_BBB) { |
275 | type = (type < BBB_DEADBEATS) ? 0 : 1; |
276 | memcpy(s->comment + offset, BBB_BASE, BBB_BASE_LEN); |
277 | if (type == 0) |
278 | memcpy(s->comment + BBB_BASE_LEN + offset + noise, BBB_COMPLAIN, BBB_TYPE_LEN); |
279 | else |
280 | memcpy(s->comment + BBB_BASE_LEN + offset + noise, BBB_COMMEND, BBB_TYPE_LEN); |
281 | } |
282 | return (0); |
283 | } |
284 | |
285 | struct { |
286 | char *mdes; |
287 | long days; |
288 | long dcnt; |
289 | } months[] = |
290 | |
291 | {{NULL, 0, 0}, {"JAN" , 31, 31}, {"FEB" , 28, 59}, {"MAR" , 31, 90}, {"APR" , 30, 120}, |
292 | {"MAY" , 31, 151}, {"JUN" , 30, 181}, {"JUL" , 31, 212}, {"AUG" , 31, 243}, {"SEP" , 30, 273}, |
293 | {"OCT" , 31, 304}, {"NOV" , 30, 334}, {"DEC" , 31, 365}}; |
294 | |
295 | long mk_time(DSS_HUGE index, dss_time_t *t) { |
296 | long m = 0; |
297 | long y; |
298 | long d; |
299 | |
300 | t->timekey = index + JDAY_BASE; |
301 | y = julian(index + STARTDATE - 1) / 1000; |
302 | d = julian(index + STARTDATE - 1) % 1000; |
303 | while (d > months[m].dcnt + LEAP_ADJ(y, m)) |
304 | m++; |
305 | PR_DATE(t->alpha, y, m, d - months[m - 1].dcnt - ((LEAP(y) && m > 2) ? 1 : 0)); |
306 | t->year = 1900 + y; |
307 | t->month = m + 12 * y + JMNTH_BASE; |
308 | t->week = (d + T_START_DAY - 1) / 7 + 1; |
309 | t->day = d - months[m - 1].dcnt - LEAP_ADJ(y, m - 1); |
310 | |
311 | return (0); |
312 | } |
313 | |
314 | int mk_nation(DSS_HUGE index, code_t *c) { |
315 | c->code = index - 1; |
316 | c->text = nations.list[index - 1].text; |
317 | c->join = nations.list[index - 1].weight; |
318 | TEXT(N_CMNT_LEN, N_CMNT_SD, c->comment); |
319 | c->clen = (int)strlen(c->comment); |
320 | return (0); |
321 | } |
322 | |
323 | int mk_region(DSS_HUGE index, code_t *c) { |
324 | |
325 | c->code = index - 1; |
326 | c->text = regions.list[index - 1].text; |
327 | c->join = 0; /* for completeness */ |
328 | TEXT(R_CMNT_LEN, R_CMNT_SD, c->comment); |
329 | c->clen = (int)strlen(c->comment); |
330 | return (0); |
331 | } |
332 | |