| 1 | /* |
| 2 | * $Id: driver.c,v 1.7 2008/09/24 22:35:21 jms Exp $ |
| 3 | * |
| 4 | * Revision History |
| 5 | * =================== |
| 6 | * $Log: driver.c,v $ |
| 7 | * Revision 1.7 2008/09/24 22:35:21 jms |
| 8 | * remove build number header |
| 9 | * |
| 10 | * Revision 1.6 2008/09/24 22:30:29 jms |
| 11 | * remove build number from default header |
| 12 | * |
| 13 | * Revision 1.5 2008/03/21 17:38:39 jms |
| 14 | * changes for 2.6.3 |
| 15 | * |
| 16 | * Revision 1.4 2006/04/26 23:01:10 jms |
| 17 | * address update generation problems |
| 18 | * |
| 19 | * Revision 1.3 2005/10/28 02:54:35 jms |
| 20 | * add release.h changes |
| 21 | * |
| 22 | * Revision 1.2 2005/01/03 20:08:58 jms |
| 23 | * change line terminations |
| 24 | * |
| 25 | * Revision 1.1.1.1 2004/11/24 23:31:46 jms |
| 26 | * re-establish external server |
| 27 | * |
| 28 | * Revision 1.5 2004/04/07 20:17:29 jms |
| 29 | * bug #58 (join fails between order/lineitem) |
| 30 | * |
| 31 | * Revision 1.4 2004/02/18 16:26:49 jms |
| 32 | * 32/64 bit changes for overflow handling needed additional changes when ported back to windows |
| 33 | * |
| 34 | * Revision 1.3 2004/01/22 05:49:29 jms |
| 35 | * AIX porting (AIX 5.1) |
| 36 | * |
| 37 | * Revision 1.2 2004/01/22 03:54:12 jms |
| 38 | * 64 bit support changes for customer address |
| 39 | * |
| 40 | * Revision 1.1.1.1 2003/08/08 21:50:33 jms |
| 41 | * recreation after CVS crash |
| 42 | * |
| 43 | * Revision 1.3 2003/08/08 21:35:26 jms |
| 44 | * first integration of rng64 for o_custkey and l_partkey |
| 45 | * |
| 46 | * Revision 1.2 2003/08/07 17:58:34 jms |
| 47 | * Convery RNG to 64bit space as preparation for new large scale RNG |
| 48 | * |
| 49 | * Revision 1.1.1.1 2003/04/03 18:54:21 jms |
| 50 | * initial checkin |
| 51 | * |
| 52 | * |
| 53 | */ |
| 54 | /* main driver for dss banchmark */ |
| 55 | |
| 56 | #define DECLARER /* EXTERN references get defined here */ |
| 57 | #define NO_FUNC (int (*) ()) NULL /* to clean up tdefs */ |
| 58 | #define NO_LFUNC (long (*) ()) NULL /* to clean up tdefs */ |
| 59 | |
| 60 | #include "config.h" |
| 61 | #include "release.h" |
| 62 | #include <stdlib.h> |
| 63 | #if (defined(_POSIX_)||!defined(WIN32)) /* Change for Windows NT */ |
| 64 | #include <unistd.h> |
| 65 | #include <sys/wait.h> |
| 66 | #endif /* WIN32 */ |
| 67 | #include <stdio.h> /* */ |
| 68 | #include <limits.h> |
| 69 | #include <math.h> |
| 70 | #include <ctype.h> |
| 71 | #include <signal.h> |
| 72 | #include <string.h> |
| 73 | #include <errno.h> |
| 74 | #ifdef HP |
| 75 | #include <strings.h> |
| 76 | #endif |
| 77 | #if (defined(WIN32)&&!defined(_POSIX_)) |
| 78 | #include <process.h> |
| 79 | #pragma warning(disable:4201) |
| 80 | #pragma warning(disable:4214) |
| 81 | #pragma warning(disable:4514) |
| 82 | #define WIN32_LEAN_AND_MEAN |
| 83 | #define NOATOM |
| 84 | #define NOGDICAPMASKS |
| 85 | #define NOMETAFILE |
| 86 | #define NOMINMAX |
| 87 | #define NOMSG |
| 88 | #define NOOPENFILE |
| 89 | #define NORASTEROPS |
| 90 | #define NOSCROLL |
| 91 | #define NOSOUND |
| 92 | #define NOSYSMETRICS |
| 93 | #define NOTEXTMETRIC |
| 94 | #define NOWH |
| 95 | #define NOCOMM |
| 96 | #define NOKANJI |
| 97 | #define NOMCX |
| 98 | #include <windows.h> |
| 99 | #pragma warning(default:4201) |
| 100 | #pragma warning(default:4214) |
| 101 | #endif |
| 102 | |
| 103 | #include "dss.h" |
| 104 | #include "dsstypes.h" |
| 105 | |
| 106 | /* |
| 107 | * Function prototypes |
| 108 | */ |
| 109 | void usage (void); |
| 110 | void kill_load (void); |
| 111 | int pload (int tbl); |
| 112 | void gen_tbl (int tnum, DSS_HUGE start, DSS_HUGE count, long upd_num); |
| 113 | int pr_drange (int tbl, DSS_HUGE min, DSS_HUGE cnt, long num); |
| 114 | int set_files (int t, int pload); |
| 115 | int partial (int, int); |
| 116 | |
| 117 | |
| 118 | extern int optind, opterr; |
| 119 | extern char *optarg; |
| 120 | DSS_HUGE rowcnt = 0, minrow = 0; |
| 121 | long upd_num = 0; |
| 122 | double flt_scale; |
| 123 | #if (defined(WIN32)&&!defined(_POSIX_)) |
| 124 | char *spawn_args[25]; |
| 125 | #endif |
| 126 | #ifdef RNG_TEST |
| 127 | extern seed_t Seed[]; |
| 128 | #endif |
| 129 | static int bTableSet = 0; |
| 130 | |
| 131 | |
| 132 | /* |
| 133 | * general table descriptions. See dss.h for details on structure |
| 134 | * NOTE: tables with no scaling info are scaled according to |
| 135 | * another table |
| 136 | * |
| 137 | * |
| 138 | * the following is based on the tdef structure defined in dss.h as: |
| 139 | * typedef struct |
| 140 | * { |
| 141 | * char *name; -- name of the table; |
| 142 | * flat file output in <name>.tbl |
| 143 | * long base; -- base scale rowcount of table; |
| 144 | * 0 if derived |
| 145 | * int (*loader) (); -- function to present output |
| 146 | * long (*gen_seed) (); -- functions to seed the RNG |
| 147 | * int child; -- non-zero if there is an associated detail table |
| 148 | * unsigned long vtotal; -- "checksum" total |
| 149 | * } tdef; |
| 150 | * |
| 151 | */ |
| 152 | |
| 153 | /* |
| 154 | * flat file print functions; used with -F(lat) option |
| 155 | */ |
| 156 | int pr_cust (customer_t * c, int mode); |
| 157 | int pr_line (order_t * o, int mode); |
| 158 | int pr_order (order_t * o, int mode); |
| 159 | int pr_part (part_t * p, int mode); |
| 160 | int pr_psupp (part_t * p, int mode); |
| 161 | int pr_supp (supplier_t * s, int mode); |
| 162 | int pr_order_line (order_t * o, int mode); |
| 163 | int pr_part_psupp (part_t * p, int mode); |
| 164 | int pr_nation (code_t * c, int mode); |
| 165 | int pr_region (code_t * c, int mode); |
| 166 | |
| 167 | /* |
| 168 | * seed generation functions; used with '-O s' option |
| 169 | */ |
| 170 | long sd_cust (int child, DSS_HUGE skip_count); |
| 171 | long sd_line (int child, DSS_HUGE skip_count); |
| 172 | long sd_order (int child, DSS_HUGE skip_count); |
| 173 | long sd_part (int child, DSS_HUGE skip_count); |
| 174 | long sd_psupp (int child, DSS_HUGE skip_count); |
| 175 | long sd_supp (int child, DSS_HUGE skip_count); |
| 176 | long sd_order_line (int child, DSS_HUGE skip_count); |
| 177 | long sd_part_psupp (int child, DSS_HUGE skip_count); |
| 178 | |
| 179 | tdef tdefs[] = |
| 180 | { |
| 181 | {"part.tbl" , "part table" , 200000, |
| 182 | pr_part, sd_part, PSUPP, 0}, |
| 183 | {"partsupp.tbl" , "partsupplier table" , 200000, |
| 184 | pr_psupp, sd_psupp, NONE, 0}, |
| 185 | {"supplier.tbl" , "suppliers table" , 10000, |
| 186 | pr_supp, sd_supp, NONE, 0}, |
| 187 | {"customer.tbl" , "customers table" , 150000, |
| 188 | pr_cust, sd_cust, NONE, 0}, |
| 189 | {"orders.tbl" , "order table" , 150000, |
| 190 | pr_order, sd_order, LINE, 0}, |
| 191 | {"lineitem.tbl" , "lineitem table" , 150000, |
| 192 | pr_line, sd_line, NONE, 0}, |
| 193 | {"orders.tbl" , "orders/lineitem tables" , 150000, |
| 194 | pr_order_line, sd_order, LINE, 0}, |
| 195 | {"part.tbl" , "part/partsupplier tables" , 200000, |
| 196 | pr_part_psupp, sd_part, PSUPP, 0}, |
| 197 | {"nation.tbl" , "nation table" , NATIONS_MAX, |
| 198 | pr_nation, NO_LFUNC, NONE, 0}, |
| 199 | {"region.tbl" , "region table" , NATIONS_MAX, |
| 200 | pr_region, NO_LFUNC, NONE, 0}, |
| 201 | }; |
| 202 | |
| 203 | /* |
| 204 | * re-set default output file names |
| 205 | */ |
| 206 | int |
| 207 | set_files (int i, int pload) |
| 208 | { |
| 209 | char line[80], *new_name; |
| 210 | |
| 211 | if (table & (1 << i)) |
| 212 | child_table: |
| 213 | { |
| 214 | if (pload != -1) |
| 215 | sprintf (line, "%s.%d" , tdefs[i].name, pload); |
| 216 | else |
| 217 | { |
| 218 | printf ("Enter new destination for %s data: " , |
| 219 | tdefs[i].name); |
| 220 | if (fgets (line, sizeof (line), stdin) == NULL) |
| 221 | return (-1);; |
| 222 | if ((new_name = strchr (line, '\n')) != NULL) |
| 223 | *new_name = '\0'; |
| 224 | if ((int)strlen (line) == 0) |
| 225 | return (0); |
| 226 | } |
| 227 | new_name = (char *) malloc ((int)strlen (line) + 1); |
| 228 | MALLOC_CHECK (new_name); |
| 229 | strcpy (new_name, line); |
| 230 | tdefs[i].name = new_name; |
| 231 | if (tdefs[i].child != NONE) |
| 232 | { |
| 233 | i = tdefs[i].child; |
| 234 | tdefs[i].child = NONE; |
| 235 | goto child_table; |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | return (0); |
| 240 | } |
| 241 | |
| 242 | |
| 243 | |
| 244 | /* |
| 245 | * read the distributions needed in the benchamrk |
| 246 | */ |
| 247 | void |
| 248 | load_dists (void) |
| 249 | { |
| 250 | read_dist (env_config (DIST_TAG, DIST_DFLT), "p_cntr" , &p_cntr_set); |
| 251 | read_dist (env_config (DIST_TAG, DIST_DFLT), "colors" , &colors); |
| 252 | read_dist (env_config (DIST_TAG, DIST_DFLT), "p_types" , &p_types_set); |
| 253 | read_dist (env_config (DIST_TAG, DIST_DFLT), "nations" , &nations); |
| 254 | read_dist (env_config (DIST_TAG, DIST_DFLT), "regions" , ®ions); |
| 255 | read_dist (env_config (DIST_TAG, DIST_DFLT), "o_oprio" , |
| 256 | &o_priority_set); |
| 257 | read_dist (env_config (DIST_TAG, DIST_DFLT), "instruct" , |
| 258 | &l_instruct_set); |
| 259 | read_dist (env_config (DIST_TAG, DIST_DFLT), "smode" , &l_smode_set); |
| 260 | read_dist (env_config (DIST_TAG, DIST_DFLT), "category" , |
| 261 | &l_category_set); |
| 262 | read_dist (env_config (DIST_TAG, DIST_DFLT), "rflag" , &l_rflag_set); |
| 263 | read_dist (env_config (DIST_TAG, DIST_DFLT), "msegmnt" , &c_mseg_set); |
| 264 | |
| 265 | /* load the distributions that contain text generation */ |
| 266 | read_dist (env_config (DIST_TAG, DIST_DFLT), "nouns" , &nouns); |
| 267 | read_dist (env_config (DIST_TAG, DIST_DFLT), "verbs" , &verbs); |
| 268 | read_dist (env_config (DIST_TAG, DIST_DFLT), "adjectives" , &adjectives); |
| 269 | read_dist (env_config (DIST_TAG, DIST_DFLT), "adverbs" , &adverbs); |
| 270 | read_dist (env_config (DIST_TAG, DIST_DFLT), "auxillaries" , &auxillaries); |
| 271 | read_dist (env_config (DIST_TAG, DIST_DFLT), "terminators" , &terminators); |
| 272 | read_dist (env_config (DIST_TAG, DIST_DFLT), "articles" , &articles); |
| 273 | read_dist (env_config (DIST_TAG, DIST_DFLT), "prepositions" , &prepositions); |
| 274 | read_dist (env_config (DIST_TAG, DIST_DFLT), "grammar" , &grammar); |
| 275 | read_dist (env_config (DIST_TAG, DIST_DFLT), "np" , &np); |
| 276 | read_dist (env_config (DIST_TAG, DIST_DFLT), "vp" , &vp); |
| 277 | |
| 278 | } |
| 279 | |
| 280 | /* |
| 281 | * generate a particular table |
| 282 | */ |
| 283 | void |
| 284 | gen_tbl (int tnum, DSS_HUGE start, DSS_HUGE count, long upd_num) |
| 285 | { |
| 286 | static order_t o; |
| 287 | supplier_t supp; |
| 288 | customer_t cust; |
| 289 | part_t part; |
| 290 | code_t code; |
| 291 | static int completed = 0; |
| 292 | DSS_HUGE i; |
| 293 | |
| 294 | DSS_HUGE rows_per_segment=0; |
| 295 | DSS_HUGE rows_this_segment=-1; |
| 296 | DSS_HUGE residual_rows=0; |
| 297 | |
| 298 | if (insert_segments) |
| 299 | { |
| 300 | rows_per_segment = count / insert_segments; |
| 301 | residual_rows = count - (rows_per_segment * insert_segments); |
| 302 | } |
| 303 | |
| 304 | for (i = start; count; count--, i++) |
| 305 | { |
| 306 | LIFENOISE (1000, i); |
| 307 | row_start(tnum); |
| 308 | |
| 309 | switch (tnum) |
| 310 | { |
| 311 | case LINE: |
| 312 | case ORDER: |
| 313 | case ORDER_LINE: |
| 314 | mk_order (i, &o, upd_num % 10000); |
| 315 | |
| 316 | if (insert_segments && (upd_num > 0)) |
| 317 | if((upd_num / 10000) < residual_rows) |
| 318 | { |
| 319 | if((++rows_this_segment) > rows_per_segment) |
| 320 | { |
| 321 | rows_this_segment=0; |
| 322 | upd_num += 10000; |
| 323 | } |
| 324 | } |
| 325 | else |
| 326 | { |
| 327 | if((++rows_this_segment) >= rows_per_segment) |
| 328 | { |
| 329 | rows_this_segment=0; |
| 330 | upd_num += 10000; |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | if (set_seeds == 0) |
| 335 | tdefs[tnum].loader(&o, upd_num); |
| 336 | break; |
| 337 | case SUPP: |
| 338 | mk_supp (i, &supp); |
| 339 | if (set_seeds == 0) |
| 340 | tdefs[tnum].loader(&supp, upd_num); |
| 341 | break; |
| 342 | case CUST: |
| 343 | mk_cust (i, &cust); |
| 344 | if (set_seeds == 0) |
| 345 | tdefs[tnum].loader(&cust, upd_num); |
| 346 | break; |
| 347 | case PSUPP: |
| 348 | case PART: |
| 349 | case PART_PSUPP: |
| 350 | mk_part (i, &part); |
| 351 | if (set_seeds == 0) |
| 352 | tdefs[tnum].loader(&part, upd_num); |
| 353 | break; |
| 354 | case NATION: |
| 355 | mk_nation (i, &code); |
| 356 | if (set_seeds == 0) |
| 357 | tdefs[tnum].loader(&code, 0); |
| 358 | break; |
| 359 | case REGION: |
| 360 | mk_region (i, &code); |
| 361 | if (set_seeds == 0) |
| 362 | tdefs[tnum].loader(&code, 0); |
| 363 | break; |
| 364 | } |
| 365 | row_stop(tnum); |
| 366 | if (set_seeds && (i % tdefs[tnum].base) < 2) |
| 367 | { |
| 368 | printf("\nSeeds for %s at rowcount %ld\n" , tdefs[tnum].comment, i); |
| 369 | dump_seeds(tnum); |
| 370 | } |
| 371 | } |
| 372 | completed |= 1 << tnum; |
| 373 | } |
| 374 | |
| 375 | |
| 376 | |
| 377 | void |
| 378 | usage (void) |
| 379 | { |
| 380 | fprintf (stderr, "%s\n%s\n\t%s\n%s %s\n\n" , |
| 381 | "USAGE:" , |
| 382 | "dbgen [-{vf}][-T {pcsoPSOL}]" , |
| 383 | "[-s <scale>][-C <procs>][-S <step>]" , |
| 384 | "dbgen [-v] [-O m] [-s <scale>]" , |
| 385 | "[-U <updates>]" ); |
| 386 | fprintf (stderr, "Basic Options\n===========================\n" ); |
| 387 | fprintf (stderr, "-C <n> -- separate data set into <n> chunks (requires -S, default: 1)\n" ); |
| 388 | fprintf (stderr, "-f -- force. Overwrite existing files\n" ); |
| 389 | fprintf (stderr, "-h -- display this message\n" ); |
| 390 | fprintf (stderr, "-q -- enable QUIET mode\n" ); |
| 391 | fprintf (stderr, "-s <n> -- set Scale Factor (SF) to <n> (default: 1) \n" ); |
| 392 | fprintf (stderr, "-S <n> -- build the <n>th step of the data/update set (used with -C or -U)\n" ); |
| 393 | fprintf (stderr, "-U <n> -- generate <n> update sets\n" ); |
| 394 | fprintf (stderr, "-v -- enable VERBOSE mode\n" ); |
| 395 | fprintf (stderr, "\nAdvanced Options\n===========================\n" ); |
| 396 | fprintf (stderr, "-b <s> -- load distributions for <s> (default: dists.dss)\n" ); |
| 397 | fprintf (stderr, "-d <n> -- split deletes between <n> files (requires -U)\n" ); |
| 398 | fprintf (stderr, "-i <n> -- split inserts between <n> files (requires -U)\n" ); |
| 399 | fprintf (stderr, "-T c -- generate cutomers ONLY\n" ); |
| 400 | fprintf (stderr, "-T l -- generate nation/region ONLY\n" ); |
| 401 | fprintf (stderr, "-T L -- generate lineitem ONLY\n" ); |
| 402 | fprintf (stderr, "-T n -- generate nation ONLY\n" ); |
| 403 | fprintf (stderr, "-T o -- generate orders/lineitem ONLY\n" ); |
| 404 | fprintf (stderr, "-T O -- generate orders ONLY\n" ); |
| 405 | fprintf (stderr, "-T p -- generate parts/partsupp ONLY\n" ); |
| 406 | fprintf (stderr, "-T P -- generate parts ONLY\n" ); |
| 407 | fprintf (stderr, "-T r -- generate region ONLY\n" ); |
| 408 | fprintf (stderr, "-T s -- generate suppliers ONLY\n" ); |
| 409 | fprintf (stderr, "-T S -- generate partsupp ONLY\n" ); |
| 410 | fprintf (stderr, |
| 411 | "\nTo generate the SF=1 (1GB), validation database population, use:\n" ); |
| 412 | fprintf (stderr, "\tdbgen -vf -s 1\n" ); |
| 413 | fprintf (stderr, "\nTo generate updates for a SF=1 (1GB), use:\n" ); |
| 414 | fprintf (stderr, "\tdbgen -v -U 1 -s 1\n" ); |
| 415 | } |
| 416 | |
| 417 | /* |
| 418 | * int partial(int tbl, int s) -- generate the s-th part of the named tables data |
| 419 | */ |
| 420 | int |
| 421 | partial (int tbl, int s) |
| 422 | { |
| 423 | DSS_HUGE rowcnt; |
| 424 | DSS_HUGE ; |
| 425 | |
| 426 | if (verbose > 0) |
| 427 | { |
| 428 | fprintf (stderr, "\tStarting to load stage %d of %ld for %s..." , |
| 429 | s, children, tdefs[tbl].comment); |
| 430 | } |
| 431 | |
| 432 | set_files (tbl, s); |
| 433 | |
| 434 | rowcnt = set_state(tbl, scale, children, s, &extra); |
| 435 | |
| 436 | if (s == children) |
| 437 | gen_tbl (tbl, rowcnt * (s - 1) + 1, rowcnt + extra, upd_num); |
| 438 | else |
| 439 | gen_tbl (tbl, rowcnt * (s - 1) + 1, rowcnt, upd_num); |
| 440 | |
| 441 | if (verbose > 0) |
| 442 | fprintf (stderr, "done.\n" ); |
| 443 | |
| 444 | return (0); |
| 445 | } |
| 446 | |
| 447 | void |
| 448 | process_options (int count, char **vector) |
| 449 | { |
| 450 | int option; |
| 451 | FILE *pF; |
| 452 | |
| 453 | while ((option = getopt (count, vector, |
| 454 | "b:C:d:fi:hO:P:qs:S:T:U:v" )) != -1) |
| 455 | switch (option) |
| 456 | { |
| 457 | case 'b': /* load distributions from named file */ |
| 458 | d_path = (char *)malloc((int)strlen(optarg) + 1); |
| 459 | MALLOC_CHECK(d_path); |
| 460 | strcpy(d_path, optarg); |
| 461 | if ((pF = fopen(d_path, "r" )) == NULL) |
| 462 | { |
| 463 | fprintf(stderr, "ERROR: Invalid argument to -b" ); |
| 464 | exit(-1); |
| 465 | } |
| 466 | else |
| 467 | fclose(pF); |
| 468 | |
| 469 | break; |
| 470 | case 'C': |
| 471 | children = atoi (optarg); |
| 472 | break; |
| 473 | case 'd': |
| 474 | delete_segments = atoi (optarg); |
| 475 | break; |
| 476 | case 'f': /* blind overwrites; Force */ |
| 477 | force = 1; |
| 478 | break; |
| 479 | case 'i': |
| 480 | insert_segments = atoi (optarg); |
| 481 | break; |
| 482 | case 'q': /* all prompts disabled */ |
| 483 | verbose = -1; |
| 484 | break; |
| 485 | case 's': /* scale by Percentage of base rowcount */ |
| 486 | case 'P': /* for backward compatibility */ |
| 487 | flt_scale = atof (optarg); |
| 488 | if (flt_scale < MIN_SCALE) |
| 489 | { |
| 490 | int i; |
| 491 | int int_scale; |
| 492 | |
| 493 | scale = 1; |
| 494 | int_scale = (int)(1000 * flt_scale); |
| 495 | for (i = PART; i < REGION; i++) |
| 496 | { |
| 497 | tdefs[i].base = (DSS_HUGE)(int_scale * tdefs[i].base)/1000; |
| 498 | if (tdefs[i].base < 1) |
| 499 | tdefs[i].base = 1; |
| 500 | } |
| 501 | } |
| 502 | else |
| 503 | scale = (long) flt_scale; |
| 504 | if (scale > MAX_SCALE) |
| 505 | { |
| 506 | fprintf (stderr, "%s %5.0f %s\n\t%s\n\n" , |
| 507 | "NOTE: Data generation for scale factors >" , |
| 508 | MAX_SCALE, |
| 509 | "GB is still in development," , |
| 510 | "and is not yet supported.\n" ); |
| 511 | fprintf (stderr, |
| 512 | "Your resulting data set MAY NOT BE COMPLIANT!\n" ); |
| 513 | } |
| 514 | break; |
| 515 | case 'S': /* generate a particular STEP */ |
| 516 | step = atoi (optarg); |
| 517 | break; |
| 518 | case 'U': /* generate flat files for update stream */ |
| 519 | updates = atoi (optarg); |
| 520 | break; |
| 521 | case 'v': /* life noises enabled */ |
| 522 | verbose = 1; |
| 523 | break; |
| 524 | case 'T': /* generate a specifc table */ |
| 525 | switch (*optarg) |
| 526 | { |
| 527 | case 'c': /* generate customer ONLY */ |
| 528 | table = 1 << CUST; |
| 529 | bTableSet = 1; |
| 530 | break; |
| 531 | case 'L': /* generate lineitems ONLY */ |
| 532 | table = 1 << LINE; |
| 533 | bTableSet = 1; |
| 534 | break; |
| 535 | case 'l': /* generate code table ONLY */ |
| 536 | table = 1 << NATION; |
| 537 | table |= 1 << REGION; |
| 538 | bTableSet = 1; |
| 539 | break; |
| 540 | case 'n': /* generate nation table ONLY */ |
| 541 | table = 1 << NATION; |
| 542 | bTableSet = 1; |
| 543 | break; |
| 544 | case 'O': /* generate orders ONLY */ |
| 545 | table = 1 << ORDER; |
| 546 | bTableSet = 1; |
| 547 | break; |
| 548 | case 'o': /* generate orders/lineitems ONLY */ |
| 549 | table = 1 << ORDER_LINE; |
| 550 | bTableSet = 1; |
| 551 | break; |
| 552 | case 'P': /* generate part ONLY */ |
| 553 | table = 1 << PART; |
| 554 | bTableSet = 1; |
| 555 | break; |
| 556 | case 'p': /* generate part/partsupp ONLY */ |
| 557 | table = 1 << PART_PSUPP; |
| 558 | bTableSet = 1; |
| 559 | break; |
| 560 | case 'r': /* generate region table ONLY */ |
| 561 | table = 1 << REGION; |
| 562 | bTableSet = 1; |
| 563 | break; |
| 564 | case 'S': /* generate partsupp ONLY */ |
| 565 | table = 1 << PSUPP; |
| 566 | bTableSet = 1; |
| 567 | break; |
| 568 | case 's': /* generate suppliers ONLY */ |
| 569 | table = 1 << SUPP; |
| 570 | bTableSet = 1; |
| 571 | break; |
| 572 | default: |
| 573 | fprintf (stderr, "Unknown table name %s\n" , |
| 574 | optarg); |
| 575 | usage (); |
| 576 | exit (1); |
| 577 | } |
| 578 | break; |
| 579 | case 'O': /* optional actions */ |
| 580 | switch (tolower (*optarg)) |
| 581 | { |
| 582 | case 's': /* calibrate the RNG usage */ |
| 583 | set_seeds = 1; |
| 584 | break; |
| 585 | default: |
| 586 | fprintf (stderr, "Unknown option name %s\n" , |
| 587 | optarg); |
| 588 | usage (); |
| 589 | exit (1); |
| 590 | } |
| 591 | break; |
| 592 | default: |
| 593 | printf ("ERROR: option '%c' unknown.\n" , |
| 594 | *(vector[optind] + 1)); |
| 595 | case 'h': /* something unexpected */ |
| 596 | fprintf (stderr, |
| 597 | "%s Population Generator (Version %d.%d.%d build %d)\n" , |
| 598 | NAME, VERSION, RELEASE, PATCH, BUILD); |
| 599 | fprintf (stderr, "Copyright %s %s\n" , TPC, C_DATES); |
| 600 | usage (); |
| 601 | exit (1); |
| 602 | } |
| 603 | |
| 604 | return; |
| 605 | } |
| 606 | |
| 607 | void validate_options(void) |
| 608 | { |
| 609 | // DBGenOptions, 3.1 |
| 610 | if (children != 1) |
| 611 | { |
| 612 | if (updates != 0) |
| 613 | { |
| 614 | fprintf(stderr, "ERROR: -C is not valid when generating updates\n" ); |
| 615 | exit(-1); |
| 616 | } |
| 617 | if (step == -1) |
| 618 | { |
| 619 | fprintf(stderr, "ERROR: -S must be specified when generating data in multiple chunks\n" ); |
| 620 | exit(-1); |
| 621 | } |
| 622 | } |
| 623 | |
| 624 | // DBGenOptions, 3.3 |
| 625 | if (updates == 0) |
| 626 | { |
| 627 | if ((insert_segments != 0) || (delete_segments != 0)) |
| 628 | { |
| 629 | fprintf(stderr, "ERROR: -d/-i are only valid when generating updates\n" ); |
| 630 | exit(-1); |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | // DBGenOptions, 3.9 |
| 635 | if (step != -1) |
| 636 | { |
| 637 | if ((children == 1) && (updates == 0)) |
| 638 | { |
| 639 | fprintf(stderr, "ERROR: -S is only valid when generating data in multiple chunks or generating updates\n" ); |
| 640 | exit(-1); |
| 641 | } |
| 642 | } |
| 643 | |
| 644 | // DBGenOptions, 3.10 |
| 645 | if (bTableSet && (updates != 0)) |
| 646 | { |
| 647 | fprintf(stderr, "ERROR: -T not valid when generating updates\n" ); |
| 648 | exit(-1); |
| 649 | } |
| 650 | |
| 651 | return; |
| 652 | } |
| 653 | |
| 654 | |
| 655 | /* |
| 656 | * MAIN |
| 657 | * |
| 658 | * assumes the existance of getopt() to clean up the command |
| 659 | * line handling |
| 660 | */ |
| 661 | int |
| 662 | main (int ac, char **av) |
| 663 | { |
| 664 | DSS_HUGE i; |
| 665 | |
| 666 | table = (1 << CUST) | |
| 667 | (1 << SUPP) | |
| 668 | (1 << NATION) | |
| 669 | (1 << REGION) | |
| 670 | (1 << PART_PSUPP) | |
| 671 | (1 << ORDER_LINE); |
| 672 | force = 0; |
| 673 | insert_segments=0; |
| 674 | delete_segments=0; |
| 675 | insert_orders_segment=0; |
| 676 | insert_lineitem_segment=0; |
| 677 | delete_segment=0; |
| 678 | verbose = 0; |
| 679 | set_seeds = 0; |
| 680 | scale = 1; |
| 681 | flt_scale = 1.0; |
| 682 | updates = 0; |
| 683 | step = -1; |
| 684 | tdefs[ORDER].base *= |
| 685 | ORDERS_PER_CUST; /* have to do this after init */ |
| 686 | tdefs[LINE].base *= |
| 687 | ORDERS_PER_CUST; /* have to do this after init */ |
| 688 | tdefs[ORDER_LINE].base *= |
| 689 | ORDERS_PER_CUST; /* have to do this after init */ |
| 690 | children = 1; |
| 691 | d_path = NULL; |
| 692 | |
| 693 | #ifdef NO_SUPPORT |
| 694 | signal (SIGINT, exit); |
| 695 | #endif /* NO_SUPPORT */ |
| 696 | process_options (ac, av); |
| 697 | validate_options(); |
| 698 | #if (defined(WIN32)&&!defined(_POSIX_)) |
| 699 | for (i = 0; i < ac; i++) |
| 700 | { |
| 701 | spawn_args[i] = malloc (((int)strlen (av[i]) + 1) * sizeof (char)); |
| 702 | MALLOC_CHECK (spawn_args[i]); |
| 703 | strcpy (spawn_args[i], av[i]); |
| 704 | } |
| 705 | spawn_args[ac] = NULL; |
| 706 | #endif |
| 707 | |
| 708 | if (verbose >= 0) |
| 709 | { |
| 710 | fprintf (stderr, |
| 711 | "%s Population Generator (Version %d.%d.%d)\n" , |
| 712 | NAME, VERSION, RELEASE, PATCH); |
| 713 | fprintf (stderr, "Copyright %s %s\n" , TPC, C_DATES); |
| 714 | } |
| 715 | |
| 716 | load_dists (); |
| 717 | #ifdef RNG_TEST |
| 718 | for (i=0; i <= MAX_STREAM; i++) |
| 719 | Seed[i].nCalls = 0; |
| 720 | #endif |
| 721 | /* have to do this after init */ |
| 722 | tdefs[NATION].base = nations.count; |
| 723 | tdefs[REGION].base = regions.count; |
| 724 | |
| 725 | /* |
| 726 | * updates are never parallelized |
| 727 | */ |
| 728 | if (updates) |
| 729 | { |
| 730 | /* |
| 731 | * set RNG to start generating rows beyond SF=scale |
| 732 | */ |
| 733 | set_state (ORDER, scale, 100, 101, &i); |
| 734 | rowcnt = (int)(tdefs[ORDER_LINE].base / 10000 * scale * UPD_PCT); |
| 735 | if (step > 0) |
| 736 | { |
| 737 | /* |
| 738 | * adjust RNG for any prior update generation |
| 739 | */ |
| 740 | for (i=1; i < step; i++) |
| 741 | { |
| 742 | sd_order(0, rowcnt); |
| 743 | sd_line(0, rowcnt); |
| 744 | } |
| 745 | upd_num = step - 1; |
| 746 | } |
| 747 | else |
| 748 | upd_num = 0; |
| 749 | |
| 750 | while (upd_num < updates) |
| 751 | { |
| 752 | if (verbose > 0) |
| 753 | fprintf (stderr, |
| 754 | "Generating update pair #%ld for %s" , |
| 755 | upd_num + 1, tdefs[ORDER_LINE].comment); |
| 756 | insert_orders_segment=0; |
| 757 | insert_lineitem_segment=0; |
| 758 | delete_segment=0; |
| 759 | minrow = upd_num * rowcnt + 1; |
| 760 | gen_tbl (ORDER_LINE, minrow, rowcnt, upd_num + 1); |
| 761 | if (verbose > 0) |
| 762 | fprintf (stderr, "done.\n" ); |
| 763 | pr_drange (ORDER_LINE, minrow, rowcnt, upd_num + 1); |
| 764 | upd_num++; |
| 765 | } |
| 766 | |
| 767 | exit (0); |
| 768 | } |
| 769 | |
| 770 | /** |
| 771 | ** actual data generation section starts here |
| 772 | **/ |
| 773 | |
| 774 | /* |
| 775 | * traverse the tables, invoking the appropriate data generation routine for any to be built |
| 776 | */ |
| 777 | for (i = PART; i <= REGION; i++) |
| 778 | if (table & (1 << i)) |
| 779 | { |
| 780 | if (children > 1 && i < NATION) |
| 781 | { |
| 782 | partial ((int)i, step); |
| 783 | } |
| 784 | else |
| 785 | { |
| 786 | minrow = 1; |
| 787 | if (i < NATION) |
| 788 | rowcnt = tdefs[i].base * scale; |
| 789 | else |
| 790 | rowcnt = tdefs[i].base; |
| 791 | if (verbose > 0) |
| 792 | fprintf (stderr, "Generating data for %s" , tdefs[i].comment); |
| 793 | gen_tbl ((int)i, minrow, rowcnt, upd_num); |
| 794 | if (verbose > 0) |
| 795 | fprintf (stderr, "done.\n" ); |
| 796 | } |
| 797 | } |
| 798 | |
| 799 | return (0); |
| 800 | } |
| 801 | |