File indexing completed on 2025-01-18 10:17:35
0001
0002
0003
0004
0005 #include "JParameterManager.h"
0006 #include "JANA/JLogger.h"
0007
0008 #include <sstream>
0009 #include <vector>
0010 #include <string>
0011 #include <fstream>
0012 #include <cstring>
0013 #include <JANA/Utils/JTablePrinter.h>
0014
0015 using namespace std;
0016
0017
0018
0019 JParameterManager::JParameterManager() {
0020 SetLoggerName("jana");
0021 }
0022
0023
0024
0025 JParameterManager::JParameterManager(const JParameterManager& other) {
0026
0027 m_logger = other.m_logger;
0028
0029 for (const auto& param : other.m_parameters) {
0030 m_parameters.insert({param.first, new JParameter(*param.second)});
0031 }
0032 }
0033
0034
0035
0036 JParameterManager::~JParameterManager() {
0037 for (const auto& p : m_parameters) delete p.second;
0038 m_parameters.clear();
0039 }
0040
0041
0042
0043
0044
0045
0046
0047 std::string JParameterManager::ToLower(const std::string& name) {
0048 std::string tmp(name);
0049 std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
0050 return tmp;
0051 }
0052
0053
0054
0055
0056
0057
0058 bool JParameterManager::Exists(string name) {
0059 return m_parameters.find(ToLower(name)) != m_parameters.end();
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069 JParameter* JParameterManager::FindParameter(std::string name) {
0070 auto result = m_parameters.find(ToLower(name));
0071 if (result == m_parameters.end()) {
0072 return nullptr;
0073 }
0074 return result->second;
0075 }
0076
0077 void JParameterManager::PrintParameters() {
0078
0079
0080
0081 SetDefaultParameter("jana:parameter_verbosity", m_verbosity, "0: Don't show parameters table\n"
0082 "1: Show user-provided parameters only\n"
0083 "2: Show defaulted parameters\n"
0084 "3: Show defaulted advanced parameters");
0085
0086 SetDefaultParameter("jana:parameter_strictness", m_strictness, "0: Ignore unused parameters\n"
0087 "1: Warn on unused parameters\n"
0088 "2: Throw on unused parameters");
0089
0090 if ((m_verbosity < 0) || (m_verbosity > 3)) throw JException("jana:parameter_verbosity: Bad parameter value!");
0091 if ((m_strictness < 0) || (m_strictness > 2)) throw JException("jana:parameter_strictness: Bad parameter value!");
0092
0093 PrintParameters(m_verbosity, m_strictness);
0094 }
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 void JParameterManager::PrintParameters(int verbosity, int strictness) {
0108
0109 bool strictness_violation = false;
0110
0111
0112
0113 for (auto& pair : m_parameters) {
0114 const auto& key = pair.first;
0115 auto param = pair.second;
0116
0117 if ((strictness > 0) && (!param->IsDefault()) && (!param->IsUsed())) {
0118 strictness_violation = true;
0119 LOG_ERROR(m_logger) << "Parameter '" << key << "' appears to be unused. Possible typo?" << LOG_END;
0120 }
0121 if ((!param->IsDefault()) && (param->IsDeprecated())) {
0122 LOG_ERROR(m_logger) << "Parameter '" << key << "' has been deprecated and may no longer be supported in future releases." << LOG_END;
0123 }
0124 }
0125
0126 if (strictness_violation) {
0127 LOG_WARN(m_logger) << "Printing parameter table with full verbosity due to strictness warning" << LOG_END;
0128 verbosity = 3;
0129 }
0130
0131 if (verbosity == 0) {
0132 LOG_INFO(m_logger) << "Configuration parameters table hidden. Set jana:parameter_verbosity > 0 to view." << LOG_END;
0133 return;
0134 }
0135
0136
0137 vector<JParameter*> params_to_print;
0138
0139 for (auto& pair : m_parameters) {
0140 auto param = pair.second;
0141
0142 if (param->IsDeprecated() && (param->IsDefault())) continue;
0143
0144
0145 if ((verbosity == 1) && (param->IsDefault())) continue;
0146
0147
0148 if ((verbosity == 2) && (param->IsDefault()) && (param->IsAdvanced())) continue;
0149
0150
0151 params_to_print.push_back(param);
0152 }
0153
0154
0155 if (params_to_print.empty()) {
0156 LOG_INFO(m_logger) << "All configuration parameters set to default values." << LOG_END;
0157 return;
0158 }
0159
0160 LOG_WARN(m_logger) << "Configuration Parameters" << LOG_END;
0161 for (JParameter* p: params_to_print) {
0162
0163 LOG_WARN(m_logger) << LOG_END;
0164 LOG_WARN(m_logger) << " - key: " << p->GetKey() << LOG_END;
0165 if (!p->IsDefault()) {
0166 LOG_WARN(m_logger) << " value: " << p->GetValue() << LOG_END;
0167 }
0168 if (p->HasDefault()) {
0169 LOG_WARN(m_logger) << " default: " << p->GetDefault() << LOG_END;
0170 }
0171 if (!p->GetDescription().empty()) {
0172 std::istringstream iss(p->GetDescription());
0173 std::string line;
0174 bool is_first_line = true;
0175 while (std::getline(iss, line)) {
0176 if (is_first_line) {
0177 LOG_INFO(m_logger) << " description: " << line << LOG_END;
0178 }
0179 else {
0180 LOG_INFO(m_logger) << " " << line << LOG_END;
0181 }
0182 is_first_line = false;
0183 }
0184 }
0185 if (p->IsConflicted()) {
0186 LOG_WARN(m_logger) << " warning: Conflicting defaults" << LOG_END;
0187 }
0188 if (p->IsDeprecated()) {
0189 LOG_WARN(m_logger) << " warning: Deprecated" << LOG_END;
0190
0191 }
0192 if (!p->IsUsed()) {
0193
0194
0195 LOG_WARN(m_logger) << " warning: Unused" << LOG_END;
0196 }
0197 if (p->IsAdvanced()) {
0198 LOG_WARN(m_logger) << " warning: Advanced" << LOG_END;
0199 }
0200 }
0201 LOG_WARN(m_logger) << LOG_END;
0202
0203
0204 if (strictness_violation && strictness > 1) {
0205 throw JException("Unrecognized parameters found! Throwing an exception because jana:parameter_strictness=2. See full parameters table in log.");
0206 }
0207 }
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217 std::map<std::string, JParameter*> JParameterManager::GetAllParameters() {
0218 return m_parameters;
0219 }
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 void JParameterManager::ReadConfigFile(std::string filename) {
0241
0242
0243 ifstream ifs(filename);
0244
0245 if (!ifs.is_open()) {
0246 LOG_ERROR(m_logger) << "Unable to open configuration file \"" << filename << "\" !" << LOG_END;
0247 throw JException("Unable to open configuration file");
0248 }
0249
0250
0251 char line[8192];
0252 while (!ifs.eof()) {
0253
0254 bzero(line, 8192);
0255 ifs.getline(line, 8190);
0256 if (strlen(line) == 0) continue;
0257 if (line[0] == '#') continue;
0258 string str(line);
0259
0260
0261 size_t comment_pos = str.find('#');
0262 if (comment_pos != string::npos) {
0263
0264
0265
0266
0267 if (comment_pos > 0 && str[comment_pos - 1] == ' ')comment_pos--;
0268
0269 str.erase(comment_pos);
0270 }
0271
0272
0273 vector<string> tokens;
0274 string buf;
0275 stringstream ss(str);
0276 while (ss >> buf)tokens.push_back(buf);
0277 if (tokens.size() < 1)continue;
0278
0279
0280 string key = tokens[0];
0281
0282
0283 string val = "";
0284 for (unsigned int i = 1; i < tokens.size(); i++) {
0285 if (i != 1)val += " ";
0286 val += tokens[i];
0287 }
0288 if (val == "")val = "1";
0289
0290
0291 JParameter* param = FindParameter(key);
0292 if (param == nullptr || param->HasDefault()) {
0293 SetParameter(key, val);
0294 }
0295 }
0296
0297
0298 ifs.close();
0299 }
0300
0301
0302
0303
0304
0305
0306
0307
0308 void JParameterManager::WriteConfigFile(std::string filename) {
0309
0310
0311 ofstream ofs(filename);
0312 if (!ofs.is_open()) {
0313 LOG_ERROR(m_logger) << "Unable to open configuration file \"" << filename << "\" for writing!" << LOG_END;
0314 throw JException("Unable to open configuration file for writing!");
0315 }
0316
0317
0318 time_t t = time(NULL);
0319 string timestr(ctime(&t));
0320 ofs << "#" << endl;
0321 ofs << "# JANA configuration parameters" << endl;
0322 ofs << "# Created " << timestr;
0323 ofs << "#" << endl;
0324 ofs << endl;
0325
0326
0327
0328
0329
0330 size_t max_key_len = 0;
0331 size_t max_val_len = 0;
0332 for (auto pair : m_parameters) {
0333 auto key_len = pair.first.length();
0334 auto val_len = pair.second->GetValue().length();
0335 if (key_len > max_key_len) max_key_len = key_len;
0336 if (val_len > max_val_len) max_val_len = val_len;
0337 }
0338
0339
0340 for (auto pair : m_parameters) {
0341 std::string key = pair.first;
0342 std::string val = pair.second->GetValue();
0343 std::string desc = pair.second->GetDescription();
0344
0345 ofs << key << string(max_key_len - key.length(), ' ') << " "
0346 << val << string(max_val_len - val.length(), ' ') << " # "
0347 << desc << std::endl;
0348 }
0349
0350
0351
0352 ofs.close();
0353 }
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 void JParameterManager::FilterParameters(std::map<std::string, std::string> &parms, std::string filter) {
0368
0369 parms.clear();
0370 std::lock_guard<std::mutex> lock(m_mutex);
0371 for (auto pair : m_parameters) {
0372 string key = pair.second->GetKey();
0373 string value = pair.second->GetValue();
0374 if (filter.size() > 0) {
0375 if (key.substr(0, filter.size()) != filter) continue;
0376 key.erase(0, filter.size());
0377 }
0378 pair.second->SetIsUsed(true);
0379 parms[key] = value;
0380 }
0381 }
0382
0383 JLogger JParameterManager::GetLogger(const std::string& component_prefix) {
0384
0385 JLogger logger;
0386 logger.group = component_prefix;
0387
0388 auto global_log_level = RegisterParameter("jana:global_loglevel", JLogger::Level::INFO, "Global log level");
0389
0390 bool enable_timestamp = RegisterParameter("jana:log:show_timestamp", true, "Show timestamp in log output");
0391 auto enable_threadstamp = RegisterParameter("jana:log:show_threadstamp", false, "Show threadstamp in log output");
0392 auto enable_group = RegisterParameter("jana:log:show_group", false, "Show threadstamp in log output");
0393 auto enable_level = RegisterParameter("jana:log:show_level", true, "Show threadstamp in log output");
0394
0395 if (component_prefix.empty()) {
0396 logger.level = global_log_level;
0397 }
0398 else {
0399 std::ostringstream os;
0400 os << component_prefix << ":loglevel";
0401 logger.level = RegisterParameter(os.str(), global_log_level, "Component log level");
0402 }
0403 logger.ShowLevel(enable_level);
0404 logger.ShowTimestamp(enable_timestamp);
0405 logger.ShowThreadstamp(enable_threadstamp);
0406 logger.ShowGroup(enable_group);
0407 logger.show_threadstamp = enable_threadstamp;
0408 return logger;
0409 }
0410
0411