// Return the specified queue of the specified input group. static InputQueue & queue(int igroup_id, InputQueueName qn) { InputGroup *ig = igroup(igroup_id); if (!ig) throw Exception("input group "+StringUtility::numberToString(igroup_id)+" does not exist"); return ig->queue(qn); }
int main(int argc, char *argv[]) { std::ios::sync_with_stdio(); argv0 = argv[0]; { size_t slash = argv0.rfind('/'); argv0 = slash==std::string::npos ? argv0 : argv0.substr(slash+1); if (0==argv0.substr(0, 3).compare("lt-")) argv0 = argv0.substr(3); } // Parse switches Switches opt; int argno = 1, ngenerators = 0; for (/*void*/; argno<argc && '-'==argv[argno][0]; ++argno) { if (!strcmp(argv[argno], "--")) { ++argno; break; } else if (!strcmp(argv[argno], "--help") || !strcmp(argv[argno], "-h")) { usage(0); } else if (!strncmp(argv[argno], "--ngroups=", 10)) { opt.ngroups = strtoul(argv[argno]+10, NULL, 0); opt.ngroups_set = true; } else if (!strcmp(argv[argno], "--collection")) { opt.single_collection = true; } else if (!strncmp(argv[argno], "--collection=", 13)) { opt.collection_id = strtoul(argv[argno]+13, NULL, 0); opt.collection_id_set = opt.single_collection = true; } else if (!strncmp(argv[argno], "--default=", 10)) { opt.default_queue = parse_queuename(argv[argno]+10); } else if (!strcmp(argv[argno], "--memhash") || !strncmp(argv[argno], "--memhash=", 10)) { std::string s; if (char *equal = strchr(argv[argno], '=')) s = equal+1; std::vector<std::string> valargs = StringUtility::split(',', s, 3); valargs.resize(3); if (valargs[0].empty()) valargs[0] = "0"; if (valargs[1].empty()) valargs[1] = "255"; std::vector<std::string> randargs(1, "1"); randargs.push_back(valargs[2]); valargs.pop_back(); opt.queue_modifiers.push_back(new ValuesGenerator(IQ_MEMHASH, valargs)); opt.queue_modifiers.push_back(new RandomGenerator(IQ_MEMHASH, randargs)); ++ngenerators; } else { std::cerr <<argv0 <<": unrecognized switch: " <<argv[argno] <<"\n" <<"see \"" <<argv0 <<" --help\" for usage info.\n"; exit(1); } } if (!opt.ngroups_set) { std::cerr <<argv0 <<": missing --ngroups switch\n" <<argv0 <<": see --help for more info\n"; exit(1); } // Parse non-switch arguments (allow the database connection string to appear anywhere in this list since simplifies // the run-analysis.sh script. for (/*void*/; argno<argc; argno++) { std::vector<std::string> colon_parts = StringUtility::split(':', argv[argno], 2); InputQueueName qn = parse_queuename(colon_parts[0]); if (IQ_NONE!=qn && 2==colon_parts.size()) { std::vector<std::string> equal_parts = StringUtility::split('=', colon_parts[1], 2); std::string gname = equal_parts[0]; std::vector<std::string> args; try { if (2==equal_parts.size()) args = StringUtility::split(',', equal_parts[1], (size_t)-1, true); if (0==gname.compare("values")) { opt.queue_modifiers.push_back(new ValuesGenerator(qn, args)); } else if (0==gname.compare("set") || 0==gname.compare("reset")) { opt.queue_modifiers.push_back(new ResetGenerator(qn, args)); } else if (0==gname.compare("pad")) { opt.queue_modifiers.push_back(new PaddingGenerator(qn, args)); ++ngenerators; } else if (0==gname.compare("random")) { opt.queue_modifiers.push_back(new RandomGenerator(qn, args)); ++ngenerators; } else if (0==gname.compare("copy")) { opt.queue_modifiers.push_back(new CopyGenerator(qn, args)); ++ngenerators; } else if (0==gname.compare("permute")) { opt.queue_modifiers.push_back(new PermuteFilter(qn, args)); } else if (0==gname.compare("shuffle")) { opt.queue_modifiers.push_back(new ShuffleFilter(qn, args)); } else if (0==gname.compare("redirect")) { opt.queue_modifiers.push_back(new RedirectFilter(qn, args)); } else { std::cerr <<argv0 <<": unknown generator or filter name: " <<gname <<"\n"; exit(1); } } catch (const Exception &e) { std::cerr <<argv0 <<": " <<argv[argno] <<": " <<e <<"\n"; exit(1); } } else if (transaction==NULL) { transaction = SqlDatabase::Connection::create(argv[argno])->transaction(); } else { std::cerr <<argv0 <<": unknown generator or filter: " <<argv[argno] <<"\n"; exit(1); } } if (transaction==NULL) { std::cerr <<argv0 <<": missing database URL\n" <<argv0 <<": see --help for more info\n"; exit(1); } if (opt.queue_modifiers.empty()) { if (opt.ngroups>0) { std::cerr <<argv0 <<": no generators specified; all input groups would be empty\n"; exit(1); } else { exit(0); } } // Get the list of queues that are affected. std::vector<int> queue_modified(IQ_NQUEUES, 0); for (size_t i=0; i<opt.queue_modifiers.size(); ++i) queue_modified[opt.queue_modifiers[i]->queuename] = 1; // Generate the inputs int64_t cmd_id = start_command(transaction, argc, argv, "generating input groups"); int first_id = transaction->statement("select coalesce(max(igroup_id),-1)+1 from semantic_inputvalues")->execute_int(); if (!opt.collection_id_set) opt.collection_id = first_id; Progress progress(opt.ngroups); for (size_t gi=0; gi<opt.ngroups; ++gi) { ++progress; int igroup_id = first_id + gi; InputGroup igroup; igroup.set_collection_id(opt.single_collection ? opt.collection_id : igroup_id); // All queues initialize redirect to the default queue. If any generator or filter is applied, then // we don't do the default redirect. for (size_t qi=0; qi<IQ_NQUEUES; ++qi) { if (!queue_modified[qi]) igroup.queue((InputQueueName)qi).redirect(opt.default_queue); } // Build the queues for (size_t qmi=0; qmi<opt.queue_modifiers.size(); ++qmi) { QueueModifier *qm = opt.queue_modifiers[qmi]; qm->reseed(igroup_id); InputQueue &q = igroup.queue(qm->queuename); qm->operator()(q, igroup_id); } // Save all queues igroup.save(transaction, igroup_id, cmd_id); } progress.clear(); std::string desc = "generated "+StringUtility::numberToString(opt.ngroups)+" input group"+(1==opt.ngroups?"":"s")+ " starting at "+StringUtility::numberToString(first_id); if (opt.ngroups>0) { finish_command(transaction, cmd_id, desc); transaction->commit(); } std::cerr <<argv0 <<": " <<desc <<"\n"; return 0; }