JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwParityDB.cc
Go to the documentation of this file.
1/*!
2 * \file QwParityDB.cc
3 * \brief A class for handling connections to the Qweak database.
4 *
5 * \author Damon Spayde
6 * \date 2010-01-07
7 */
8
9#ifdef __USE_DATABASE__
10#include "QwParityDB.h"
11#include "QwParitySchema.h"
12
13// System headers
14
15// Qweak headers
16#include "QwEventBuffer.h"
17#include "QwRunCondition.h"
18using namespace QwParitySchema;
19
20// Definition of static class members in QwParityDB
21std::map<string, unsigned int> QwParityDB::fMonitorIDs;
22std::map<string, unsigned int> QwParityDB::fMainDetectorIDs;
23std::map<string, unsigned int> QwParityDB::fLumiDetectorIDs;
24std::vector<string> QwParityDB::fMeasurementIDs;
25std::map<string, unsigned int> QwParityDB::fSlowControlDetectorIDs;// for epics
26std::map<string, unsigned char> QwParityDB::fErrorCodeIDs;
27
28// Functor classes for MySQL++ for_each() have been removed
29// They have been replaced with direct sqlpp11 SELECT queries and range-based for loops
30
31
32/*! The simple constructor initializes member fields. This class is not
33 * used to establish the database connection. It sets up a
34 * mysqlpp::Connection() object that has exception throwing disabled.
35 */
36//QwDatabase::QwDatabase() : Connection(false)
37QwParityDB::QwParityDB() : QwDatabase("01", "04", "0000")
38{
39 QwDebug << "Greetings from QwParityDB simple constructor." << QwLog::endl;
40 // Initialize member fields
41
42 fRunNumber = 0;
43 fRunID = 0;
44 fRunletID = 0;
45 fAnalysisID = 0;
46 fSegmentNumber = -1;
47 fDisableAnalysisCheck = false;
48
49}
50
51/*! The constructor initializes member fields using the values in
52 * the QwOptions object.
53 * @param options The QwOptions object.
54 */
55QwParityDB::QwParityDB(QwOptions &options) : QwDatabase(options, "01", "04", "0000")
56{
57 QwDebug << "Greetings from QwParityDB extended constructor." << QwLog::endl;
58
59 // Initialize member fields
60 fRunNumber = 0;
61 fRunID = 0;
62 fRunletID = 0;
63 fAnalysisID = 0;
64 fSegmentNumber = -1;
65 fDisableAnalysisCheck = false;
66
67 ProcessAdditionalOptions(options);
68
69}
70
71/*! The destructor says "Good-bye World!"
72 */
73QwParityDB::~QwParityDB()
74{
75 QwDebug << "QwParityDB::~QwParityDB() : Good-bye World from QwParityDB destructor!" << QwLog::endl;
76 if( Connected() ) Disconnect();
77}
78
79/*!
80 * Sets run number for subsequent database interactions. Makes sure correct
81 * entry exists in run table and retrieves run_id.
82 */
83void QwParityDB::SetupOneRun(QwEventBuffer& qwevt)
84{
85 if (this->AllowsReadAccess()) {
86 UInt_t run_id = this->GetRunID(qwevt);
87 UInt_t runlet_id = this->GetRunletID(qwevt);
88 UInt_t analysis_id = this->GetAnalysisID(qwevt);
89
90 // Write from the database
91 QwMessage << "QwParityDB::SetupOneRun::"
92 << " Run Number " << QwColor(Qw::kBoldMagenta) << qwevt.GetRunNumber() << QwColor(Qw::kNormal)
93 << " Run ID " << QwColor(Qw::kBoldMagenta) << run_id << QwColor(Qw::kNormal)
94 << " Runlet ID " << QwColor(Qw::kBoldMagenta) << runlet_id << QwColor(Qw::kNormal)
95 << " Analysis ID " << QwColor(Qw::kBoldMagenta) << analysis_id
97 << QwLog::endl;
98 }
99}
100
101/*!
102 * Sets run number for subsequent database interactions. Makes sure correct
103 * entry exists in run table and retrieves run_id.
104 */
105bool QwParityDB::SetRunNumber(const UInt_t runnum)
106{
107
108 QwDebug << "Made it into QwParityDB::SetRunNumber()" << QwLog::endl;
109
110 try {
111
112 auto c = GetScopedConnection();
113
114 const auto& run = QwParitySchema::run{};
115 auto query = sqlpp::select(sqlpp::all_of(run))
116 .from(run)
117 .where(run.run_number == runnum);
118
119 auto results = QuerySelect(query);
120 size_t result_count = CountResults(results);
121 QwDebug << "Number of rows returned: " << result_count << QwLog::endl;
122
123 if (result_count != 1) {
124 QwError << "Unable to find unique run number " << runnum << " in database." << QwLog::endl;
125 QwError << "Run number query returned " << result_count << "rows." << QwLog::endl;
126 QwError << "Please make sure that the database contains one unique entry for this run." << QwLog::endl;
127 return false;
128 }
129
130 // Access first row from result
131 UInt_t found_run_id = 0;
132 ForFirstResult(results, [&](const auto& row) {
133 found_run_id = row.run_id;
134 });
135 QwDebug << "Run ID = " << found_run_id << QwLog::endl;
136
137 fRunNumber = runnum;
138 fRunID = found_run_id;
139 }
140 catch (const std::exception& er) {
141 QwError << er.what() << QwLog::endl;
142 return false;
143 }
144
145 return true;
146
147}
148
149/*!
150 * This function sets the fRunID for the run being replayed as determined by the QwEventBuffer class.
151 */
152UInt_t QwParityDB::SetRunID(QwEventBuffer& qwevt)
153{
154
155 // Check to see if run is already in database. If so retrieve run ID and exit.
156 try {
157 auto c = GetScopedConnection();
158
159 const auto& run = QwParitySchema::run{};
160 auto query = sqlpp::select(sqlpp::all_of(run))
161 .from(run)
162 .where(run.run_number == qwevt.GetRunNumber());
163 auto results = QuerySelect(query);
164
165 size_t result_count = CountResults(results);
166 UInt_t first_run_id = 0;
167 UInt_t first_run_number = 0;
168 ForFirstResult(results, [&](const auto& row) {
169 first_run_id = row.run_id;
170 first_run_number = row.run_number;
171 });
172
173 QwDebug << "QwParityDB::SetRunID => Number of rows returned: " << result_count << QwLog::endl;
174
175 // If there is more than one run in the DB with the same run number, then there will be trouble later on. Catch and bomb out.
176 if (result_count > 1) {
177 QwError << "Unable to find unique run number " << qwevt.GetRunNumber() << " in database." << QwLog::endl;
178 QwError << "Run number query returned " << result_count << "rows." << QwLog::endl;
179 QwError << "Please make sure that the database contains one unique entry for this run." << QwLog::endl;
180 return 0;
181 }
182
183 // Run already exists in database. Pull run_id and move along.
184 if (result_count == 1) {
185 QwDebug << "QwParityDB::SetRunID => Run ID = " << first_run_id << QwLog::endl;
186
187 fRunNumber = qwevt.GetRunNumber();
188 fRunID = first_run_id;
189 return fRunID;
190 }
191
192 // If we reach here, run is not in database so insert pertinent data and retrieve run ID
193 // Right now this does not insert start/stop times or info on number of events.
194 QwParitySchema::row<QwParitySchema::run> run_row;
195 run_row[run.run_number] = qwevt.GetRunNumber();
196 run_row[run.run_type] = "good"; // qwevt.GetRunType(); RunType is the confused name because we have also a CODA run type.
197 // Convert Unix timestamps to sqlpp11 datetime using chrono time_point
198 // FIXME (wdconinc) verify conversion
199 run_row[run.start_time] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::from_time_t(qwevt.GetStartUnixTime()));
200 run_row[run.end_time] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::from_time_t(qwevt.GetEndUnixTime()));
201 run_row[run.n_mps] = 0;
202 run_row[run.n_qrt] = 0;
203 // Set following quantities to 9999 as "uninitialized value". DTS 8/3/2012
204 run_row[run.slug] = 9999;
205 run_row[run.wien_slug] = 9999;
206 run_row[run.injector_slug] = 9999;
207 run_row[run.comment] = "";
208
209 QwDebug << "QwParityDB::SetRunID() => Executing sqlpp11 run insert" << QwLog::endl;
210 auto insert_id = QueryInsertAndGetId(run_row.insert_into());
211
212 if (insert_id != 0) {
213 fRunNumber = qwevt.GetRunNumber();
214 fRunID = insert_id;
215 }
216 return fRunID;
217 }
218 catch (const std::exception& er) {
219 QwError << er.what() << QwLog::endl;
220 return 0;
221 }
222
223}
224
225/*!
226 * This is a getter for run_id in the run table. Should be used in subsequent queries to retain key relationships between tables.
227 */
228UInt_t QwParityDB::GetRunID(QwEventBuffer& qwevt)
229{
230 // If the stored run number does not agree with the CODA run number
231 // or if fRunID is not set, then retrieve data from database and update if necessary.
232
233 // GetRunNumber() in QwEventBuffer returns Int_t, thus
234 // we should convert it to UInt_t here. I think, it is OK.
235
236 if (fRunID == 0 || fRunNumber != (UInt_t) qwevt.GetRunNumber() ) {
237 QwDebug << "QwParityDB::GetRunID() set fRunID to " << SetRunID(qwevt) << QwLog::endl;
238 fRunletID = 0;
239 fAnalysisID = 0;
240 }
241
242 return fRunID;
243
244}
245
246/*!
247 * This function sets the fRunletID for the run being replayed as determined by the QwEventBuffer class.
248 *
249 * Runlets are differentiated by file segment number at the moment, not by event range or start/stop time. This function will need to be altered if we opt to differentiate between runlets in a different way.
250 */
251UInt_t QwParityDB::SetRunletID(QwEventBuffer& qwevt)
252{
253
254 // Make sure 'run' table has been populated and retrieve run_id
255 // UInt_t runid = this->GetRunID(qwevt);
256
257 // Check to see if runlet is already in database. If so retrieve runlet_id and exit.
258 try {
259 auto c = GetScopedConnection();
260
261 QwParitySchema::runlet runlet{};
262
263 // Query is slightly different if file segments are being chained together for replay or not.
264 if (qwevt.AreRunletsSplit()) {
265 fSegmentNumber = qwevt.GetSegmentNumber();
266 auto query = sqlpp::select(sqlpp::all_of(runlet))
267 .from(runlet)
268 .where(runlet.run_id == fRunID
269 and runlet.full_run == "false"
270 and runlet.segment_number == fSegmentNumber);
271 auto results = QuerySelect(query);
272
273 // Count results and process using helper functions
274 size_t result_count = CountResults(results);
275 UInt_t found_runlet_id = 0;
276 ForFirstResult(results, [&](const auto& row) {
277 found_runlet_id = row.runlet_id;
278 });
279
280 QwDebug << "QwParityDB::SetRunletID => Number of rows returned: " << result_count << QwLog::endl;
281
282 // If there is more than one run in the DB with the same runlet number, then there will be trouble later on.
283 if (result_count > 1) {
284 QwError << "Unable to find unique runlet number " << qwevt.GetRunNumber() << " in database." << QwLog::endl;
285 QwError << "Run number query returned " << result_count << " rows." << QwLog::endl;
286 QwError << "Please make sure that the database contains one unique entry for this run." << QwLog::endl;
287 return 0;
288 }
289
290 // Run already exists in database. Pull runlet_id and move along.
291 if (result_count == 1) {
292 QwDebug << "QwParityDB::SetRunletID => Runlet ID = " << found_runlet_id << QwLog::endl;
293 fRunletID = found_runlet_id;
294 return fRunletID;
295 }
296
297 } else {
298 auto query = sqlpp::select(sqlpp::all_of(runlet))
299 .from(runlet)
300 .where(runlet.run_id == fRunID
301 and runlet.full_run == "true");
302 auto results = QuerySelect(query);
303
304 // Count results and process using helper functions
305 size_t result_count = CountResults(results);
306 UInt_t found_runlet_id = 0;
307 ForFirstResult(results, [&](const auto& row) {
308 found_runlet_id = row.runlet_id;
309 });
310
311 QwDebug << "QwParityDB::SetRunletID => Number of rows returned: " << result_count << QwLog::endl;
312
313 // If there is more than one run in the DB with the same runlet number, then there will be trouble later on.
314 if (result_count > 1) {
315 QwError << "Unable to find unique runlet number " << qwevt.GetRunNumber() << " in database." << QwLog::endl;
316 QwError << "Run number query returned " << result_count << " rows." << QwLog::endl;
317 QwError << "Please make sure that the database contains one unique entry for this run." << QwLog::endl;
318 return 0;
319 }
320
321 // Run already exists in database. Pull runlet_id and move along.
322 if (result_count == 1) {
323 QwDebug << "QwParityDB::SetRunletID => Runlet ID = " << found_runlet_id << QwLog::endl;
324 fRunletID = found_runlet_id;
325 return fRunletID;
326 }
327 }
328
329 // If we reach here, runlet is not in database so insert pertinent data and retrieve run ID
330 // Right now this does not insert start/stop times or info on number of events.
331 QwParitySchema::runlet runlet_table{};
332 QwParitySchema::row<QwParitySchema::runlet> row;
333 row[runlet_table.run_id] = fRunID;
334 row[runlet_table.run_number] = qwevt.GetRunNumber();
335 // Note: start_time and end_time are nullable fields but we need to use proper sqlpp11 null types
336 // row[runlet_table.start_time] = sqlpp::null;
337 // row[runlet_table.end_time] = sqlpp::null;
338 row[runlet_table.first_mps] = 0;
339 row[runlet_table.last_mps] = 0;
340
341 // Handle segment_number based on runlet split condition
342 if (qwevt.AreRunletsSplit()) {
343 row[runlet_table.segment_number] = fSegmentNumber;
344 row[runlet_table.full_run] = "false";
345 QwDebug << "QwParityDB::SetRunletID() => Executing sqlpp11 runlet insert (with segment)" << QwLog::endl;
346 } else {
347 // Note: segment_number is nullable, but row assignment might need special handling for null
348 // For now, use 0 or another default value
349 // row[runlet_table.segment_number] = sqlpp::null;
350 row[runlet_table.full_run] = "true";
351 QwDebug << "QwParityDB::SetRunletID() => Executing sqlpp11 runlet insert (no segment)" << QwLog::endl;
352 }
353
354 auto insert_id = QueryInsertAndGetId(row.insert_into());
355 if (insert_id != 0) {
356 fRunletID = insert_id;
357 }
358 return fRunletID;
359 }
360 catch (const std::exception& er) {
361 QwError << er.what() << QwLog::endl;
362 return 0;
363 }
364
365}
366
367/*!
368 * This is a getter for runlet_id in the runlet table. Should be used in subsequent queries to retain key relationships between tables.
369 */
370UInt_t QwParityDB::GetRunletID(QwEventBuffer& qwevt)
371{
372 // If the stored run number does not agree with the CODA run number
373 // or if fRunID is not set, then retrieve data from database and update if necessary.
374
375 if (fRunletID == 0 || (qwevt.AreRunletsSplit() && fSegmentNumber!=qwevt.GetSegmentNumber()) || fRunNumber != (UInt_t) qwevt.GetRunNumber() ) {
376 QwDebug << "QwParityDB::GetRunletID() set fRunletID to " << SetRunletID(qwevt) << QwLog::endl;
377 fAnalysisID = 0;
378 }
379
380 return fRunletID;
381
382}
383
384/*!
385 * This is used to set the appropriate analysis_id for this run. Must be a valid runlet_id in the runlet table before proceeding. Will insert an entry into the analysis table if necessary.
386 */
387UInt_t QwParityDB::SetAnalysisID(QwEventBuffer& qwevt)
388{
389 // If there is already an analysis_id for this run, then let's bomb out.
390
391 try {
392 auto c = GetScopedConnection();
393
394 const auto& analysis = QwParitySchema::analysis{};
395 auto query = sqlpp::select(analysis.analysis_id)
396 .from(analysis)
397 .where(analysis.beam_mode == "nbm"
398 and analysis.slope_calculation == "off"
399 and analysis.slope_correction == "off"
400 and analysis.runlet_id == this->GetRunletID(qwevt));
401 auto results = QuerySelect(query);
402 size_t result_count = CountResults(results);
403 if (result_count > 0) {
404 QwError << "This runlet has already been analyzed by the engine!" << QwLog::endl;
405 QwError << "The following analysis_id values already exist in the database: ";
406 ForEachResult(results, [&](const auto& row) {
407 QwError << row.analysis_id << " ";
408 });
410
411 if (fDisableAnalysisCheck==false) {
412 QwError << "Analysis of this run will now be terminated." << QwLog::endl;
413 // Note: return statement cannot be used in lambda to return from function
414 } else {
415 QwWarning << "Analysis will continue. A duplicate entry with new analysis_id will be added to the analysis table." << QwLog::endl;
416 }
417 }
418 }
419 catch (const std::exception& er) {
420 QwError << er.what() << QwLog::endl;
421 QwError << "Unable to determine if there are other database entries for this run. Exiting." << QwLog::endl;
422 return 0;
423 }
424
425
426 try {
427
428 QwParitySchema::analysis analysis;
429 QwParitySchema::row<QwParitySchema::analysis> analysis_row;
430
431 analysis_row[analysis.runlet_id] = GetRunletID(qwevt);
432 analysis_row[analysis.seed_id] = 1;
433
434 std::pair<UInt_t, UInt_t> event_range;
435 event_range = qwevt.GetEventRange();
436
437 analysis_row[analysis.time] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
438 analysis_row[analysis.bf_checksum] = "empty"; // we will match this as a real one later
439 analysis_row[analysis.beam_mode] = "nbm"; // we will match this as a real one later
440 analysis_row[analysis.n_mps] = 0; // we will match this as a real one later
441 analysis_row[analysis.n_qrt] = 4; // we will match this as a real one later
442 analysis_row[analysis.first_event] = event_range.first;
443 analysis_row[analysis.last_event] = event_range.second;
444 analysis_row[analysis.segment] = 0; // we will match this as a real one later
445 analysis_row[analysis.slope_calculation] = "off"; // we will match this as a real one later
446 analysis_row[analysis.slope_correction] = "off"; // we will match this as a real one later
447
448 // Analyzer Information Parsing
449 QwRunCondition run_condition(
450 gQwOptions.GetArgc(),
451 gQwOptions.GetArgv(),
452 "run_condition"
453 );
454
455 run_condition.Get()->Print();
456
457 TIter next(run_condition.Get());
458 TObjString *obj_str;
459 TString str_val, str_var;
460 Ssiz_t location;
461
462 // Iterate over each entry in run_condition
463 while ((obj_str = (TObjString *) next())) {
464 QwMessage << obj_str->GetName() << QwLog::endl;
465
466 // Store string contents for parsing
467 str_var = str_val = obj_str->GetString();
468 location = str_val.First(":"); // The first : separates variable from value
469 location = location + 2; // Value text starts two characters after :
470 str_val.Remove(0,location); //str_val stores value to go in DB
471
472 // Decision tree to figure out which variable to store in
473 if (str_var.BeginsWith("ROOT Version")) {
474 analysis_row[analysis.root_version] = str_val;
475 } else if (str_var.BeginsWith("ROOT file creating time")) {
476 analysis_row[analysis.root_file_time] = str_val;
477 } else if (str_var.BeginsWith("ROOT file created on Hostname")) {
478 analysis_row[analysis.root_file_host] = str_val;
479 } else if (str_var.BeginsWith("ROOT file created by the user")) {
480 analysis_row[analysis.root_file_user] = str_val;
481 } else if (str_var.BeginsWith("QwAnalyzer Name")) {
482 analysis_row[analysis.analyzer_name] = str_val;
483 } else if (str_var.BeginsWith("QwAnalyzer Options")) {
484 analysis_row[analysis.analyzer_argv] = str_val;
485 } else if (str_var.BeginsWith("QwAnalyzer SVN Revision")) {
486 analysis_row[analysis.analyzer_svn_rev] = str_val;
487 } else if (str_var.BeginsWith("QwAnalyzer SVN Last Changed Revision")) {
488 analysis_row[analysis.analyzer_svn_lc_rev] = str_val;
489 } else if (str_var.BeginsWith("QwAnalyzer SVN URL")) {
490 analysis_row[analysis.analyzer_svn_url] = str_val;
491 } else if (str_var.BeginsWith("DAQ ROC flags when QwAnalyzer runs")) {
492 analysis_row[analysis.roc_flags] = str_val;
493 } else {
494 }
495 }
496 auto c = GetScopedConnection();
497
498 auto insert_id = QueryInsertAndGetId(analysis_row.insert_into());
499
500 if (insert_id != 0)
501 {
502 fAnalysisID = insert_id;
503 }
504 return fAnalysisID;
505 }
506 catch (const std::exception& er) {
507 QwError << er.what() << QwLog::endl;
508 return 0;
509 }
510
511
512}
513
514void QwParityDB::FillParameterFiles(QwSubsystemArrayParity& subsys){
515 TList* param_file_list = subsys.GetParamFileNameList("mapfiles");
516 try {
517 auto c = GetScopedConnection();
518
519 QwParitySchema::parameter_files parameter_files;
520 QwParitySchema::row<QwParitySchema::parameter_files> parameter_file_row;
521 parameter_file_row[parameter_files.analysis_id] = GetAnalysisID();
522
523 param_file_list->Print();
524 TIter next(param_file_list);
525 TList *pfl_elem;
526 while ((pfl_elem = (TList *) next())) {
527 parameter_file_row[parameter_files.filename] = pfl_elem->GetName();
528 QueryExecute(parameter_file_row.insert_into());
529 }
530 delete param_file_list;
531 }
532 catch (const std::exception& er) {
533 QwError << er.what() << QwLog::endl;
534 delete param_file_list;
535 }
536}
537
538/*!
539 * This is a getter for analysis_id in the analysis table. Required by all queries on cerenkov, beam, etc. tables. Will return 0 if fRunID has not been successfully set. If fAnalysisID is not set, then calls code to insert into analysis table and retrieve analysis_id.
540 */
541UInt_t QwParityDB::GetAnalysisID(QwEventBuffer& qwevt)
542{
543 // Sanity check to make sure not calling this before runlet_id has been retrieved.
544 if (fRunletID == 0) {
545 QwDebug << "QwParityDB::GetAnalysisID() : fRunletID must be set before proceeding. Check to make sure run exists in database." << QwLog::endl;
546 return 0;
547 }
548
549 if (fAnalysisID == 0 || fRunNumber != (UInt_t) qwevt.GetRunNumber()
550 || (qwevt.AreRunletsSplit() && fSegmentNumber!=qwevt.GetSegmentNumber())) {
551 QwDebug << "QwParityDB::GetAnalysisID() set fAnalysisID to " << SetAnalysisID(qwevt) << QwLog::endl;
552 if (fAnalysisID==0) {
553 QwError << "QwParityDB::SetAnalysisID() unable to set valid fAnalysisID for this run. Exiting." <<QwLog::endl;
554 exit(1);
555 }
556 }
557
558 return fAnalysisID;
559}
560
561
562/*
563 * This function retrieves the monitor table key 'monitor_id' for a given beam monitor.
564 */
565UInt_t QwParityDB::GetMonitorID(const string& name, Bool_t zero_id_is_error)
566{
567 if (fMonitorIDs.size() == 0) {
568 StoreMonitorIDs();
569 }
570
571 UInt_t monitor_id = fMonitorIDs[name];
572
573 if (zero_id_is_error && monitor_id==0) {
574 // monitor_id = 6; // only for QwMockDataAnalysis
575 QwError << "QwParityDB::GetMonitorID() => Unable to determine valid ID for beam monitor " << name << QwLog::endl;
576 }
577
578 return monitor_id;
579
580}
581
582/*
583 * Stores monitor table keys in an associative array indexed by monitor name.
584 */
585void QwParityDB::StoreMonitorIDs()
586{
587 try {
588 auto c = GetScopedConnection();
589
590 QwParitySchema::monitor monitor{};
591 auto query = sqlpp::select(sqlpp::all_of(monitor)).from(monitor).where(sqlpp::value(true));
592 QuerySelectForEachResult(query, [&](const auto& row) {
593 QwDebug << "StoreMonitorID: monitor_id = " << row.monitor_id << " quantity = " << row.quantity << QwLog::endl;
594 QwParityDB::fMonitorIDs.insert(std::make_pair(row.quantity, row.monitor_id));
595 });
596 }
597 catch (const std::exception& er) {
598 QwError << er.what() << QwLog::endl;
599 exit(1);
600 }
601 return;
602}
603
604/*
605 * This function retrieves the main_detector table key 'main_detector_id' for a given beam main_detector.
606 */
607UInt_t QwParityDB::GetMainDetectorID(const string& name, Bool_t zero_id_is_error)
608{
609 if (fMainDetectorIDs.size() == 0) {
610 StoreMainDetectorIDs();
611 }
612
613 UInt_t main_detector_id = fMainDetectorIDs[name];
614
615 if (zero_id_is_error && main_detector_id==0) {
616
617 if (fDBInsertMissingKeys) {
618 QwWarning << "Inserting missing variable " << name << " into main_detector table." << QwLog::endl;
619 try {
620 auto c = GetScopedConnection();
621
622 QwParitySchema::main_detector main_detector;
623 QwParitySchema::row<QwParitySchema::main_detector> main_detector_row;
624 main_detector_row[main_detector.quantity] = name;
625 main_detector_row[main_detector.title] = "unknown";
626
627 auto insert_id = QueryInsertAndGetId(main_detector_row.insert_into());
628
629 if (insert_id != 0) {
630 fMainDetectorIDs[name] = insert_id;
631 main_detector_id = insert_id;
632 QwWarning << "Successfully inserted variable " << name << " into main_detector table with ID " << insert_id << QwLog::endl;
633 } else {
634 QwError << "Failed to insert variable " << name << " into main_detector table." << QwLog::endl;
635 }
636 }
637 catch (const std::exception& er) {
638 QwError << er.what() << QwLog::endl;
639 }
640 } else {
641 QwError << "To enable automatic insertion of missing variables, set the option '--QwDatabase.insert-missing-keys'" << QwLog::endl;
642 }
643 }
644
645 return main_detector_id;
646}
647
648
649/*
650 * Stores main_detector table keys in an associative array indexed by main_detector name.
651 */
652void QwParityDB::StoreMainDetectorIDs()
653{
654 try {
655 auto c = GetScopedConnection();
656
657 QwParitySchema::main_detector main_detector{};
658 auto query = sqlpp::select(sqlpp::all_of(main_detector)).from(main_detector).where(sqlpp::value(true));
659 QuerySelectForEachResult(query, [&](const auto& row) {
660 QwDebug << "StoreMainDetectorID: main_detector_id = " << row.main_detector_id << " quantity = " << row.quantity << QwLog::endl;
661 QwParityDB::fMainDetectorIDs.insert(std::make_pair(row.quantity, row.main_detector_id));
662 });
663 }
664 catch (const std::exception& er) {
665 QwError << er.what() << QwLog::endl;
666 exit(1);
667 }
668 return;
669}
670
671
672/*
673 * This function retrieves the slow control detector table key 'sc_detector_id' for a given epics variable.
674 */
675UInt_t QwParityDB::GetSlowControlDetectorID(const string& name)
676{
677 if (fSlowControlDetectorIDs.size() == 0) {
678 StoreSlowControlDetectorIDs();
679 }
680
681 UInt_t sc_detector_id = fSlowControlDetectorIDs[name];
682
683 if (sc_detector_id==0) {
684 QwError << "QwParityDB::GetSlowControlDetectorID() => Unable to determine valid ID for the epics variable " << name << QwLog::endl;
685
686 if (fDBInsertMissingKeys) {
687 QwWarning << "Inserting missing variable " << name << " into sc_detector table." << QwLog::endl;
688 try {
689 auto c = GetScopedConnection();
690
691 QwParitySchema::sc_detector sc_detector;
692 QwParitySchema::row<QwParitySchema::sc_detector> sc_detector_row;
693 sc_detector_row[sc_detector.name] = name;
694 sc_detector_row[sc_detector.units] = "unknown";
695 sc_detector_row[sc_detector.comment] = "unknown";
696
697 auto insert_id = QueryInsertAndGetId(sc_detector_row.insert_into());
698
699 if (insert_id != 0) {
700 fSlowControlDetectorIDs[name] = insert_id;
701 sc_detector_id = insert_id;
702 QwWarning << "Successfully inserted variable " << name << " into sc_detector table with ID " << insert_id << QwLog::endl;
703 } else {
704 QwError << "Failed to insert variable " << name << " into sc_detector table." << QwLog::endl;
705 }
706 }
707 catch (const std::exception& er) {
708 QwError << er.what() << QwLog::endl;
709 }
710 } else {
711 QwError << "To enable automatic insertion of missing variables, set the option '--QwDatabase.insert-missing-keys'" << QwLog::endl;
712 }
713 }
714
715 return sc_detector_id;
716
717}
718
719/*
720 * This function retrieves the error code table key 'error_code_id' for a given error code name.
721 */
722UInt_t QwParityDB::GetErrorCodeID(const string& name)
723{
724 if (fErrorCodeIDs.size() == 0) {
725 StoreErrorCodeIDs();
726 }
727
728 UInt_t error_code_id = fErrorCodeIDs[name];
729
730 if (error_code_id==0) {
731 QwError << "QwParityDB::GetErrorCodeID() => Unable to determine valid ID for the error code " << name << QwLog::endl;
732 }
733
734 return error_code_id;
735
736}
737
738/*
739 * Stores slow control detector table keys in an associative array indexed by slow_controls_data name.
740 */
741void QwParityDB::StoreSlowControlDetectorIDs()
742{
743 try {
744 auto c = GetScopedConnection();
745
746 QwParitySchema::sc_detector sc_detector{};
747 auto query = sqlpp::select(sqlpp::all_of(sc_detector)).from(sc_detector).where(sqlpp::value(true));
748 QuerySelectForEachResult(query, [&](const auto& row) {
749 QwDebug << "StoreSlowControlDetectorID: sc_detector_id = " << row.sc_detector_id << " name = " << row.name << QwLog::endl;
750 QwParityDB::fSlowControlDetectorIDs.insert(std::make_pair(row.name, row.sc_detector_id));
751 });
752 }
753 catch (const std::exception& er) {
754 QwError << er.what() << QwLog::endl;
755 exit(1);
756 }
757 return;
758}
759
760/*
761 * Stores error_code table keys in an associative array indexed by error_code quantity.
762 */
763void QwParityDB::StoreErrorCodeIDs()
764{
765 try {
766 auto c = GetScopedConnection();
767
768 QwParitySchema::error_code error_code{};
769 auto query = sqlpp::select(sqlpp::all_of(error_code)).from(error_code).where(sqlpp::value(true));
770 QuerySelectForEachResult(query, [&](const auto& row) {
771 QwDebug << "StoreErrorCodeID: error_code_id = " << row.error_code_id << " quantity = " << row.quantity << QwLog::endl;
772 QwParityDB::fErrorCodeIDs.insert(std::make_pair(row.quantity, row.error_code_id));
773 });
774 }
775 catch (const std::exception& er) {
776 QwError << er.what() << QwLog::endl;
777 exit(1);
778 }
779 return;
780}
781
782/*
783 * This function retrieves the lumi_detector table key 'lumi_detector_id' for a given beam lumi_detector.
784 */
785UInt_t QwParityDB::GetLumiDetectorID(const string& name, Bool_t zero_id_is_error)
786{
787 if (fLumiDetectorIDs.size() == 0) {
788 StoreLumiDetectorIDs();
789 }
790
791 UInt_t lumi_detector_id = fLumiDetectorIDs[name];
792
793 if (zero_id_is_error && lumi_detector_id==0) {
794 QwError << "QwParityDB::GetLumiDetectorID() => Unable to determine valid ID for beam lumi_detector " << name << QwLog::endl;
795 }
796
797 return lumi_detector_id;
798}
799
800/*
801 * Stores lumi_detector table keys in an associative array indexed by lumi_detector name.
802 */
803void QwParityDB::StoreLumiDetectorIDs()
804{
805 try {
806 auto c = GetScopedConnection();
807
808 QwParitySchema::lumi_detector lumi_detector{};
809 auto query = sqlpp::select(sqlpp::all_of(lumi_detector)).from(lumi_detector).where(sqlpp::value(true));
810 QuerySelectForEachResult(query, [&](const auto& row) {
811 QwDebug << "StoreLumiDetectorID: lumi_detector_id = " << row.lumi_detector_id << " quantity = " << row.quantity << QwLog::endl;
812 QwParityDB::fLumiDetectorIDs.insert(std::make_pair(row.quantity, row.lumi_detector_id));
813 });
814 }
815 catch (const std::exception& er) {
816 QwError << er.what() << QwLog::endl;
817 exit(1);
818 }
819 return;
820}
821
822
823
824
825const string QwParityDB::GetMeasurementID(const Int_t index)
826{
827 if (fMeasurementIDs.size() == 0) {
828 StoreMeasurementIDs();
829 }
830
831 string measurement_type = fMeasurementIDs[index];
832
833 if (measurement_type.empty()) {
834 QwError << "QwParityDB::GetMeasurementID() => Unable to determine valid ID for measurement type with " << index << QwLog::endl;
835 }
836
837 return measurement_type;
838}
839
840void QwParityDB::StoreMeasurementIDs()
841{
842 try {
843 auto c = GetScopedConnection();
844
845 QwParitySchema::measurement_type measurement_type{};
846 auto query = sqlpp::select(sqlpp::all_of(measurement_type)).from(measurement_type).where(sqlpp::value(true));
847 QuerySelectForEachResult(query, [&](const auto& row) {
848 QwDebug << "StoreMeasurementID: measurement_type = " << row.measurement_type_id << QwLog::endl;
849 QwParityDB::fMeasurementIDs.push_back((std::string) row.measurement_type_id);
850 });
851 }
852 catch (const std::exception& er) {
853 QwError << er.what() << QwLog::endl;
854 exit(1);
855 }
856 return;
857}
858
859/*!
860 * Defines configuration options for QwParityDB class using QwOptions
861 * functionality.
862 *
863 * Should apparently by called by QwOptions::DefineOptions() in
864 * QwParityOptions.h
865 */
866void QwParityDB::DefineAdditionalOptions(QwOptions& options)
867{
868 // Specify command line options for use by QwParityDB
869 options.AddOptions("Parity Analyzer Database options")
870 ("QwParityDB.disable-analysis-check",
871 po::value<bool>()->default_bool_value(false),
872 "disable check of pre-existing analysis_id");
873}
874
875/*!
876 * Loads the configuration options for QwParityDB class into this instance of
877 * QwParityDB from the QwOptions object.
878 * @param options Options object
879 */
880void QwParityDB::ProcessAdditionalOptions(QwOptions &options)
881{
882 if (options.GetValue<bool>("QwParityDB.disable-analysis-check"))
883 fDisableAnalysisCheck=true;
884
885 return;
886}
887
888#endif // #ifdef __USE_DATABASE__
#define gQwOptions
Definition QwOptions.h:31
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
#define QwDebug
Predefined log drain for debugging output.
Definition QwLog.h:59
Run condition management and metadata.
Event buffer management for reading and processing CODA data.
@ kBoldMagenta
Definition QwColor.h:79
@ kNormal
Definition QwColor.h:81
A color changing class for the output stream.
Definition QwColor.h:103
A database interface class.
Definition QwDatabase.h:121
Event buffer management for reading and processing CODA data.
time_t GetStartUnixTime()
std::pair< UInt_t, UInt_t > GetEventRange() const
Int_t GetSegmentNumber() const
Return CODA file segment number.
Int_t GetRunNumber() const
Return CODA file run number.
time_t GetEndUnixTime()
Bool_t AreRunletsSplit() const
Return true if file segments are being separated for.
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Command-line and configuration file options processor.
Definition QwOptions.h:141
T GetValue(const std::string &key)
Get a templated value.
Definition QwOptions.h:236
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition QwOptions.h:170
Run condition and quality management.
TList * GetParamFileNameList(TString name) const
Get list of parameter files.
Subsystem array container specialized for parity analysis with asymmetry calculations.