File indexing completed on 2025-07-05 09:14:46
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 << " --inspect-collection <name> Inspect a collection" << std::endl;
0044 std::cout << " --inspect-component <name> Inspect a component" << std::endl;
0045 }
0046
0047
0048 JApplication* CreateJApplication(UserOptions& options) {
0049
0050 auto params = new JParameterManager();
0051 for (auto pair : options.params) {
0052 params->SetParameter(pair.first, pair.second);
0053 }
0054
0055 if (options.flags[LoadConfigs]) {
0056
0057 try {
0058 params->ReadConfigFile(options.load_config_file);
0059 }
0060 catch (JException &e) {
0061 std::cout << "Problem loading config file '" << options.load_config_file << "'. Exiting." << std::endl
0062 << std::endl;
0063 exit(-1);
0064 }
0065 std::cout << "Loaded config file '" << options.load_config_file << "'." << std::endl << std::endl;
0066 }
0067
0068 auto app = new JApplication(params);
0069
0070 for (auto event_src : options.eventSources) {
0071 app->Add(event_src);
0072 }
0073 return app;
0074 }
0075
0076 int Execute(JApplication* app, UserOptions &options) {
0077
0078 JSignalHandler::register_handlers(app);
0079
0080 if (options.flags[ShowConfigs]) {
0081
0082 app->Initialize();
0083 if (options.flags[Benchmark]) {
0084 JBenchmarker benchmarker(app);
0085 }
0086 app->GetJParameterManager()->PrintParameters(2, 1);
0087 }
0088 else if (options.flags[DumpConfigs]) {
0089
0090 app->Initialize();
0091 std::cout << std::endl << "Writing configuration options to file: " << options.dump_config_file
0092 << std::endl;
0093 app->GetJParameterManager()->WriteConfigFile(options.dump_config_file);
0094 }
0095 else if (options.flags[InspectCollection]) {
0096 app->Initialize();
0097 const auto& summary = app->GetComponentSummary();
0098 std::cout << "----------------------------------------------------------" << std::endl;
0099 if (options.collection_query.empty()) {
0100 PrintCollectionTable(std::cout, summary);
0101 }
0102 else {
0103 auto lookup = summary.FindCollections(options.collection_query);
0104 std::cout << "Collection query: '" << options.collection_query << "'" << std::endl;
0105 if (lookup.empty()) {
0106 std::cout << "Collection not found!" << std::endl;
0107 }
0108 else {
0109 std::cout << "----------------------------------------------------------" << std::endl;
0110 for (auto* item : lookup) {
0111 std::cout << *item;
0112 std::cout << "----------------------------------------------------------" << std::endl;
0113 }
0114 }
0115 }
0116 }
0117 else if (options.flags[InspectComponent]) {
0118 app->Initialize();
0119 const auto& summary = app->GetComponentSummary();
0120 std::cout << "----------------------------------------------------------" << std::endl;
0121 if (options.component_query.empty()) {
0122 PrintComponentTable(std::cout, summary);
0123 }
0124 else {
0125 auto lookup = summary.FindComponents(options.component_query);
0126 std::cout << "Component query: '" << options.component_query << "'" << std::endl;
0127 if (lookup.empty()) {
0128 std::cout << "Component not found!" << std::endl;
0129 }
0130 else {
0131 std::cout << "----------------------------------------------------------" << std::endl;
0132 for (auto* item : lookup) {
0133 std::cout << *item;
0134 std::cout << "----------------------------------------------------------" << std::endl;
0135 }
0136 }
0137 }
0138 }
0139 else if (options.flags[Benchmark]) {
0140
0141 JBenchmarker benchmarker(app);
0142 benchmarker.RunUntilFinished();
0143 }
0144 else {
0145
0146 try {
0147 app->Run(true, true);
0148 }
0149 catch (JException& e) {
0150 std::cout << "----------------------------------------------------------" << std::endl;
0151 std::cout << e << std::endl;
0152 app->SetExitCode((int) JApplication::ExitCode::UnhandledException);
0153 }
0154 catch (std::exception& e) {
0155 std::cout << "----------------------------------------------------------" << std::endl;
0156 std::cout << "Exception: " << e.what() << std::endl;
0157 app->SetExitCode((int) JApplication::ExitCode::UnhandledException);
0158 }
0159 catch (...) {
0160 std::cout << "----------------------------------------------------------" << std::endl;
0161 std::cout << "Unknown exception" << std::endl;
0162 app->SetExitCode((int) JApplication::ExitCode::UnhandledException);
0163 }
0164 }
0165 return (int) app->GetExitCode();
0166 }
0167
0168
0169 UserOptions ParseCommandLineOptions(int nargs, char *argv[], bool expect_extra) {
0170
0171 UserOptions options;
0172
0173 std::map<std::string, Flag> tokenizer;
0174 tokenizer["-h"] = ShowUsage;
0175 tokenizer["--help"] = ShowUsage;
0176 tokenizer["-v"] = ShowVersion;
0177 tokenizer["--version"] = ShowVersion;
0178 tokenizer["-c"] = ShowConfigs;
0179 tokenizer["--configs"] = ShowConfigs;
0180 tokenizer["-l"] = LoadConfigs;
0181 tokenizer["--loadconfigs"] = LoadConfigs;
0182 tokenizer["-d"] = DumpConfigs;
0183 tokenizer["--dumpconfigs"] = DumpConfigs;
0184 tokenizer["-b"] = Benchmark;
0185 tokenizer["--benchmark"] = Benchmark;
0186 tokenizer["--inspect-collection"] = InspectCollection;
0187 tokenizer["--inspect-component"] = InspectComponent;
0188
0189 if (nargs == 1) {
0190 options.flags[ShowUsage] = true;
0191 }
0192
0193 for (int i = 1; i < nargs; i++) {
0194
0195 std::string arg = argv[i];
0196
0197
0198 if (argv[i][0] != '-') {
0199 options.eventSources.push_back(arg);
0200 continue;
0201 }
0202
0203 switch (tokenizer[arg]) {
0204
0205 case Benchmark:
0206 options.flags[Benchmark] = true;
0207 break;
0208
0209 case ShowUsage:
0210 options.flags[ShowUsage] = true;
0211 break;
0212
0213 case ShowVersion:
0214 options.flags[ShowVersion] = true;
0215 break;
0216
0217 case ShowConfigs:
0218 options.flags[ShowConfigs] = true;
0219 break;
0220
0221 case LoadConfigs:
0222 options.flags[LoadConfigs] = true;
0223 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0224 options.load_config_file = argv[i + 1];
0225 i += 1;
0226 } else {
0227 options.load_config_file = "jana.config";
0228 }
0229 break;
0230
0231 case DumpConfigs:
0232 options.flags[DumpConfigs] = true;
0233 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0234 options.dump_config_file = argv[i + 1];
0235 i += 1;
0236 } else {
0237 options.dump_config_file = "jana.config";
0238 }
0239 break;
0240
0241 case InspectCollection:
0242 options.flags[InspectCollection] = true;
0243 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0244 options.collection_query = argv[i + 1];
0245 i += 1;
0246 }
0247 break;
0248
0249 case InspectComponent:
0250 options.flags[InspectComponent] = true;
0251 if (i + 1 < nargs && argv[i + 1][0] != '-') {
0252 options.component_query = argv[i + 1];
0253 i += 1;
0254 }
0255 break;
0256
0257 case Interactive:
0258 options.flags[Interactive] = true;
0259 break;
0260
0261 case Unknown:
0262 if (argv[i][0] == '-' && argv[i][1] == 'P') {
0263
0264 size_t pos = arg.find("=");
0265 if ((pos != std::string::npos) && (pos > 2)) {
0266 std::string key = arg.substr(2, pos - 2);
0267 std::string val = arg.substr(pos + 1);
0268 options.params.insert({key, val});
0269 } else {
0270 std::cout << "Invalid JANA parameter '" << arg
0271 << "': Expected format -Pkey=value" << std::endl;
0272 options.flags[ShowConfigs] = true;
0273 }
0274 } else {
0275 if (!expect_extra) {
0276 std::cout << "Invalid command line flag '" << arg << "'" << std::endl;
0277 options.flags[ShowUsage] = true;
0278 }
0279 }
0280 }
0281 }
0282 return options;
0283 }
0284 }