File indexing completed on 2025-01-18 10:17:32
0001
0002
0003
0004
0005 #include "JMain.h"
0006
0007 #include <JANA/CLI/JBenchmarker.h>
0008 #include <JANA/CLI/JSignalHandler.h>
0009
0010
0011 namespace jana {
0012
0013 void PrintUsage() {
0014
0015
0016
0017
0018 std::cout << std::endl;
0019 std::cout << "Usage:" << std::endl;
0020 std::cout << " jana [options] source1 source2 ..." << std::endl << std::endl;
0021
0022 std::cout << "Description:" << std::endl;
0023 std::cout << " Command-line interface for running JANA plugins. This can be used to" << std::endl;
0024 std::cout << " read in events and process them. Command-line flags control configuration" << std::endl;
0025 std::cout << " while additional arguments denote input files, which are to be loaded and" << std::endl;
0026 std::cout << " processed by the appropriate EventSource plugin." << std::endl << std::endl;
0027
0028 std::cout << "Options:" << std::endl;
0029 std::cout << " -h --help Display this message" << std::endl;
0030 PrintUsageOptions();
0031 std::cout << "Example:" << std::endl;
0032 std::cout << " jana -Pplugins=plugin1,plugin2,plugin3 -Pnthreads=8 inputfile1.txt" << std::endl << std::endl;
0033
0034 }
0035
0036 void PrintUsageOptions() {
0037 std::cout << " -Pkey=value Specify a configuration parameter" << std::endl << std::endl;
0038 std::cout << " -v --version Display version information" << std::endl;
0039 std::cout << " -c --configs Display configuration parameters" << std::endl;
0040 std::cout << " -l --loadconfigs <file> Load configuration parameters from file" << std::endl;
0041 std::cout << " -d --dumpconfigs <file> Dump configuration parameters to file" << std::endl;
0042 std::cout << " -b --benchmark Run in benchmark mode" << std::endl;
0043 std::cout << " -i --interactive Run in interactive mode" << std::endl;
0044 std::cout << " --inspect-collection <name> Inspect a collection" << std::endl;
0045 std::cout << " --inspect-component <name> Inspect a component" << std::endl;
0046 }
0047
0048
0049 JApplication* CreateJApplication(UserOptions& options) {
0050
0051 auto params = new JParameterManager();
0052 for (auto pair : options.params) {
0053 params->SetParameter(pair.first, pair.second);
0054 }
0055
0056 if (options.flags[LoadConfigs]) {
0057
0058 try {
0059 params->ReadConfigFile(options.load_config_file);
0060 }
0061 catch (JException &e) {
0062 std::cout << "Problem loading config file '" << options.load_config_file << "'. Exiting." << std::endl
0063 << std::endl;
0064 exit(-1);
0065 }
0066 std::cout << "Loaded config file '" << options.load_config_file << "'." << std::endl << std::endl;
0067 }
0068
0069 auto app = new JApplication(params);
0070
0071 for (auto event_src : options.eventSources) {
0072 app->Add(event_src);
0073 }
0074 return app;
0075 }
0076
0077 int Execute(JApplication* app, UserOptions &options) {
0078
0079 JSignalHandler::register_handlers(app);
0080
0081 if (options.flags[ShowConfigs]) {
0082
0083 app->Initialize();
0084 if (options.flags[Benchmark]) {
0085 JBenchmarker benchmarker(app);
0086 }
0087 app->GetJParameterManager()->PrintParameters(2, 1);
0088 }
0089 else if (options.flags[DumpConfigs]) {
0090
0091 app->Initialize();
0092 std::cout << std::endl << "Writing configuration options to file: " << options.dump_config_file
0093 << std::endl;
0094 app->GetJParameterManager()->WriteConfigFile(options.dump_config_file);
0095 }
0096 else if (options.flags[InspectCollection]) {
0097 app->Initialize();
0098 const auto& summary = app->GetComponentSummary();
0099 std::cout << "----------------------------------------------------------" << std::endl;
0100 if (options.collection_query.empty()) {
0101 PrintCollectionTable(std::cout, summary);
0102 }
0103 else {
0104 auto lookup = summary.FindCollections(options.collection_query);
0105 std::cout << "Collection query: '" << options.collection_query << "'" << std::endl;
0106 if (lookup.empty()) {
0107 std::cout << "Collection not found!" << std::endl;
0108 }
0109 else {
0110 std::cout << "----------------------------------------------------------" << std::endl;
0111 for (auto* item : lookup) {
0112 std::cout << *item;
0113 std::cout << "----------------------------------------------------------" << std::endl;
0114 }
0115 }
0116 }
0117 }
0118 else if (options.flags[InspectComponent]) {
0119 app->Initialize();
0120 const auto& summary = app->GetComponentSummary();
0121 std::cout << "----------------------------------------------------------" << std::endl;
0122 if (options.component_query.empty()) {
0123 PrintComponentTable(std::cout, summary);
0124 }
0125 else {
0126 auto lookup = summary.FindComponents(options.component_query);
0127 std::cout << "Component query: '" << options.component_query << "'" << std::endl;
0128 if (lookup.empty()) {
0129 std::cout << "Component not found!" << std::endl;
0130 }
0131 else {
0132 std::cout << "----------------------------------------------------------" << std::endl;
0133 for (auto* item : lookup) {
0134 std::cout << *item;
0135 std::cout << "----------------------------------------------------------" << std::endl;
0136 }
0137 }
0138 }
0139 }
0140 else if (options.flags[Interactive]) {
0141 app->Initialize();
0142 app->Inspect();
0143
0144
0145
0146
0147 }
0148 else if (options.flags[Benchmark]) {
0149
0150 JBenchmarker benchmarker(app);
0151 benchmarker.RunUntilFinished();
0152 }
0153 else {
0154
0155 try {
0156 app->Run(true, true);
0157 }
0158 catch (JException& e) {
0159 std::cout << "----------------------------------------------------------" << std::endl;
0160 std::cout << e << std::endl;
0161 app->SetExitCode((int) JApplication::ExitCode::UnhandledException);
0162 }
0163 catch (std::exception& e) {
0164 std::cout << "----------------------------------------------------------" << std::endl;
0165 std::cout << "Exception: " << e.what() << std::endl;
0166 app->SetExitCode((int) JApplication::ExitCode::UnhandledException);
0167 }
0168 catch (...) {
0169 std::cout << "----------------------------------------------------------" << std::endl;
0170 std::cout << "Unknown exception" << std::endl;
0171 app->SetExitCode((int) JApplication::ExitCode::UnhandledException);
0172 }
0173 }
0174 return (int) app->GetExitCode();
0175 }
0176
0177
0178 UserOptions ParseCommandLineOptions(int nargs, char *argv[], bool expect_extra) {
0179
0180 UserOptions options;
0181
0182 std::map<std::string, Flag> tokenizer;
0183 tokenizer["-h"] = ShowUsage;
0184 tokenizer["--help"] = ShowUsage;
0185 tokenizer["-v"] = ShowVersion;
0186 tokenizer["--version"] = ShowVersion;
0187 tokenizer["-c"] = ShowConfigs;
0188 tokenizer["--configs"] = ShowConfigs;
0189 tokenizer["-l"] = LoadConfigs;
0190 tokenizer["--loadconfigs"] = LoadConfigs;
0191 tokenizer["-d"] = DumpConfigs;
0192 tokenizer["--dumpconfigs"] = DumpConfigs;
0193 tokenizer["-b"] = Benchmark;
0194 tokenizer["--benchmark"] = Benchmark;
0195 tokenizer["-i"] = Interactive;
0196 tokenizer["--interactive"] = Interactive;
0197 tokenizer["--inspect-collection"] = InspectCollection;
0198 tokenizer["--inspect-component"] = InspectComponent;
0199
0200 if (nargs == 1) {
0201 options.flags[ShowUsage] = true;
0202 }
0203
0204 for (int i = 1; i < nargs; i++) {
0205
0206 std::string arg = argv[i];
0207
0208
0209 if (argv[i][0] != '-') {
0210 options.eventSources.push_back(arg);
0211 continue;
0212 }
0213
0214 switch (tokenizer[arg]) {
0215
0216 case Benchmark:
0217 options.flags[Benchmark] = true;
0218 break;
0219
0220 case ShowUsage:
0221 options.flags[ShowUsage] = true;
0222 break;
0223
0224 case ShowVersion:
0225 options.flags[ShowVersion] = true;
0226 break;
0227
0228 case ShowConfigs:
0229 options.flags[ShowConfigs] = true;
0230 break;
0231
0232 case LoadConfigs:
0233 options.flags[LoadConfigs] = true;
0234 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0235 options.load_config_file = argv[i + 1];
0236 i += 1;
0237 } else {
0238 options.load_config_file = "jana.config";
0239 }
0240 break;
0241
0242 case DumpConfigs:
0243 options.flags[DumpConfigs] = true;
0244 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0245 options.dump_config_file = argv[i + 1];
0246 i += 1;
0247 } else {
0248 options.dump_config_file = "jana.config";
0249 }
0250 break;
0251
0252 case InspectCollection:
0253 options.flags[InspectCollection] = true;
0254 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0255 options.collection_query = argv[i + 1];
0256 i += 1;
0257 }
0258 break;
0259
0260 case InspectComponent:
0261 options.flags[InspectComponent] = true;
0262 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0263 options.component_query = argv[i + 1];
0264 i += 1;
0265 }
0266 break;
0267
0268 case Interactive:
0269 options.flags[Interactive] = true;
0270 break;
0271
0272 case Unknown:
0273 if (argv[i][0] == '-' && argv[i][1] == 'P') {
0274
0275 size_t pos = arg.find("=");
0276 if ((pos != std::string::npos) && (pos > 2)) {
0277 std::string key = arg.substr(2, pos - 2);
0278 std::string val = arg.substr(pos + 1);
0279 options.params.insert({key, val});
0280 } else {
0281 std::cout << "Invalid JANA parameter '" << arg
0282 << "': Expected format -Pkey=value" << std::endl;
0283 options.flags[ShowConfigs] = true;
0284 }
0285 } else {
0286 if (!expect_extra) {
0287 std::cout << "Invalid command line flag '" << arg << "'" << std::endl;
0288 options.flags[ShowUsage] = true;
0289 }
0290 }
0291 }
0292 }
0293 return options;
0294 }
0295 }