/* Sccsid: @(#)driver.c 9.1.1.34 5/1/96 11:45:07 */ /* main driver for dss banchmark */ #define DECLARER /* EXTERN references get defined here */ #define NO_FUNC (int (*) ()) NULL /* to clean up tdefs */ #define NO_LFUNC (long (*) ()) NULL /* to clean up tdefs */ #include "config.h" #include #if (defined(_POSIX_)||!defined(WIN32)) /* Change for Windows NT */ #include #include #endif /* WIN32 */ #include /* */ #include #include #include #include #include #include #ifdef HP #include #endif #if (defined(WIN32)&&!defined(_POSIX_)) #include #pragma warning(disable:4201) #pragma warning(disable:4214) #pragma warning(disable:4514) #define WIN32_LEAN_AND_MEAN #define NOATOM #define NOGDICAPMASKS #define NOMETAFILE #define NOMINMAX #define NOMSG #define NOOPENFILE #define NORASTEROPS #define NOSCROLL #define NOSOUND #define NOSYSMETRICS #define NOTEXTMETRIC #define NOWH #define NOCOMM #define NOKANJI #define NOMCX #include #pragma warning(default:4201) #pragma warning(default:4214) #endif #include "dss.h" #include "dsstypes.h" #include "bcd2.h" /* * Function prototypes */ void usage (void); int prep_direct (char *); int close_direct (void); void kill_load (void); int pload (int tbl); void gen_tbl (int tnum, long start, long count, long upd_num); int pr_drange (int tbl, long min, long cnt, long num); int set_files (int t, int pload); void seed_name (char *tgt, long s, long c, long p); int partial (int, int); void gen_seeds (int start, int s); extern int optind, opterr; extern char *optarg; long rowcnt = 0, minrow = 0, upd_num = 0; double flt_scale; #if (defined(WIN32)&&!defined(_POSIX_)) char *spawn_args[25]; #endif /* * Extensions to dbgen for generation of skewed data. * Surajit Chaudhuri, Vivek Narasayya. * (Jan '99) */ /* default skew is 0 -- i.e. uniform distribution */ double skew = 0; /* * general table descriptions. See dss.h for details on structure * NOTE: tables with no scaling info are scaled according to * another table * * * the following is based on the tdef structure defined in dss.h as: * typedef struct * { * char *name; -- name of the table; * flat file output in .tbl * long base; -- base scale rowcount of table; * 0 if derived * int (*header) (); -- function to prep output * int (*loader[2]) (); -- functions to present output * long (*gen_seed) (); -- functions to seed the RNG * int child; -- non-zero if there is an associated detail table * } tdef; * */ /* * flat file print functions; used with -F(lat) option */ int pr_cust (customer_t * c, int mode); int pr_line (order_t * o, int mode); int pr_order (order_t * o, int mode); int pr_part (part_t * p, int mode); int pr_psupp (part_t * p, int mode); int pr_supp (supplier_t * s, int mode); int pr_order_line (order_t * o, int mode); int pr_part_psupp (part_t * p, int mode); int pr_time (dss_time_t * t, int mode); int pr_nation (code_t * c, int mode); int pr_region (code_t * c, int mode); /* * inline load functions; used with -D(irect) option */ int ld_cust (customer_t * c, int mode); int ld_line (order_t * o, int mode); int ld_order (order_t * o, int mode); int ld_part (part_t * p, int mode); int ld_psupp (part_t * p, int mode); int ld_supp (supplier_t * s, int mode); int ld_order_line (order_t * o, int mode); int ld_part_psupp (part_t * p, int mode); int ld_time (dss_time_t * t, int mode); int ld_nation (code_t * c, int mode); int ld_region (code_t * c, int mode); /* * seed generation functions; used with '-O s' option */ long sd_cust (long skip_count); long sd_line (long skip_count); long sd_order (long skip_count); long sd_part (long skip_count); long sd_psupp (long skip_count); long sd_supp (long skip_count); long sd_order_line (long skip_count); long sd_part_psupp (long skip_count); long sd_nation (long skip_count); long sd_region (long skip_count); /* * header output functions); used with -h(eader) option */ int hd_cust (FILE * f); int hd_line (FILE * f); int hd_order (FILE * f); int hd_part (FILE * f); int hd_psupp (FILE * f); int hd_supp (FILE * f); int hd_order_line (FILE * f); int hd_part_psupp (FILE * f); int hd_time (FILE * f); int hd_nation (FILE * f); int hd_region (FILE * f); tdef tdefs[] = { {"part.tbl", "part table", 200000, hd_part, {pr_part, ld_part}, sd_part, NONE}, {"partsupp.tbl", "partsupplier table", 200000, hd_psupp, {pr_psupp, ld_psupp}, sd_psupp, NONE}, {"supplier.tbl", "suppliers table", 10000, hd_supp, {pr_supp, ld_supp}, sd_supp, NONE}, {"customer.tbl", "customers table", 150000, hd_cust, {pr_cust, ld_cust}, sd_cust, NONE}, {"order.tbl", "order table", 150000, hd_order, {pr_order, ld_order}, sd_order, NONE}, {"lineitem.tbl", "lineitem table", 150000, hd_line, {pr_line, ld_line}, sd_line, NONE}, {"order.tbl", "order/lineitem tables", 150000, hd_order_line, {pr_order_line, ld_order_line}, sd_order_line, LINE}, {"part.tbl", "part/partsupplier tables", 200000, hd_part_psupp, {pr_part_psupp, ld_part_psupp}, sd_part_psupp, PSUPP}, {"time.tbl", "time table", 2557, hd_time, {pr_time, ld_time}, NO_LFUNC, NONE}, {"nation.tbl", "nation table", NATIONS_MAX, hd_nation, {pr_nation, ld_nation}, sd_nation, NONE}, {"region.tbl", "region table", NATIONS_MAX, hd_region, {pr_region, ld_region}, sd_region, NONE}, {"TPCDSEED", NULL, 0, NO_FUNC, {NO_FUNC, NO_FUNC}, NO_LFUNC, NONE} }; int *pids; #define LIFENOISE(n) if (verbose && (i % n) == 0) fprintf(stderr, ".") void mk_sparse (long res[], long base, long seq) { long low_mask, seq_mask, overflow = 0; int count = 0; low_mask = (1 << SPARSE_KEEP) - 1; seq_mask = (1 << SPARSE_BITS) - 1; LONG2HUGE (base, res); HUGE_DIV (res, 1 << SPARSE_KEEP); HUGE_MUL (res, 1 << SPARSE_BITS); HUGE_ADD (res, seq, res); HUGE_MUL (res, 1 << SPARSE_KEEP); HUGE_ADD (res, base & low_mask, res); bcd2_bin (&low_mask, res[0]); bcd2_bin (&seq_mask, res[1]); res[0] = low_mask; res[1] = seq_mask; return; } /* * routines to handle the graceful cleanup of multi-process loads */ void stop_proc (int signum) { exit (0); } void kill_load (void) { int i; #if !defined(U2200) && !defined(DOS) for (i = 0; i < children; i++) if (pids[i]) KILL (pids[i]); #endif /* !U2200 && !DOS */ return; } /* * re-set default output file names */ int set_files (int i, int pload) { char line[80], *new_name; if (table & (1 << i)) child_table: { if (pload != -1) sprintf (line, "%s.%d", tdefs[i].name, pload + 1); else { printf ("Enter new destination for %s data: ", tdefs[i].name); if (fgets (line, sizeof (line), stdin) == NULL) return (-1);; if ((new_name = strchr (line, '\n')) != NULL) *new_name = '\0'; if (strlen (line) == 0) return (0); } new_name = (char *) malloc (strlen (line) + 1); MALLOC_CHECK (new_name); strcpy (new_name, line); tdefs[i].name = new_name; if (tdefs[i].child != NONE) { i = tdefs[i].child; tdefs[i].child = NONE; goto child_table; } } return (0); } /* * read the distributions needed in the benchamrk */ void load_dists (void) { read_dist (env_config (DIST_TAG, DIST_DFLT), "p_cntr", &p_cntr_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "colors", &colors); read_dist (env_config (DIST_TAG, DIST_DFLT), "p_types", &p_types_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "nations", &nations); read_dist (env_config (DIST_TAG, DIST_DFLT), "regions", ®ions); read_dist (env_config (DIST_TAG, DIST_DFLT), "o_oprio", &o_priority_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "instruct", &l_instruct_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "smode", &l_smode_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "category", &l_category_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "rflag", &l_rflag_set); read_dist (env_config (DIST_TAG, DIST_DFLT), "msegmnt", &c_mseg_set); } /* * generate a particular table */ #ifndef SUPPORT_64BITS void gen_h_tbl (int tnum, long start[], long count[], long upd_num) { order_t o; static long max_easy = LONG_MAX >> SPARSE_BITS; HUGE_T (i); HUGE_T (sk); HUGE_SET (start, i); while (HUGE_CMP (count, 0) > 0) { if (verbose && (i[0] % 1000) == 0) fprintf (stderr, "."); mk_sparse (sk, (long) i, (upd_num == 0) ? 0 : 1 + upd_num / (10000 / refresh)); /*mk_order (sk, &o);*/ tdefs[tnum].loader[direct] (&o, upd_num); HUGE_SUB (count, 1, count); HUGE_ADD (i, 1, i); } return; } #endif /* SUPPORT_64BITS */ #ifdef SUPPORT_64BITS void gen_tbl (int tnum, DSS_HUGE start, DSS_HUGE count, long upd_num) #else void gen_tbl (int tnum, long start, long count, long upd_num) #endif /* SUPPORT_64BITS */ { order_t o; supplier_t supp; customer_t cust; part_t part; dss_time_t t; code_t code; static long max_easy = LONG_MAX >> SPARSE_BITS; static int completed = 0; long i; HUGE_T (sk); for (i = start; count; count--, i++) { LIFENOISE (1000); ROW_START (tnum); switch (tnum) { case LINE: case ORDER: case ORDER_LINE: mk_sparse (sk, i, (upd_num == 0) ? 0 : 1 + upd_num / (10000 / refresh)); mk_order (sk, &o); /* tdefs[tnum].loader[direct] (&o, upd_num); */ break; case SUPP: mk_supp (i, &supp); tdefs[tnum].loader[direct] (&supp, upd_num); break; case CUST: mk_cust (i, &cust); tdefs[tnum].loader[direct] (&cust, upd_num); break; case PSUPP: case PART: case PART_PSUPP: mk_part (i, &part); tdefs[tnum].loader[direct] (&part, upd_num); break; case TIME: mk_time (i, &t); tdefs[tnum].loader[direct] (&t, 0); break; case NATION: mk_nation (i, &code); tdefs[tnum].loader[direct] (&code, 0); break; case REGION: mk_region (i, &code); tdefs[tnum].loader[direct] (&code, 0); break; } ROW_STOP (tnum); } completed |= 1 << tnum; } void usage (void) { fprintf (stderr, "%s\n%s\n\t%s\n%s %s\n\n", "USAGE:", "dbgen [-{vfFD}] [-O {fhmst}][-T {pcsoPSOL}]", "[-s ][-C ][-S ]", "dbgen [-v] [-O {dhmrt}] [-s ]", "[-U ] [-r ]"); fprintf (stderr, "-C -- use processes to generate data\n"); fprintf (stderr, " [Under DOS, must be used with -S]\n"); fprintf (stderr, "-D -- do database load in line\n"); fprintf (stderr, "-f -- force. Overwrite existing files\n"); fprintf (stderr, "-F -- generate flat files output\n"); fprintf (stderr, "-h -- display this message\n"); fprintf (stderr, "-n -- inline load into database \n"); fprintf (stderr, "-O d -- generate SQL syntax for deletes\n"); fprintf (stderr, "-O f -- over-ride default output file names\n"); fprintf (stderr, "-O h -- output files with headers\n"); fprintf (stderr, "-O m -- produce columnar output\n"); fprintf (stderr, "-O r -- generate key ranges for deletes.\n"); fprintf (stderr, "-O s -- generate seed sets ONLY\n"); fprintf (stderr, "-O t -- use TIME table and julian dates\n"); fprintf (stderr, "-r -- updates refresh (n/100)%% of the\n"); fprintf (stderr, " data set\n"); fprintf (stderr, "-R -- resume seed rfile generation with step \n"); fprintf (stderr, "-s -- set Scale Factor (SF) to \n"); fprintf (stderr, "-S -- build the th step of the data set\n"); fprintf (stderr, "-T c -- generate cutomers ONLY\n"); fprintf (stderr, "-T l -- generate nation/region ONLY\n"); fprintf (stderr, "-T L -- generate lineitem ONLY\n"); fprintf (stderr, "-T n -- generate nation ONLY\n"); fprintf (stderr, "-T o -- generate orders/lineitem ONLY\n"); fprintf (stderr, "-T O -- generate orders ONLY\n"); fprintf (stderr, "-T p -- generate parts/partsupp ONLY\n"); fprintf (stderr, "-T P -- generate parts ONLY\n"); fprintf (stderr, "-T r -- generate region ONLY\n"); fprintf (stderr, "-T s -- generate suppliers ONLY\n"); fprintf (stderr, "-T S -- generate partsupp ONLY\n"); fprintf (stderr, "-U -- generate update sets\n"); fprintf (stderr, "-v -- enable VERBOSE mode\n"); fprintf (stderr, "-z -- generate skewed data for columns with cardinal\n" " data types using the Zipf-distribution for 0 <= n <= 4;\n" " n might be a float. For n < 0 or n > 5 a Zipf-factor\n" " out of {0,1,2,3,4} is chosen by random.\n"); fprintf (stderr, "\nTo generate the SF=1 (1GB) database population , use:\n"); fprintf (stderr, "\tdbgen -vfF -s 1\n"); fprintf (stderr, "\n%s %s\n", "To generate the qualification database population", "(100 MB), use:\n"); fprintf (stderr, "\tdbgen -vfF -s 0.1\n"); fprintf (stderr, "\nTo generate updates for a SF=1 (1GB), use:\n"); fprintf (stderr, "\tdbgen -v -O s -s 1\n"); fprintf (stderr, "\tdbgen -v -U 1 -s 1\n"); } /* * pload() -- handle the parallel loading of tables */ #ifndef DOS int partial (int tbl, int s) { HUGE_T (h_rowcnt); HUGE_T (h_minrow); long rowcnt; long minrow; char fname[80]; long extrarows; if (verbose) { fprintf (stderr, "Starting to load stage %d of %d of %s...", s + 1, children, tdefs[tbl].comment); } if (load_state (scale, children, s)) { seed_name (fname, scale, children, s); fprintf (stderr, "Unable to load seeds (%s)\n", fname); exit (-1); } if (direct == 0) set_files (tbl, s); #ifndef SUPPORT_64BITS if ((tbl == LINE || tbl == ORDER) && scale > MAX_32B_SCALE) { long step_size; step_size = scale / children; if (step_size > MAX_32B_SCALE) { fprintf (stderr, "Each child must generate less than 1TB.\n"); fprintf (stderr, "Please rerun DBGEN with a larger number of children\n"); exit (1); } rowcnt = step_size * tdefs[tbl].base; extrarows = tdefs[tbl].base % children; extrarows *= scale; extrarows %= children; LONG2HUGE (rowcnt, h_rowcnt); LONG2HUGE (rowcnt, h_minrow); HUGE_MUL (h_minrow, s); if (s == children) HUGE_ADD (h_rowcnt, extrarows, h_rowcnt); gen_h_tbl (tbl, h_minrow, h_rowcnt, upd_num); } else { #endif /* SUPPORT_64BITS */ rowcnt = tdefs[tbl].base * scale; extrarows = rowcnt % children; rowcnt /= children; minrow = rowcnt * s + 1; if (s == children) rowcnt += extrarows; gen_tbl (tbl, minrow, rowcnt, upd_num); #ifndef SUPPORT_64BITS } #endif /* SUPPORT_64BITS */ if (verbose) fprintf (stderr, "done.\n"); return (0); } int pload (int tbl) { int c = 0, i, status; char cmdline[256]; rowcnt = tdefs[tbl].base * scale; if (rowcnt % children) { fprintf (stderr, "'-C' cannot split load equally\n"); exit (-1); } else rowcnt /= children; if (verbose) { fprintf (stderr, "Starting %d children to load %s", children, tdefs[tbl].comment); } for (c = 0; c < children; c++) { pids[c] = SPAWN (); if (pids[c] == -1) { perror ("Child loader not created"); kill_load (); exit (-1); } else if (pids[c] == 0) /* CHILD */ { SET_HANDLER (stop_proc); verbose = 0; partial (tbl, c); exit (0); } else if (verbose) /* PARENT */ fprintf (stderr, "."); } if (verbose) fprintf (stderr, "waiting..."); c = children; while (c) { i = WAIT (&status, pids[c - 1]); if (i == -1 && children) { if (errno == ECHILD) fprintf (stderr, "Could not wait on pid %d\n", pids[c - 1]); else if (errno == EINTR) fprintf (stderr, "Process %d stopped abnormally\n", pids[c - 1]); else if (errno == EINVAL) fprintf (stderr, "Program bug\n"); } if (status & 0xFF) { if (status & 0xFF == 0117) printf ("Process %d: STOPPED\n", i); else printf ("Process %d: rcvd signal %d\n", i, status & 0x7F); } c--; } if (direct == 0) { sprintf (cmdline, "mv %s/pl%d.%d%c %s/%s", env_config (PATH_TAG, PATH_DFLT), pids[0], tbl, 'B' + tdefs[tbl].child, env_config (PATH_TAG, PATH_DFLT), tdefs[tbl].name); system (cmdline); #if (defined(WIN32)&&!defined(_POSIX_)) sprintf (cmdline, "COPY %s\\pl*.%d %s\\%s", env_config (PATH_TAG, PATH_DFLT), tbl, env_config (PATH_TAG, PATH_DFLT), tdefs[tbl].name); fprintf (stderr, "%s\n", cmdline); system (cmdline); sprintf (cmdline, "DEL %s\\pl*.%d", env_config (PATH_TAG, PATH_DFLT), tbl); fprintf (stderr, "%s\n", cmdline); system (cmdline); #else for (c = 1; c < children; c++) { sprintf (cmdline, "cat %s/pl%d.%d%c >> %s/%s; rm %s/pl%d.%d%c", env_config (PATH_TAG, PATH_DFLT), pids[c], tbl, 'B' + tdefs[tbl].child, env_config (PATH_TAG, PATH_DFLT), tdefs[tbl].name, env_config (PATH_TAG, PATH_DFLT), pids[c], tbl, 'B' + tdefs[tbl].child); system (cmdline); } #endif /* WIN32 */ } fprintf (stderr, "done\n"); return (0); } #endif /* !DOS */ void process_options (int count, char **vector) { int option; optind = 0; opterr = 0; #ifndef DOS while ((option = getopt (count, vector, "C:DFfhz:n:O:P:r:R:s:S:T:U:v")) != -1) #else while ((option = getopt (count, vector, "DFfhz:n:O:P:r:R:s:S:T:U:v")) != -1) #endif /* !DOS */ switch (option) { case 'S': /* generate a particular STEP */ step = atoi (optarg) - 1; break; case 'v': /* life noises enabled */ verbose = 1; break; case 'z': /* for all columns use specified skew parameter */ skew = atof(optarg); if(skew==-1.0) skew = 5; break; case 'f': /* blind overwrites; Force */ force = 1; break; case 'T': /* generate a specifc table */ switch (*optarg) { case 'c': /* generate customer ONLY */ table = 1 << CUST; break; case 'L': /* generate lineitems ONLY */ table = 1 << LINE; break; case 'l': /* generate code table ONLY */ table = 1 << NATION; table |= 1 << REGION; break; case 'n': /* generate nation table ONLY */ table = 1 << NATION; break; case 'O': /* generate orders ONLY */ table = 1 << ORDER; break; case 'o': /* generate orders/lineitems ONLY */ table = 1 << ORDER_LINE; break; case 'P': /* generate part ONLY */ table = 1 << PART; break; case 'p': /* generate part/partsupp ONLY */ table = 1 << PART_PSUPP; break; case 'r': /* generate region table ONLY */ table = 1 << REGION; break; case 'S': /* generate partsupp ONLY */ table = 1 << PSUPP; break; case 's': /* generate suppliers ONLY */ table = 1 << SUPP; break; case 't': /* generate time ONLY */ table = 1 << TIME; break; default: fprintf (stderr, "Unknown table name %s\n", optarg); usage (); exit (1); } break; case 's': /* scale by Percentage of base rowcount */ case 'P': /* for backward compatibility */ flt_scale = atof (optarg); if (flt_scale < MIN_SCALE) { int i; scale = 1; for (i = PART; i < TIME; i++) { tdefs[i].base *= flt_scale; if (tdefs[i].base < 1) tdefs[i].base = 1; } } else scale = (long) flt_scale; if (scale > MAX_SCALE && bld_seeds != 1) { fprintf (stderr, "%s %5.0f %s\n\t%s\n\n", "NOTE: Data generation for scale factors >", MAX_SCALE, "GB is still in development,", "and is not yet supported.\n"); fprintf (stderr, "Your resulting data set MAY NOT BE COMPLIANT!\n"); } break; case 'O': /* optional actions */ switch (tolower (*optarg)) { case 'd': /* generate SQL for deletes */ gen_sql = 1; break; case 'f': /* over-ride default file names */ fnames = 1; break; case 'h': /* generate headers */ header = 1; break; case 'm': /* generate columnar output */ columnar = 1; break; case 'r': /* generate key ranges for delete */ gen_rng = 1; break; case 's': /* generate seed sets */ bld_seeds = 1; break; case 't': /* use TIME table and join fields */ oldtime = 1; if (updates == 0) table |= (1 << TIME); break; default: fprintf (stderr, "Unknown option name %s\n", optarg); usage (); exit (1); } break; case 'D': /* direct load of generated data */ direct = 1; break; case 'F': /* generate flat files for later loading */ direct = 0; break; case 'U': /* generate flat files for update stream */ updates = atoi (optarg); break; case 'r': /* set the refresh (update) percentage */ refresh = atoi (optarg); break; case 'R': /* resume seed file generation */ resume = atoi (optarg); break; #ifndef DOS case 'C': children = atoi (optarg); if (children > 999) /* limitation of current seed file names */ { printf ("Child process counts of > 999 not supported.\n"); exit (1); } pids = malloc (children * sizeof (pid_t)); break; #endif /* !DOS */ case 'n': /* set name of database for direct load */ db_name = (char *) malloc (strlen (optarg) + 1); MALLOC_CHECK (db_name); strcpy (db_name, optarg); break; default: printf ("ERROR: option '%c' unknown.\n", option); case 'h': /* something unexpected */ fprintf (stderr, "TPC-D Population Generator (Version %d.%d.%d%s)\n", VERSION, RELEASE, MODIFICATION, PATCH); fprintf (stderr, "Copyright %s %s\n", TPC, C_DATES); usage (); exit (1); } return; } void gen_seeds (int start, int s) { int i; long c; double step_size; if (start != 1) { if (load_state (s, children, start - 1)) { char fname[80]; seed_name (fname, s, children, start - 1); fprintf (stderr, "Unable to load seeds (%s)\n", fname); exit (-1); } } for (c = (long) start; c <= children; c++) { for (i = PART; i <= PART_PSUPP; i++) if (table & (1 << i)) { if (verbose) fprintf (stderr, "Generating seeds for %s [step: %d] ", tdefs[i].comment, c); step_size = scale / children; while (step_size > MAX_32B_SCALE) { rowcnt = tdefs[i].base * MAX_32B_SCALE; tdefs[i].gen_seed (rowcnt); step_size -= MAX_32B_SCALE; } rowcnt = tdefs[i].base * step_size; if (c == children) { int k, j=0; for (k = 0; k < scale; k++) j += tdefs[i].base % children; rowcnt += j % children; } if (rowcnt > 1) tdefs[i].gen_seed (rowcnt); } if (verbose) fprintf (stderr, "\n"); if (store_state (scale, children, c)) { fprintf (stderr, "Unable to store seeds\n"); exit (-1); } } exit (0); } /* * MAIN * * assumes the existance of getopt() to clean up the command * line handling */ int main (int ac, char **av) { int i; table = (1 << CUST) | (1 << SUPP) | (1 << NATION) | (1 << REGION) | (1 << PART_PSUPP) | (1 << ORDER_LINE); force = 0; verbose = 0; columnar = 0; bld_seeds = 0; header = 0; oldtime = 0; direct = 0; scale = 1; flt_scale = 1.0; updates = 0; refresh = UPD_PCT; resume = -1; step = -1; tdefs[ORDER].base *= ORDERS_PER_CUST; /* have to do this after init */ tdefs[LINE].base *= ORDERS_PER_CUST; /* have to do this after init */ tdefs[ORDER_LINE].base *= ORDERS_PER_CUST; /* have to do this after init */ fnames = 0; db_name = NULL; gen_sql = 0; gen_rng = 0; children = 1; #ifdef NO_SUPPORT signal (SIGINT, exit); #endif /* NO_SUPPORT */ process_options (ac, av); #if (defined(WIN32)&&!defined(_POSIX_)) for (i = 0; i < ac; i++) { spawn_args[i] = malloc ((strlen (av[i]) + 1) * sizeof (char)); MALLOC_CHECK (spawn_args[i]); strcpy (spawn_args[i], av[i]); } spawn_args[ac] = NULL; #endif fprintf (stderr, "TPC-D Population Generator (Version %d.%d.%d%s)\n", VERSION, RELEASE, MODIFICATION, PATCH); fprintf (stderr, "Copyright %s %s\n", TPC, C_DATES); load_dists (); /* have to do this after init */ tdefs[NATION].base = nations.count; tdefs[REGION].base = regions.count; /* * updates are never parallelized */ if (updates) { for (i = LINE; i <= ORDER_LINE; i++) { if (table & (1 << i)) { if (load_state (scale, children, children)) { fprintf (stderr, "Unable to load seeds (%d)\n", scale); exit (-1); } rowcnt = tdefs[i].base / 10000 * scale * refresh; upd_num = 0; while (upd_num < updates) { minrow = rowcnt * upd_num + 1; if (verbose) fprintf (stderr, "Generating updates for %s [pid: %d]", tdefs[i].comment, DSS_PROC); gen_tbl (i, minrow, rowcnt, upd_num + 1); if (verbose) fprintf (stderr, "done.\n"); pr_drange (i, minrow, rowcnt, upd_num + 1); upd_num++; } } } exit (0); } /* * seed gen is never parallelized */ if (bld_seeds) gen_seeds ((resume == -1) ? 1 : resume, scale); /** ** actual data generation section starts here **/ /* * open database connection or set all the file names, as appropriate */ if (direct) prep_direct ((db_name) ? db_name : DBNAME); else if (fnames) for (i = PART; i <= REGION; i++) { if (table & (1 << i)) if (set_files (i, -1)) { fprintf (stderr, "Load aborted!\n"); exit (1); } } for (i = PART; i <= REGION; i++) if (table & (1 << i)) { if (children > 1 && i < TIME) if (step >= 0) partial (i, step); #ifdef DOS else { fprintf (stderr, "Parallel load is not supported on your platform.\n"); exit (1); } #else else pload (i); #endif /* DOS */ else { minrow = 1; if (i < TIME) rowcnt = tdefs[i].base * scale; else rowcnt = tdefs[i].base; if (verbose) fprintf (stderr, "Generating data for %s [pid: %d]", tdefs[i].comment, DSS_PROC); gen_tbl (i, minrow, rowcnt, upd_num); if (verbose) fprintf (stderr, "done.\n"); } } if (direct) close_direct (); return (0); }