| 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 | |