NamedConfigUtils.cpp
Go to the documentation of this file.
1 #include <DatabaseUtils/DAQConfig/NamedConfigUtils.h>
2 #include <DatabaseUtils/DAQConfig/DBColumnUtils.h>
3 #include <NovaDatabase/Util.h>
4 #include <NovaDAQUtilities/EnvVarCache.h>
5 #include <NovaDAQConventions/DAQConventions.h>
6 
7 #include <boost/lexical_cast.hpp>
8 #include <boost/algorithm/string.hpp>
9 #include <iostream>
10 
11 namespace NOVADB = nova::database;
12 
13 namespace dbutils {
14 namespace daqconfig {
15 
17 DEFAULT_GLOBAL_NAMES_TABLE_FILE("NovaDatabase/tables/DAQConfig/NamedGlobalConfigurations.xml");
19 DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE("NovaDatabase/tables/DAQConfig/NamedSubsystemConfigurations.xml");
21 DEFAULT_DCS_GLOBAL_NAMES_TABLE_FILE("NovaDatabase/tables/DCS/DCSNamedGlobalConfigurations.xml");
23 DEFAULT_DCS_SUBSYSTEM_NAMES_TABLE_FILE("NovaDatabase/tables/DCS/DCSNamedSubsystemConfigurations.xml");
24 
44 
48 
50 
51 const int32_t NamedConfigUtils::COPY_SUCCEEDED = 11;
52 const int32_t NamedConfigUtils::COPY_FAILED = 12;
55 
56 /**
57  * Fetches the database ID for the specified named global configuration.
58  *
59  * NOTE that this method assumes certain column names for the database
60  * table that contains the configuration names. If any of these
61  * assumptions are not valid for the given globalNamesTableFile,
62  * then this method will always return false.
63  *
64  * @param globalNameSpec The specification of the named global
65  * configuration of interest.
66  * @param globalConfigId The database ID of the named configuration
67  * [output parameter].
68  * (If the status returned by this method is false, then the value
69  * returned in this parameter is undefined.)
70  * @param globalNamesTableFile The name of the XML file (with any
71  * needed path information) that contains the definition of the
72  * database table that contains the named configurations.
73  *
74  * @returns true if the lookup of the ID of the specified named
75  * configuration worked, false if not.
76  */
78 getGlobalConfigId(const GlobalNameSpec& globalNameSpec,
79  int64_t& globalConfigId,
80  const std::string& globalNamesTableFile)
81 {
82  boost::shared_ptr<NOVADB::Table> dbt;
83  if (globalNameSpec.isSlowControlsConfiguration() &&
84  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
85  dbt.reset(new NOVADB::Table(DEFAULT_DCS_GLOBAL_NAMES_TABLE_FILE.c_str()));
86  }
87  else {
88  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
89  }
90 
92  dbt->SetDetector(detName);
93  dbt->SetTableType(NOVADB::kDAQTable);
94 
95  std::string dbUser =
96  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
97  if (dbUser.length() > 0) {
98  dbt->SetUser(dbUser);
99  }
100  dbt->GetConnection();
101 
102  NamedConfigSelectionCriteria selections;
103  selections[NAME_COLUMN_NAME] = globalNameSpec.getConfigName();
104  selections[DCMOPMODE_COLUMN_NAME] = globalNameSpec.getDCMOpMode();
105  selections[DETECTORID_COLUMN_NAME] = globalNameSpec.getDetectorId();
106  if (globalNameSpec.hasTimestamp()) {
107  selections[INSERTTIME_COLUMN_NAME] = globalNameSpec.getTimestamp();
108  }
109  if (! globalNameSpec.skipInvalidStateTest()) {
110  selections[ISOBSOLETE_COLUMN_NAME] = "false";
111  selections[ISCHANGING_COLUMN_NAME] = "false";
112  selections[ISCOMPLETE_COLUMN_NAME] = "true";
113  }
114 
115  return _getId(dbt, selections, globalConfigId);
116 }
117 
118 /**
119  * Fetches the database ID for the specified named subsystem configuration.
120  *
121  * NOTE that this method assumes certain column names for the database
122  * table that contains the configuration names. If any of these
123  * assumptions are not valid for the given subsystemNamesTableFile,
124  * then this method will always return false.
125  *
126  * @param subsystemNameSpec The specification of the named subsystem
127  * configuration of interest.
128  * @param subsystemConfigId The database ID of the named configuration
129  * [output parameter].
130  * (If the status returned by this method is false, then the value
131  * returned in this parameter is undefined.)
132  * @param subsystemNamesTableFile The name of the XML file (with any
133  * needed path information) that contains the definition of the
134  * database table that contains the named configurations.
135  *
136  * @returns true if the lookup of the ID of the specified named
137  * configuration worked, false if not.
138  */
140 getSubsystemConfigId(const SubsystemNameSpec& subsystemNameSpec,
141  int64_t& subsystemConfigId,
142  const std::string& subsystemNamesTableFile)
143 {
144  boost::shared_ptr<NOVADB::Table> dbt;
145  if (subsystemNameSpec.isSlowControlsConfiguration() &&
146  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
148  }
149  else {
150  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
151  }
152 
154  dbt->SetDetector(detName);
155  dbt->SetTableType(NOVADB::kDAQTable);
156 
157  std::string dbUser =
158  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
159  if (dbUser.length() > 0) {
160  dbt->SetUser(dbUser);
161  }
162  dbt->GetConnection();
163 
164  NamedConfigSelectionCriteria selections;
165  selections[NAME_COLUMN_NAME] = subsystemNameSpec.getConfigName();
166  selections[DCMOPMODE_COLUMN_NAME] = subsystemNameSpec.getDCMOpMode();
167  selections[DETECTORID_COLUMN_NAME] = subsystemNameSpec.getDetectorId();
168  selections[SUBSYSTEMNAME_COLUMN_NAME]=subsystemNameSpec.getSubsystemName();
169  selections[CONFIGTYPE_COLUMN_NAME] = subsystemNameSpec.getConfigType();
170  if (subsystemNameSpec.hasTimestamp()) {
171  selections[INSERTTIME_COLUMN_NAME] = subsystemNameSpec.getTimestamp();
172  }
173  selections[ISOBSOLETE_COLUMN_NAME] = "false";
174  selections[ISCHANGING_COLUMN_NAME] = "false";
175  selections[ISCOMPLETE_COLUMN_NAME] = "true";
176 
177  return _getId(dbt, selections, subsystemConfigId);
178 }
179 
180 /**
181  * Fetches the full set of database IDs for the specified named
182  * configuration. This includes the input ID
183  * *and* all of the ancestor named configurations.
184  *
185  * The ID of the requested configuration is first in the returned
186  * ID list, followed by its parent then grandparent, etc. If the
187  * requested configuration has no ancestors, then only the ID of
188  * the requested configuration will be added to the ID list.
189  *
190  * NOTE that this method assumes certain column names for the database
191  * table that contains the configuration names. If any of these
192  * assumptions are not valid for the table file that is given (or
193  * inferred), then this method will always return false.
194  *
195  * @param idSpec The ID-based specification of the named configuration
196  * of interest.
197  * @param idList The list of database IDs for the named configuration
198  * and its ancestors [output parameter].
199  * (If the status returned by this method is false, then the
200  * values returned in this parameter are undefined.)
201  * @param tableFile The name of the XML file (with any
202  * needed path information) that contains the definition of the
203  * database table that contains the named configurations.
204  *
205  * @returns true if the lookup of the ID of the specified named
206  * configuration and its ancestors worked, false if not.
207  */
210  std::vector<int64_t>& idList,
211  const std::string& tableFile)
212 {
213  boost::shared_ptr<NOVADB::Table> dbt;
214  if (tableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
215  if (idSpec.isGlobalConfiguration()) {
216  if (idSpec.isDAQConfiguration()) {
217  dbt.reset(new NOVADB::
219  }
220  else { // slow controls
221  dbt.reset(new NOVADB::
223  }
224  }
225  else { // subsystem
226  if (idSpec.isDAQConfiguration()) {
227  dbt.reset(new NOVADB::
229  }
230  else { // slow controls
231  dbt.reset(new NOVADB::
233  }
234  }
235  }
236  else {
237  dbt.reset(new NOVADB::Table(tableFile.c_str()));
238  }
239 
241  dbt->SetDetector(detName);
242  dbt->SetTableType(NOVADB::kDAQTable);
243 
244  std::string dbUser =
245  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
246  if (dbUser.length() > 0) {
247  dbt->SetUser(dbUser);
248  }
249  dbt->GetConnection();
250 
251  idList.push_back(idSpec.getConfigId());
252  uint32_t previousSize = idList.size() - 1;
253 
254  while (idList.size() > previousSize) {
255  previousSize = idList.size();
256  if (! _findNextAncestor(dbt, idList)) {
257  return false;
258  }
259  }
260  return true;
261 }
262 
263 /**
264  * Fetches the full set of database IDs for the specified named
265  * configuration. This includes the ID corresponding to the name
266  * *and* all of the ancestor named configurations.
267  *
268  * The ID of the requested configuration is first in the returned
269  * ID list, followed by its parent then grandparent, etc. If the
270  * requested configuration has no ancestors, then only the ID of
271  * the requested configuration will be added to the ID list.
272  *
273  * NOTE that this method assumes certain column names for the database
274  * table that contains the configuration names. If any of these
275  * assumptions are not valid for the given globalNamesTableFile,
276  * then this method will always return false.
277  *
278  * @param globalNameSpec The specification of the named global
279  * configuration of interest.
280  * @param idList The list of database IDs for the named configuration
281  * and its ancestors [output parameter].
282  * (If the status returned by this method is false, then the
283  * values returned in this parameter are undefined.)
284  * @param globalNamesTableFile The name of the XML file (with any
285  * needed path information) that contains the definition of the
286  * database table that contains the named configurations.
287  *
288  * @returns true if the lookup of the ID of the specified named
289  * configuration and its ancestors worked, false if not.
290  */
293  std::vector<int64_t>& idList,
294  const std::string& globalNamesTableFile)
295 {
296  int64_t globalConfigId;
297 
298  boost::shared_ptr<NOVADB::Table> dbt;
299  if (globalNameSpec.isSlowControlsConfiguration() &&
300  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
301  dbt.reset(new NOVADB::Table(DEFAULT_DCS_GLOBAL_NAMES_TABLE_FILE.c_str()));
302  }
303  else {
304  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
305  }
306 
308  dbt->SetDetector(detName);
309  dbt->SetTableType(NOVADB::kDAQTable);
310 
311  std::string dbUser =
312  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
313  if (dbUser.length() > 0) {
314  dbt->SetUser(dbUser);
315  }
316  dbt->GetConnection();
317 
318  NamedConfigSelectionCriteria selections;
319  selections[NAME_COLUMN_NAME] = globalNameSpec.getConfigName();
320  selections[DCMOPMODE_COLUMN_NAME] = globalNameSpec.getDCMOpMode();
321  selections[DETECTORID_COLUMN_NAME] = globalNameSpec.getDetectorId();
322  if (globalNameSpec.hasTimestamp()) {
323  selections[INSERTTIME_COLUMN_NAME] = globalNameSpec.getTimestamp();
324  }
325  if (! globalNameSpec.skipInvalidStateTest()) {
326  selections[ISOBSOLETE_COLUMN_NAME] = "false";
327  selections[ISCHANGING_COLUMN_NAME] = "false";
328  selections[ISCOMPLETE_COLUMN_NAME] = "true";
329  }
330 
331  if (! _getId(dbt, selections, globalConfigId)) {
332  return false;
333  }
334 
335  idList.push_back(globalConfigId);
336  uint32_t previousSize = idList.size() - 1;
337 
338  while (idList.size() > previousSize) {
339  previousSize = idList.size();
340  if (! _findNextAncestor(dbt, idList)) {
341  return false;
342  }
343  }
344  return true;
345 }
346 
347 /**
348  * Fetches the full set of database IDs for the specified named
349  * configuration. This includes the ID corresponding to the name
350  * *and* all of the ancestor named configurations.
351  *
352  * The ID of the requested configuration is first in the returned
353  * ID list, followed by its parent then grandparent, etc. If the
354  * requested configuration has no ancestors, then only the ID of
355  * the requested configuration will be added to the ID list.
356  *
357  * NOTE that this method assumes certain column names for the database
358  * table that contains the configuration names. If any of these
359  * assumptions are not valid for the given subsystemNamesTableFile,
360  * then this method will always return false.
361  *
362  * @param subsystemNameSpec The specification of the named subsystem
363  * configuration of interest.
364  * @param idList The list of database IDs for the named configuration
365  * and its ancestors [output parameter].
366  * (If the status returned by this method is false, then the
367  * values returned in this parameter are undefined.)
368  * @param subsystemNamesTableFile The name of the XML file (with any
369  * needed path information) that contains the definition of the
370  * database table that contains the named configurations.
371  *
372  * @returns true if the lookup of the ID of the specified named
373  * configuration and its ancestors worked, false if not.
374  */
377  std::vector<int64_t>& idList,
378  const std::string& subsystemNamesTableFile)
379 {
380  int64_t subsystemConfigId;
381 
382  boost::shared_ptr<NOVADB::Table> dbt;
383  if (subsystemNameSpec.isSlowControlsConfiguration() &&
384  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
386  }
387  else {
388  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
389  }
390 
392  dbt->SetDetector(detName);
393  dbt->SetTableType(NOVADB::kDAQTable);
394 
395  std::string dbUser =
396  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
397  if (dbUser.length() > 0) {
398  dbt->SetUser(dbUser);
399  }
400  dbt->GetConnection();
401 
402  NamedConfigSelectionCriteria selections;
403  selections[NAME_COLUMN_NAME] = subsystemNameSpec.getConfigName();
404  selections[DCMOPMODE_COLUMN_NAME] = subsystemNameSpec.getDCMOpMode();
405  selections[DETECTORID_COLUMN_NAME] = subsystemNameSpec.getDetectorId();
406  selections[SUBSYSTEMNAME_COLUMN_NAME]=subsystemNameSpec.getSubsystemName();
407  selections[CONFIGTYPE_COLUMN_NAME] = subsystemNameSpec.getConfigType();
408  if (subsystemNameSpec.hasTimestamp()) {
409  selections[INSERTTIME_COLUMN_NAME] = subsystemNameSpec.getTimestamp();
410  }
411  selections[ISOBSOLETE_COLUMN_NAME] = "false";
412  selections[ISCHANGING_COLUMN_NAME] = "false";
413  selections[ISCOMPLETE_COLUMN_NAME] = "true";
414 
415  if (! _getId(dbt, selections, subsystemConfigId)) {
416  return false;
417  }
418 
419  idList.push_back(subsystemConfigId);
420  uint32_t previousSize = idList.size() - 1;
421 
422  while (idList.size() > previousSize) {
423  previousSize = idList.size();
424  if (! _findNextAncestor(dbt, idList)) {
425  return false;
426  }
427  }
428  return true;
429 }
430 
431 /**
432  * Fetches the database ID for the named subsystem configuration that
433  * matches the input global name specification.
434  *
435  * NOTE that this method assumes certain column names for the database
436  * table that contains the configuration names. If any of these
437  * assumptions are not valid for the given globalNamesTableFile,
438  * then this method will always return false.
439  *
440  * @param globalNameSpec The specification of the named global
441  * configuration of interest.
442  * @param subsystemNameSpec The specification of the subsystem
443  * of interest (only the subsystemName and configType are used).
444  * @param subsystemConfigId The database ID of the named subsystem
445  * configuration [output parameter].
446  * (If the status returned by this method is false, then the value
447  * returned in this parameter is undefined.)
448  * @param globalNamesTableFile The name of the XML file (with any
449  * needed path information) that contains the definition of the
450  * database table that contains the named configurations.
451  * @param subsystemNamesTableFile The name of the XML file (with any
452  * needed path information) that contains the definition of the
453  * database table that contains the named configurations.
454  *
455  * @returns true if the lookup of the ID of the specified named
456  * configuration worked, false if not.
457  */
460  const std::string& subsystemName,
461  const std::string& subsystemConfigType,
462  int64_t& subsystemConfigId,
463  const std::string& globalNamesTableFile,
464  const std::string& subsystemNamesTableFile)
465 {
466  std::vector<int64_t> globalIdList;
467  if (! getGlobalConfigIdAncestry(globalNameSpec, globalIdList,
468  globalNamesTableFile)) {
469  return false;
470  }
471 
472  boost::shared_ptr<NOVADB::Table> dbt;
473  if (globalNameSpec.isSlowControlsConfiguration() &&
474  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
476  }
477  else {
478  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
479  }
481  dbt->SetDetector(detName);
482  dbt->SetTableType(NOVADB::kDAQTable);
483 
484  std::string dbUser =
485  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
486  if (dbUser.length() > 0) {
487  dbt->SetUser(dbUser);
488  }
489  dbt->GetConnection();
490  for (uint32_t cfgIdx = 0; cfgIdx < globalIdList.size(); ++cfgIdx) {
491  dbt->Clear();
492  dbt->SetValidityRange(GLOBALCFGID_COLUMN_NAME, globalIdList[cfgIdx]);
493  dbt->SetValidityRange(SUBSYSTEMNAME_COLUMN_NAME, subsystemName);
494  dbt->SetValidityRange(CONFIGTYPE_COLUMN_NAME, subsystemConfigType);
495  dbt->SetValidityRange(ISOBSOLETE_COLUMN_NAME, false);
496  dbt->SetValidityRange(ISCHANGING_COLUMN_NAME, false);
497  dbt->SetValidityRange(ISCOMPLETE_COLUMN_NAME, true);
498  if (! dbt->LoadFromDB()) {return false;}
499  if (dbt->NRow() == 1) {
500  NOVADB::Row* rowPtr = dbt->GetRow(0);
501  NOVADB::Column* colPtr = rowPtr->Col(ID_COLUMN_NAME);
502  return (colPtr->Get(subsystemConfigId));
503  }
504  }
505 
506  return false;
507 }
508 
511  const std::string& subsystemName,
512  const std::string& subsystemConfigType,
513  int64_t& subsystemConfigId,
514  const std::string& globalNamesTableFile,
515  const std::string& subsystemNamesTableFile)
516 {
517  std::vector<int64_t> globalIdList;
518  if (! getConfigIdAncestry(idSpec, globalIdList, globalNamesTableFile)) {
519  return false;
520  }
521 
522  subsystemConfigId = 0;
523  boost::shared_ptr<NOVADB::Table> dbt;
524  if (idSpec.isSlowControlsConfiguration() &&
525  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
527  }
528  else {
529  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
530  }
531 
533  dbt->SetDetector(detName);
534  dbt->SetTableType(NOVADB::kDAQTable);
535 
536  std::string dbUser =
537  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
538  if (dbUser.length() > 0) {
539  dbt->SetUser(dbUser);
540  }
541  dbt->GetConnection();
542  for (uint32_t cfgIdx = 0; cfgIdx < globalIdList.size(); ++cfgIdx) {
543  dbt->Clear();
544  dbt->SetValidityRange(GLOBALCFGID_COLUMN_NAME, globalIdList[cfgIdx]);
545  dbt->SetValidityRange(SUBSYSTEMNAME_COLUMN_NAME, subsystemName);
546  dbt->SetValidityRange(CONFIGTYPE_COLUMN_NAME, subsystemConfigType);
547  if (! dbt->LoadFromDB()) {return false;}
548  if (dbt->NRow() == 1) {
549  NOVADB::Row* rowPtr = dbt->GetRow(0);
550  NOVADB::Column* colPtr = rowPtr->Col(ID_COLUMN_NAME);
551  if (! colPtr->Get(subsystemConfigId)) {return false;}
552  else {break;}
553  }
554  }
555 
556  return (subsystemConfigId != 0);
557 }
558 
561  const std::string& subsystemName,
562  const std::string& subsystemConfigType,
563  std::vector<int64_t>& idList,
564  const std::string&
565  globalNamesTableFile,
566  const std::string&
567  subsystemNamesTableFile)
568 {
569  std::string gntf = globalNamesTableFile;
570  if (idSpec.isSlowControlsConfiguration() &&
571  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
573  }
574  std::string sntf = subsystemNamesTableFile;
575  if (idSpec.isSlowControlsConfiguration() &&
576  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
578  }
579 
580  std::vector<int64_t> globalIdList;
581  if (! getConfigIdAncestry(idSpec, globalIdList, gntf)) {
582  return false;
583  }
584 
585  int64_t subsystemConfigId = 0;
586  boost::shared_ptr<NOVADB::Table> dbt;
587  dbt.reset(new NOVADB::Table(sntf.c_str()));
588  std::string daqEnv =
589  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
590  dbt->SetDetector(daqEnv);
591  dbt->SetTableType(NOVADB::kDAQTable);
592  std::string dbUser =
593  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
594  if (dbUser.length() > 0) {
595  dbt->SetUser(dbUser);
596  }
597 
599  dbt->SetDetector(detName);
600  dbt->SetTableType(NOVADB::kDAQTable);
601 
602  dbt->GetConnection();
603  for (uint32_t cfgIdx = 0; cfgIdx < globalIdList.size(); ++cfgIdx) {
604  dbt->Clear();
605  dbt->SetValidityRange(GLOBALCFGID_COLUMN_NAME, globalIdList[cfgIdx]);
606  dbt->SetValidityRange(SUBSYSTEMNAME_COLUMN_NAME, subsystemName);
607  dbt->SetValidityRange(CONFIGTYPE_COLUMN_NAME, subsystemConfigType);
608  if (! dbt->LoadFromDB()) {return false;}
609  if (dbt->NRow() == 1) {
610  NOVADB::Row* rowPtr = dbt->GetRow(0);
611  NOVADB::Column* colPtr = rowPtr->Col(ID_COLUMN_NAME);
612  if (! colPtr->Get(subsystemConfigId)) {return false;}
613  else {break;}
614  }
615  }
616  if (subsystemConfigId == 0) {return false;}
617 
618  IDSpec subsystemIdSpec(subsystemConfigId, IDSpec::SUBSYSTEM,
619  (idSpec.isSlowControlsConfiguration() ?
621  return getConfigIdAncestry(subsystemIdSpec, idList, sntf);
622 }
623 
626  std::vector<int64_t>& idList,
627  std::vector<SubsystemNameSpec>&
628  subsystemNameSpecList,
629  const std::string& globalNamesTableFile,
630  const std::string& subsystemNamesTableFile)
631 {
632  std::vector<int64_t> globalIdList;
633  if (! getConfigIdAncestry(idSpec, globalIdList, globalNamesTableFile)) {
634  return false;
635  }
636 
637  boost::shared_ptr<NOVADB::Table> dbt;
638  if (idSpec.isSlowControlsConfiguration() &&
639  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
641  }
642  else {
643  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
644  }
646  dbt->SetDetector(detName);
647  dbt->SetTableType(NOVADB::kDAQTable);
648 
649  std::string dbUser =
650  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
651  if (dbUser.length() > 0) {
652  dbt->SetUser(dbUser);
653  }
654  dbt->GetConnection();
655  for (uint32_t cfgIdx = 0; cfgIdx < globalIdList.size(); ++cfgIdx) {
656  dbt->Clear();
657  dbt->SetValidityRange(GLOBALCFGID_COLUMN_NAME, globalIdList[cfgIdx]);
658  if (dbt->LoadFromDB()) {
659  for (int iRow = 0; iRow < dbt->NRow(); ++iRow) {
660  NOVADB::Row* rowPtr = dbt->GetRow(iRow);
661  NOVADB::Column* colPtr;
662 
663  std::string subsystemName;
664  colPtr = rowPtr->Col(SUBSYSTEMNAME_COLUMN_NAME);
665  if (! colPtr->Get(subsystemName)) {return false;}
666 
667  std::string configType;
668  colPtr = rowPtr->Col(CONFIGTYPE_COLUMN_NAME);
669  if (! colPtr->Get(configType)) {return false;}
670 
671  bool alreadyFound = false;
672  for (uint32_t sdx=0; sdx<subsystemNameSpecList.size(); ++sdx) {
673  if (subsystemName ==
674  subsystemNameSpecList[sdx].getSubsystemName() &&
675  configType ==
676  subsystemNameSpecList[sdx].getConfigType()) {
677  alreadyFound = true;
678  break;
679  }
680  }
681  if (alreadyFound) {continue;}
682 
683  int64_t subsystemConfigId = 0;
684  colPtr = rowPtr->Col(ID_COLUMN_NAME);
685  if (! colPtr->Get(subsystemConfigId)) {return false;}
686 
687  std::string configName;
688  colPtr = rowPtr->Col(NAME_COLUMN_NAME);
689  if (! colPtr->Get(configName)) {return false;}
690 
691  std::string dcmOpMode;
692  colPtr = rowPtr->Col(DCMOPMODE_COLUMN_NAME);
693  if (! colPtr->Get(dcmOpMode)) {return false;}
694 
695  std::string detectorName;
696  colPtr = rowPtr->Col(DETECTORID_COLUMN_NAME);
697  if (! colPtr->Get(detectorName)) {return false;}
698 
699  SubsystemNameSpec tmpNameSpec(configName, dcmOpMode,
700  detectorName, subsystemName,
701  configType);
702  subsystemNameSpecList.push_back(tmpNameSpec);
703  idList.push_back(subsystemConfigId);
704  }
705  }
706  }
707 
708  return true;
709 }
710 
711 std::vector<NamedConfigUtils::NamedConfigDetailsPtr> NamedConfigUtils::
713  const std::string& globalNamesTableFile,
714  const std::string& subsystemNamesTableFile)
715 {
716  std::vector<NamedConfigDetailsPtr> emptyList;
717  std::vector<NamedConfigDetailsPtr> detailsList;
718 
719  std::vector<int64_t> globalIdList;
720  if (! getConfigIdAncestry(idSpec, globalIdList, globalNamesTableFile)) {
721  return emptyList;
722  }
723 
724  boost::shared_ptr<NOVADB::Table> dbt;
725  if (idSpec.isSlowControlsConfiguration() &&
726  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
728  }
729  else {
730  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
731  }
733  dbt->SetDetector(detName);
734  dbt->SetTableType(NOVADB::kDAQTable);
735 
736  std::string dbUser =
737  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
738  if (dbUser.length() > 0) {
739  dbt->SetUser(dbUser);
740  }
741  dbt->GetConnection();
742  for (uint32_t cfgIdx = 0; cfgIdx < globalIdList.size(); ++cfgIdx) {
743  dbt->Clear();
744  dbt->SetValidityRange(GLOBALCFGID_COLUMN_NAME, globalIdList[cfgIdx]);
745  if (! dbt->LoadFromDB()) {
746  return emptyList;
747  }
748  for (int iRow = 0; iRow < dbt->NRow(); ++iRow) {
749  NamedConfigDetailsPtr detailsPtr(new NamedConfigDetails());
750  std::string columnValue;
751  NOVADB::Row* rowPtr = dbt->GetRow(iRow);
752  for (int idx = 0; idx < dbt->NCol(); ++idx) {
753  NOVADB::Column& colRef = rowPtr->Col(idx);
754  if (colRef.IsNull()) {
755  (*detailsPtr)[colRef.Name()] = "";
756  }
757  else if (colRef.Get(columnValue)) {
758  (*detailsPtr)[colRef.Name()] = columnValue;
759  }
760  else {
761  return emptyList;
762  }
763  }
764 
765  bool alreadyFound = false;
766  for (uint32_t ddx = 0; ddx < detailsList.size(); ++ddx) {
767  std::string sname1, sname2, ctype1, ctype2;
768  if (getFieldValue(detailsPtr,
769  SUBSYSTEMNAME_COLUMN_NAME, sname1) &&
770  getFieldValue(detailsList[ddx],
771  SUBSYSTEMNAME_COLUMN_NAME, sname2) &&
772  getFieldValue(detailsPtr,
773  CONFIGTYPE_COLUMN_NAME, ctype1) &&
774  getFieldValue(detailsList[ddx],
775  CONFIGTYPE_COLUMN_NAME, ctype2) &&
776  sname1 == sname2 && ctype1 == ctype2) {
777  alreadyFound = true;
778  break;
779  }
780  }
781  if (! alreadyFound) {
782  detailsList.push_back(detailsPtr);
783  }
784  }
785  }
786 
787  return detailsList;
788 }
789 
792  const std::string& subsystemNamesTableFile,
793  const std::string& globalNamesTableFile)
794 {
795  NamedConfigDetailsPtr detailsPtr;
796 
797  // step 1: look up the subsystem configuration
798  boost::shared_ptr<NOVADB::Table> dbt;
799  if (subsystemNameSpec.isSlowControlsConfiguration() &&
800  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
802  }
803  else {
804  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
805  }
806  std::string daqEnv =
807  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
808  dbt->SetDetector(daqEnv);
809  dbt->SetTableType(NOVADB::kDAQTable);
810  std::string dbUser =
811  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
812  if (dbUser.length() > 0) {
813  dbt->SetUser(dbUser);
814  }
815  dbt->GetConnection();
816 
817  NamedConfigSelectionCriteria selections;
818  selections[NAME_COLUMN_NAME] = subsystemNameSpec.getConfigName();
819  selections[DCMOPMODE_COLUMN_NAME] = subsystemNameSpec.getDCMOpMode();
820  selections[DETECTORID_COLUMN_NAME] = subsystemNameSpec.getDetectorId();
821  selections[SUBSYSTEMNAME_COLUMN_NAME]=subsystemNameSpec.getSubsystemName();
822  selections[CONFIGTYPE_COLUMN_NAME] = subsystemNameSpec.getConfigType();
823  if (subsystemNameSpec.hasTimestamp()) {
824  selections[INSERTTIME_COLUMN_NAME] = subsystemNameSpec.getTimestamp();
825  }
826  selections[ISOBSOLETE_COLUMN_NAME] = "false";
827  selections[ISCHANGING_COLUMN_NAME] = "false";
828  selections[ISCOMPLETE_COLUMN_NAME] = "true";
829 
830  NamedConfigDetailsPtr subsysDetails = _getDetails(dbt, selections);
831 
832  // step 2: pull out the associated global CFG ID
833  int64_t globalCfgId = 0;
834  std::string tmpString;
835  if (! getFieldValue(subsysDetails, GLOBALCFGID_COLUMN_NAME,
836  tmpString)) {return detailsPtr;}
837  try {
838  globalCfgId = boost::lexical_cast<int64_t>(tmpString);
839  }
840  catch (...) {return detailsPtr;}
841 
842  // step 3: fetch the details for the latest global CFG ID
843  IDSpec globalIdSpec(globalCfgId, IDSpec::GLOBAL,
844  (subsystemNameSpec.isSlowControlsConfiguration() ?
846  return getNewestGlobalConfigFromGlobalId(globalIdSpec,
847  globalNamesTableFile);
848 }
849 
852  const std::string& subsystemNamesTableFile,
853  const std::string& globalNamesTableFile)
854 {
855  NamedConfigDetailsPtr detailsPtr;
856 
857  // step 1: look up the subsystem configuration
858  boost::shared_ptr<NOVADB::Table> dbt;
859  if (idSpec.isSlowControlsConfiguration() &&
860  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
861  dbt.reset(new NOVADB::
863  }
864  else {
865  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
866  }
867  std::string daqEnv =
868  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
869  dbt->SetDetector(daqEnv);
870  dbt->SetTableType(NOVADB::kDAQTable);
871  std::string dbUser =
872  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
873  if (dbUser.length() > 0) {
874  dbt->SetUser(dbUser);
875  }
876  dbt->GetConnection();
877 
878  NamedConfigSelectionCriteria selections;
879  selections[ID_COLUMN_NAME] =
880  boost::lexical_cast<std::string>(idSpec.getConfigId());
881 
882  NamedConfigDetailsPtr subsysDetails = _getDetails(dbt, selections);
883 
884  // step 2: pull out the associated global CFG ID
885  int64_t globalCfgId = 0;
886  std::string tmpString;
887  if (! getFieldValue(subsysDetails, GLOBALCFGID_COLUMN_NAME,
888  tmpString)) {return detailsPtr;}
889  try {
890  globalCfgId = boost::lexical_cast<int64_t>(tmpString);
891  }
892  catch (...) {return detailsPtr;}
893 
894  // step 3: fetch the details for the latest global CFG ID
895  IDSpec globalIdSpec(globalCfgId, IDSpec::GLOBAL,
896  (idSpec.isSlowControlsConfiguration() ?
898  return getNewestGlobalConfigFromGlobalId(globalIdSpec,
899  globalNamesTableFile);
900 }
901 
904  const std::string& globalNamesTableFile)
905 {
906  NamedConfigDetailsPtr detailsPtr;
907 
908  // step 1: build the list of child global IDs
909  boost::shared_ptr<NOVADB::Table> dbt;
910  if (idSpec.isSlowControlsConfiguration() &&
911  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
912  dbt.reset(new NOVADB::
914  }
915  else {
916  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
917  }
918  std::string daqEnv =
919  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
920  dbt->SetDetector(daqEnv);
921  dbt->SetTableType(NOVADB::kDAQTable);
922  std::string dbUser =
923  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
924  if (dbUser.length() > 0) {
925  dbt->SetUser(dbUser);
926  }
927  dbt->GetConnection();
928 
929  std::vector<int64_t> globalCfgIdList;
930  globalCfgIdList.push_back(idSpec.getConfigId());
931  uint32_t previousSize = 0;
932 
933  while (globalCfgIdList.size() > previousSize) {
934  previousSize = globalCfgIdList.size();
935  if (! _findNextChild(dbt, globalCfgIdList)) {
936  return detailsPtr;
937  }
938  }
939  int64_t globalCfgId = globalCfgIdList[globalCfgIdList.size()-1];
940 
941  // step 2: fetch the details for the latest global CFG ID
942  NamedConfigSelectionCriteria selections;
943  selections[ID_COLUMN_NAME] = boost::lexical_cast<std::string>(globalCfgId);
944  detailsPtr = _getDetails(dbt, selections);
945 
946  return detailsPtr;
947 }
948 
949 /**
950  * Fetches the details of the most recent global configuration that was
951  * used by the specified partition.
952  *
953  * @returns an empty shared pointer if the lookup fails.
954  */
957  const int& partitionNumber,
958  const std::string& globalNamesTableFile)
959 {
960  GlobalNameSpecPtr nameSpecPtr;
961  boost::shared_ptr<NOVADB::Table> dbt;
962  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
963  std::string daqEnv =
964  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
965  dbt->SetDetector(daqEnv);
966  dbt->SetTableType(NOVADB::kDAQTable);
967  std::string dbUser =
968  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
969  if (dbUser.length() > 0) {
970  dbt->SetUser(dbUser);
971  }
972  else {
973  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("NOVADBUSER");
974  if (dbUser.length() > 0) {
975  dbt->SetUser(dbUser);
976  }
977  }
978  dbt->GetConnection();
979 
980  PGresult* resultSetPtr;
981  std::string queryString="SELECT cfg.name,cfg.dcmopmode,cfg.detectorname ";
982  queryString.append("FROM runs as rr ");
983  queryString.append("JOIN " + dbt->Schema() + "." + dbt->Name() + " as cfg ");
984  queryString.append("ON (rr.configid = cfg.id) ");
985  queryString.append("WHERE rr.partition=");
986  queryString.append(boost::lexical_cast<std::string>(partitionNumber));
987  queryString.append(" AND rr.detector='");
988  queryString.append(detectorName);
989  queryString.append("' ORDER BY rr.run DESC LIMIT 1");
990 
991  resultSetPtr = 0;
992  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
993  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
994  PQclear(resultSetPtr);
995  return nameSpecPtr;
996  }
997 
998  int nRows = PQntuples(resultSetPtr);
999  if (nRows != 1) {
1000  PQclear(resultSetPtr);
1001  return nameSpecPtr;
1002  }
1003 
1004  std::string name1 = PQgetvalue(resultSetPtr, 0, 0);
1005  std::string opmode1 = PQgetvalue(resultSetPtr, 0, 1);
1006  std::string detector1 = PQgetvalue(resultSetPtr, 0, 2);
1007  PQclear(resultSetPtr);
1008 
1009  GlobalNameSpec globalNameSpec(name1, opmode1, detector1);
1010  std::vector<NamedConfigDetailsPtr> detailsList =
1011  getGlobalConfigDetailAncestry(globalNameSpec, globalNamesTableFile);
1012  if (detailsList.size() == 0) {return nameSpecPtr;}
1013 
1014  std::string nameString;
1015  std::string opModeString;
1016  std::string detectorString;
1017  std::string timeString;
1018  if (! getFieldValue(detailsList[0], NAME_COLUMN_NAME, nameString) ||
1019  ! getFieldValue(detailsList[0], DCMOPMODE_COLUMN_NAME, opModeString) ||
1020  ! getFieldValue(detailsList[0], DETECTORNAME_COLUMN_NAME, detectorString) ||
1021  ! getFieldValue(detailsList[0], INSERTTIME_COLUMN_NAME, timeString)) {
1022  return nameSpecPtr;
1023  }
1024  nameSpecPtr.reset(new GlobalNameSpec(nameString, opModeString,
1025  detectorString, timeString));
1026  return nameSpecPtr;
1027 }
1028 
1029 /**
1030  * Fetches a list of recent global configurations for a specific detector.
1031  */
1032 bool NamedConfigUtils::
1034  const std::string& detectorName,
1035  int resultOffset, int resultLimit,
1036  GlobalNameSpecList& resultList,
1037  const std::string& globalNamesTableFile)
1038 {
1039  boost::shared_ptr<NOVADB::Table> dbt;
1040  if (daqOrSlowControls == IDSpec::SLOWCONTROLS &&
1041  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
1042  dbt.reset(new NOVADB::
1044  }
1045  else {
1046  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
1047  }
1048  std::string detName = detectorName;
1049  if (!novadaq::cnv::DetInfo::DetNameOk(detName))
1050  detName = novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
1051  dbt->SetDetector(detName);
1052  dbt->SetTableType(NOVADB::kDAQTable);
1053 
1054  std::string dbUser =
1055  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
1056  if (dbUser.length() > 0) {
1057  dbt->SetUser(dbUser);
1058  }
1059  else {
1060  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("NOVADBUSER");
1061  if (dbUser.length() > 0) {
1062  dbt->SetUser(dbUser);
1063  }
1064  }
1065  dbt->GetConnection();
1066 
1067  dbt->Clear();
1068  // dbt->SetValidityRange(DETECTORNAME_COLUMN_NAME, detectorName);
1069  dbt->SetValidityRange(ISOBSOLETE_COLUMN_NAME, false);
1070  dbt->SetValidityRange(ISCHANGING_COLUMN_NAME, false);
1071  dbt->SetValidityRange(ISCOMPLETE_COLUMN_NAME, true);
1072  dbt->AddOrderColumn(INSERTTIME_COLUMN_NAME);
1073  dbt->SetOrderDesc();
1074  dbt->SetSelectLimit(resultLimit);
1075  dbt->SetSelectOffset(resultOffset);
1076  if (! dbt->LoadFromDB()) {return false;}
1077 
1078  for (int32_t idx = 0; idx < dbt->NRow(); ++idx) {
1079  NOVADB::Row* rowPtr = dbt->GetRow(idx);
1080  NOVADB::Column* colPtr;
1081 
1082  std::string configName;
1083  colPtr = rowPtr->Col(NAME_COLUMN_NAME);
1084  if (! colPtr->Get(configName)) {return false;}
1085 
1086  std::string dcmOpMode;
1087  colPtr = rowPtr->Col(DCMOPMODE_COLUMN_NAME);
1088  if (! colPtr->Get(dcmOpMode)) {return false;}
1089 
1091  colPtr = rowPtr->Col(INSERTTIME_COLUMN_NAME);
1092  if (! colPtr->Get(timestamp)) {return false;}
1093 
1094  GlobalNameSpec nameSpec(configName, dcmOpMode,
1095  detectorName, timestamp);
1096 
1097  resultList.push_back(nameSpec);
1098  }
1099 
1100  return true;
1101 }
1102 
1103 /**
1104  * Fetches a list of the available global configuration names and DCM
1105  * operating modes for a specific detector.
1106  */
1107 bool NamedConfigUtils::
1109  const std::string& detectorName,
1110  GlobalNameSpecMap& resultsTable,
1111  int maxDetailCountPerSummary,
1112  const std::string& globalNamesTableFile)
1113 {
1114  boost::shared_ptr<NOVADB::Table> dbt;
1115  if (daqOrSlowControls == IDSpec::SLOWCONTROLS &&
1116  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
1117  dbt.reset(new NOVADB::
1119  }
1120  else {
1121  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
1122  }
1123  std::string daqEnv =
1124  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
1125  dbt->SetDetector(daqEnv);
1126  dbt->SetTableType(NOVADB::kDAQTable);
1127  std::string dbUser =
1128  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
1129  if (dbUser.length() > 0) {
1130  dbt->SetUser(dbUser);
1131  }
1132  else {
1133  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("NOVADBUSER");
1134  if (dbUser.length() > 0) {
1135  dbt->SetUser(dbUser);
1136  }
1137  }
1138  dbt->GetConnection();
1139 
1140  // Fetch the list of available Name and DCMOpMode combinations,
1141  // for all timestamps and taking into account all usageCounts.
1142  PGresult* resultSetPtr;
1143  std::string queryString = "SELECT ";
1144  queryString.append(NAME_COLUMN_NAME);
1145  queryString.append(", ");
1146  queryString.append(DCMOPMODE_COLUMN_NAME);
1147  queryString.append(", SUM(");
1148  queryString.append(USAGECOUNT_COLUMN_NAME);
1149  queryString.append("), MAX(");
1150  queryString.append(INSERTTIME_COLUMN_NAME);
1151  queryString.append(") FROM ");
1152  queryString.append(dbt->Schema() + "." + dbt->Name());
1153  queryString.append(" WHERE ");
1154  // queryString.append(DETECTORNAME_COLUMN_NAME);
1155  // queryString.append("='");
1156  // queryString.append(detectorName);
1157  // queryString.append("' AND ");
1158  queryString.append(ISOBSOLETE_COLUMN_NAME);
1159  queryString.append("=false AND ");
1160  queryString.append(ISCHANGING_COLUMN_NAME);
1161  queryString.append("=false AND ");
1162  queryString.append(ISCOMPLETE_COLUMN_NAME);
1163  queryString.append("=true GROUP BY ");
1164  queryString.append(NAME_COLUMN_NAME);
1165  queryString.append(", ");
1166  queryString.append(DCMOPMODE_COLUMN_NAME);
1167  queryString.append(" ORDER BY SUM(");
1168  queryString.append(USAGECOUNT_COLUMN_NAME);
1169  queryString.append(") DESC, MAX(");
1170  queryString.append(INSERTTIME_COLUMN_NAME);
1171  queryString.append(") DESC, ");
1172  queryString.append(NAME_COLUMN_NAME);
1173  queryString.append(" ASC");
1174 
1175  resultSetPtr = 0;
1176  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
1177  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
1178  PQclear(resultSetPtr);
1179 
1180  return false;
1181  }
1182  std::vector<GlobalNameSpec> summaryList;
1183  int nRows = PQntuples(resultSetPtr);
1184  if (nRows > 0) {
1185  for (int idx = 0; idx < nRows; ++idx) {
1186  std::string nameString = PQgetvalue(resultSetPtr, idx, 0);
1187  std::string opModeString = PQgetvalue(resultSetPtr, idx, 1);
1188  std::string usageCountString = PQgetvalue(resultSetPtr, idx, 2);
1189  int usageCount = 0;
1190  try {
1191  usageCount = boost::lexical_cast<int>(usageCountString);
1192  }
1193  catch (...) {}
1194 
1195  GlobalNameSpec nameSpec(nameString, opModeString, detectorName);
1196  nameSpec.setUsageCount(usageCount);
1197  nameSpec.setSortIndex(idx);
1198  summaryList.push_back(nameSpec);
1199  }
1200  }
1201  PQclear(resultSetPtr);
1202 
1203  // Fetch the most recent N instances of each name and dcmOpMode.
1204  for (int cfgIdx = 0; cfgIdx < (int) summaryList.size(); ++cfgIdx) {
1205  std::string configName = summaryList[cfgIdx].getConfigName();
1206  std::string dcmOpMode = summaryList[cfgIdx].getDCMOpMode();
1207 
1208  dbt->Clear();
1209  dbt->SetValidityRange(NAME_COLUMN_NAME, configName);
1210  dbt->SetValidityRange(DCMOPMODE_COLUMN_NAME, dcmOpMode);
1211  // dbt->SetValidityRange(DETECTORNAME_COLUMN_NAME, detectorName);
1212  dbt->SetValidityRange(ISOBSOLETE_COLUMN_NAME, false);
1213  dbt->SetValidityRange(ISCHANGING_COLUMN_NAME, false);
1214  dbt->SetValidityRange(ISCOMPLETE_COLUMN_NAME, true);
1215  dbt->AddOrderColumn(INSERTTIME_COLUMN_NAME);
1216  dbt->SetOrderDesc();
1217  dbt->SetSelectLimit(maxDetailCountPerSummary);
1218  if (! dbt->LoadFromDB()) {return false;}
1219 
1220  std::vector<GlobalNameSpec> detailsList;
1221  for (int32_t idx = 0; idx < dbt->NRow(); ++idx) {
1222  NOVADB::Row* rowPtr = dbt->GetRow(idx);
1223  NOVADB::Column* colPtr;
1224 
1226  colPtr = rowPtr->Col(INSERTTIME_COLUMN_NAME);
1227  if (! colPtr->Get(timestamp)) {return false;}
1228 
1229  int usageCount;
1230  colPtr = rowPtr->Col(USAGECOUNT_COLUMN_NAME);
1231  if (colPtr->IsNull()) {usageCount = 0;}
1232  else if (! colPtr->Get(usageCount)) {return false;}
1233 
1234  GlobalNameSpec nameSpec(configName, dcmOpMode,
1235  detectorName, timestamp);
1236  nameSpec.setUsageCount(usageCount);
1237  detailsList.push_back(nameSpec);
1238  }
1239 
1240  resultsTable[summaryList[cfgIdx]] = detailsList;
1241  }
1242 
1243  return true;
1244 }
1245 
1246 /**
1247  * Fetches a list of the available subsystem configuration names and DCM
1248  * operating modes for a specific subsystem, configuration type, and
1249  * detector ID.
1250  *
1251  * NOTE that this method assumes certain column names for the database
1252  * table that contains the configuration names. If any of these
1253  * assumptions are not valid for the given globalNamesTableFile,
1254  * then this method will always return false.
1255  *
1256  * @param subsystemName The name of the subsystem of interest.
1257  * @param configType The configuration type of interest.
1258  * @param detectorName The detector of interest (e.g. NDOS or FarDet).
1259  * @param subsystemConfigList The resulting list of subsystem configurations
1260  * [output parameter].
1261  * (If the status returned by this method is false, then the value
1262  * returned in this parameter is undefined.)
1263  * @param subsystemNamesTableFile The name of the XML file (with any
1264  * needed path information) that contains the definition of the
1265  * database table that contains the named configurations.
1266  *
1267  * @returns true if the lookup of the available subsystem configuration
1268  * names worked, false if not.
1269  */
1270 bool NamedConfigUtils::
1272  const std::string& detectorName,
1273  const std::string& subsystemName,
1274  const std::string& configType,
1275  SubsystemNameSpecMap& resultsTable,
1276  int maxDetailCountPerSummary,
1277  const std::string& subsystemNamesTableFile)
1278 {
1279  boost::shared_ptr<NOVADB::Table> dbt;
1280  if (daqOrSlowControls == IDSpec::SLOWCONTROLS &&
1281  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
1282  dbt.reset(new NOVADB::
1284  }
1285  else {
1286  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
1287  }
1288  std::string daqEnv =
1289  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
1290  dbt->SetDetector(daqEnv);
1291  dbt->SetTableType(NOVADB::kDAQTable);
1292  std::string dbUser =
1293  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
1294  if (dbUser.length() > 0) {
1295  dbt->SetUser(dbUser);
1296  }
1297  else {
1298  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("NOVADBUSER");
1299  if (dbUser.length() > 0) {
1300  dbt->SetUser(dbUser);
1301  }
1302  }
1303  dbt->GetConnection();
1304 
1305  // Fetch the list of available Name and DCMOpMode combinations,
1306  // for all timestamps and taking into account all usageCounts.
1307  PGresult* resultSetPtr;
1308  std::string queryString = "SELECT ";
1309  queryString.append(NAME_COLUMN_NAME);
1310  queryString.append(", ");
1311  queryString.append(DCMOPMODE_COLUMN_NAME);
1312  queryString.append(", SUM(");
1313  queryString.append(USAGECOUNT_COLUMN_NAME);
1314  queryString.append("), MAX(");
1315  queryString.append(INSERTTIME_COLUMN_NAME);
1316  queryString.append(") FROM ");
1317  queryString.append(dbt->Schema() + "." + dbt->Name());
1318  queryString.append(" WHERE ");
1319  // queryString.append(DETECTORNAME_COLUMN_NAME);
1320  // queryString.append("='");
1321  // queryString.append(detectorName);
1322  // queryString.append("' AND ");
1323  queryString.append(SUBSYSTEMNAME_COLUMN_NAME);
1324  queryString.append("='");
1325  queryString.append(subsystemName);
1326  queryString.append("' AND ");
1327  queryString.append(CONFIGTYPE_COLUMN_NAME);
1328  queryString.append("='");
1329  queryString.append(configType);
1330  queryString.append("' AND ");
1331  queryString.append(ISOBSOLETE_COLUMN_NAME);
1332  queryString.append("=false AND ");
1333  queryString.append(ISCHANGING_COLUMN_NAME);
1334  queryString.append("=false AND ");
1335  queryString.append(ISCOMPLETE_COLUMN_NAME);
1336  queryString.append("=true GROUP BY ");
1337  queryString.append(NAME_COLUMN_NAME);
1338  queryString.append(", ");
1339  queryString.append(DCMOPMODE_COLUMN_NAME);
1340  queryString.append(" ORDER BY SUM(");
1341  queryString.append(USAGECOUNT_COLUMN_NAME);
1342  queryString.append(") DESC, MAX(");
1343  queryString.append(INSERTTIME_COLUMN_NAME);
1344  queryString.append(") DESC, ");
1345  queryString.append(NAME_COLUMN_NAME);
1346  queryString.append(" ASC");
1347 
1348  resultSetPtr = 0;
1349  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
1350  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
1351  PQclear(resultSetPtr);
1352 
1353  return false;
1354  }
1355  std::vector<SubsystemNameSpec> summaryList;
1356  int nRows = PQntuples(resultSetPtr);
1357  if (nRows > 0) {
1358  for (int idx = 0; idx < nRows; ++idx) {
1359  std::string nameString = PQgetvalue(resultSetPtr, idx, 0);
1360  std::string opModeString = PQgetvalue(resultSetPtr, idx, 1);
1361  std::string usageCountString = PQgetvalue(resultSetPtr, idx, 2);
1362  int usageCount = 0;
1363  try {
1364  usageCount = boost::lexical_cast<int>(usageCountString);
1365  }
1366  catch (...) {}
1367 
1368  SubsystemNameSpec nameSpec(nameString, opModeString, detectorName,
1369  subsystemName, configType);
1370  nameSpec.setUsageCount(usageCount);
1371  nameSpec.setSortIndex(idx);
1372  summaryList.push_back(nameSpec);
1373  }
1374  }
1375  PQclear(resultSetPtr);
1376 
1377  // Fetch the most recent N instances of each name and dcmOpMode.
1378  for (int cfgIdx = 0; cfgIdx < (int) summaryList.size(); ++cfgIdx) {
1379  std::string configName = summaryList[cfgIdx].getConfigName();
1380  std::string dcmOpMode = summaryList[cfgIdx].getDCMOpMode();
1381 
1382  dbt->Clear();
1383  dbt->SetValidityRange(NAME_COLUMN_NAME, configName);
1384  dbt->SetValidityRange(DCMOPMODE_COLUMN_NAME, dcmOpMode);
1385  dbt->SetValidityRange(DETECTORNAME_COLUMN_NAME, detectorName);
1386  dbt->SetValidityRange(SUBSYSTEMNAME_COLUMN_NAME, subsystemName);
1387  dbt->SetValidityRange(CONFIGTYPE_COLUMN_NAME, configType);
1388  dbt->SetValidityRange(ISOBSOLETE_COLUMN_NAME, false);
1389  dbt->SetValidityRange(ISCHANGING_COLUMN_NAME, false);
1390  dbt->SetValidityRange(ISCOMPLETE_COLUMN_NAME, true);
1391  dbt->AddOrderColumn(INSERTTIME_COLUMN_NAME);
1392  dbt->SetOrderDesc();
1393  dbt->SetSelectLimit(maxDetailCountPerSummary);
1394  if (! dbt->LoadFromDB()) {return false;}
1395 
1396  std::vector<SubsystemNameSpec> detailsList;
1397  for (int32_t idx = 0; idx < dbt->NRow(); ++idx) {
1398  NOVADB::Row* rowPtr = dbt->GetRow(idx);
1399  NOVADB::Column* colPtr;
1400 
1402  colPtr = rowPtr->Col(INSERTTIME_COLUMN_NAME);
1403  if (! colPtr->Get(timestamp)) {return false;}
1404 
1405  int usageCount;
1406  colPtr = rowPtr->Col(USAGECOUNT_COLUMN_NAME);
1407  if (colPtr->IsNull()) {usageCount = 0;}
1408  else if (! colPtr->Get(usageCount)) {return false;}
1409 
1410  SubsystemNameSpec nameSpec(configName, dcmOpMode, detectorName,
1411  subsystemName, configType, timestamp);
1412  nameSpec.setUsageCount(usageCount);
1413  detailsList.push_back(nameSpec);
1414  }
1415 
1416  resultsTable[summaryList[cfgIdx]] = detailsList;
1417  }
1418 
1419  return true;
1420 }
1421 
1423 copyGlobalConfig(const IDSpec& sourceId, bool makeParentChildLink,
1424  const SimpleParameterSet& valuesToOverride,
1425  std::string baselineTimestamp,
1426  bool overrideIntermediateUpdate,
1427  int64_t& resultId, const std::string& globalNamesTableFile)
1428 {
1429  novadaq::Status resultStatus;
1430  PGresult* resultSetPtr;
1431  boost::shared_ptr<NOVADB::Table> dbt;
1432  if (sourceId.isSlowControlsConfiguration() &&
1433  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
1434  dbt.reset(new NOVADB::
1436  }
1437  else {
1438  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
1439  }
1440  std::string daqEnv =
1441  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
1442  dbt->SetDetector(daqEnv);
1443  dbt->SetTableType(NOVADB::kDAQTable);
1444  std::string dbUser =
1445  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
1446  if (dbUser.length() > 0) {
1447  dbt->SetUser(dbUser);
1448  }
1449  else {
1450  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("USER");
1451  }
1452  dbt->GetConnection();
1453 
1454  // look up the parameters associated with the source configuration
1455  NamedConfigSelectionCriteria selections;
1456  selections[ID_COLUMN_NAME] =
1457  boost::lexical_cast<std::string>(sourceId.getConfigId());
1458  NamedConfigDetailsPtr sourceCfgDetails = _getDetails(dbt, selections);
1459  if (sourceCfgDetails.get() == 0) {
1460  resultStatus.code = COPY_FAILED;
1461  resultStatus.message = "The lookup of the input global ";
1462  resultStatus.message.append("configuration ID failed.");
1463  return resultStatus;
1464  }
1465  std::string sourceConfigName;
1466  if (! getFieldValue(sourceCfgDetails, NAME_COLUMN_NAME,
1467  sourceConfigName)) {
1468  resultStatus.code = COPY_FAILED;
1469  resultStatus.message = "Unable to determine the configuration name ";
1470  resultStatus.message.append("for the source configuration.");
1471  return resultStatus;
1472  }
1473  std::string sourceDcmOpMode;
1474  if (! getFieldValue(sourceCfgDetails, DCMOPMODE_COLUMN_NAME,
1475  sourceDcmOpMode)) {
1476  resultStatus.code = COPY_FAILED;
1477  resultStatus.message = "Unable to determine the DCM operating mode ";
1478  resultStatus.message.append("for the source configuration.");
1479  return resultStatus;
1480  }
1481  std::string sourceDetectorName;
1482  if (! getFieldValue(sourceCfgDetails, DETECTORNAME_COLUMN_NAME,
1483  sourceDetectorName)) {
1484  resultStatus.code = COPY_FAILED;
1485  resultStatus.message = "Unable to determine the detector name ";
1486  resultStatus.message.append("for the source configuration.");
1487  return resultStatus;
1488  }
1489  std::string sourceTimestamp;
1490  if (! getFieldValue(sourceCfgDetails, INSERTTIME_COLUMN_NAME,
1491  sourceTimestamp)) {
1492  resultStatus.code = COPY_FAILED;
1493  resultStatus.message = "Unable to determine the timestamp for the ";
1494  resultStatus.message.append("source configuration.");
1495  return resultStatus;
1496  }
1497 
1498  // determine the values of the parameters that we'll use to identify
1499  // the target configuration
1500  bool targetAndSourceHaveSameKey = true;
1501  std::string targetConfigName;
1502  if (valuesToOverride.get(NAME_COLUMN_NAME, targetConfigName)) {
1503  if (targetConfigName != sourceConfigName) {
1504  targetAndSourceHaveSameKey = false;
1505  }
1506  }
1507  else {
1508  targetConfigName = sourceConfigName;
1509  }
1510  std::string targetDcmOpMode;
1511  if (valuesToOverride.get(DCMOPMODE_COLUMN_NAME, targetDcmOpMode)) {
1512  if (targetDcmOpMode != sourceDcmOpMode) {
1513  targetAndSourceHaveSameKey = false;
1514  }
1515  }
1516  else {
1517  targetDcmOpMode = sourceDcmOpMode;
1518  }
1519  std::string targetDetectorName;
1520  if (valuesToOverride.get(DETECTORNAME_COLUMN_NAME, targetDetectorName)) {
1521  if (targetDetectorName != sourceDetectorName) {
1522  targetAndSourceHaveSameKey = false;
1523  }
1524  }
1525  else {
1526  targetDetectorName = sourceDetectorName;
1527  }
1528 
1529  // lock the table
1530  std::string dbCmd = "BEGIN";
1531  resultSetPtr = 0;
1532  if (! dbt->ExecuteSQL(dbCmd, resultSetPtr) ||
1533  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
1534  PQclear(resultSetPtr);
1535 
1536  resultStatus.code = COPY_FAILED;
1537  resultStatus.message = "Unable to begin the database transaction.";
1538  return resultStatus;
1539  }
1540  PQclear(resultSetPtr);
1541  dbCmd = "LOCK TABLE ";
1542  dbCmd.append(dbt->Schema() + "." + dbt->Name());
1543  dbCmd.append(" IN ACCESS EXCLUSIVE MODE");
1544  resultSetPtr = 0;
1545  if (! dbt->ExecuteSQL(dbCmd, resultSetPtr) ||
1546  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
1547  PQclear(resultSetPtr);
1548 
1549  resultStatus.code = COPY_FAILED;
1550  resultStatus.message = "Unable to lock DB table ";
1551  resultStatus.message.append(dbt->Schema() + "." + dbt->Name());
1552  resultStatus.message.append(".");
1553  return resultStatus;
1554  }
1555  PQclear(resultSetPtr);
1556 
1557  // check if the latest instance of the target configuration is changing
1558  std::string queryString = "SELECT ";
1559  queryString.append(ISCHANGING_COLUMN_NAME);
1560  queryString.append(", ");
1561  queryString.append(ID_COLUMN_NAME);
1562  queryString.append(" FROM ");
1563  queryString.append(dbt->Schema() + "." + dbt->Name());
1564  queryString.append(" WHERE ");
1565  queryString.append(NAME_COLUMN_NAME);
1566  queryString.append("='");
1567  queryString.append(targetConfigName);
1568  queryString.append("' AND ");
1569  queryString.append(DCMOPMODE_COLUMN_NAME);
1570  queryString.append("='");
1571  queryString.append(targetDcmOpMode);
1572  queryString.append("' AND ");
1573  queryString.append(DETECTORNAME_COLUMN_NAME);
1574  queryString.append("='");
1575  queryString.append(targetDetectorName);
1576  queryString.append("' ORDER BY ");
1577  queryString.append(ID_COLUMN_NAME);
1578  queryString.append(" DESC LIMIT 1");
1579 
1580  resultSetPtr = 0;
1581  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
1582  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
1583  PQclear(resultSetPtr);
1584 
1585  resultStatus.code = COPY_FAILED;
1586  resultStatus.message = "Unable to check if the latest instance ";
1587  resultStatus.message.append("of the target configuration ");
1588  resultStatus.message.append("is changing.");
1589  return resultStatus;
1590  }
1591  if (PQntuples(resultSetPtr) > 0) {
1592  std::string resultString = PQgetvalue(resultSetPtr, 0, 0);
1593  boost::to_lower(resultString);
1594  if (resultString == "t") {
1595  resultStatus.code = COPY_FOUND_UPDATE_IN_PROGRESS;
1596  resultStatus.message = "Concurrent changes are in progress ";
1597  resultStatus.message.append("(globalConfigId = ");
1598  resultStatus.message.append(PQgetvalue(resultSetPtr, 0, 1));
1599  resultStatus.message.append(").");
1600 
1601  PQclear(resultSetPtr);
1602 
1603  dbCmd = "END";
1604  dbt->ExecuteSQL(dbCmd, resultSetPtr);
1605 
1606  return resultStatus;
1607  }
1608  }
1609  PQclear(resultSetPtr);
1610 
1611  // check if there are intermediate changes to the target configuration
1612  if (! overrideIntermediateUpdate) {
1613  boost::trim(baselineTimestamp);
1614  if (baselineTimestamp.length() == 0) {
1615  if (targetAndSourceHaveSameKey) {
1616  baselineTimestamp = sourceTimestamp;
1617  }
1618  else {
1619  baselineTimestamp = NOVADB::Util::GetFarPastTimeAsString();
1620  }
1621  }
1622 
1623  queryString = "SELECT ";
1624  queryString.append(ID_COLUMN_NAME);
1625  queryString.append(" FROM ");
1626  queryString.append(dbt->Schema() + "." + dbt->Name());
1627  queryString.append(" WHERE ");
1628  queryString.append(NAME_COLUMN_NAME);
1629  queryString.append("='");
1630  queryString.append(targetConfigName);
1631  queryString.append("' AND ");
1632  queryString.append(DCMOPMODE_COLUMN_NAME);
1633  queryString.append("='");
1634  queryString.append(targetDcmOpMode);
1635  queryString.append("' AND ");
1636  queryString.append(DETECTORNAME_COLUMN_NAME);
1637  queryString.append("='");
1638  queryString.append(targetDetectorName);
1639  queryString.append("' AND ");
1640  queryString.append(INSERTTIME_COLUMN_NAME);
1641  queryString.append(">'");
1642  queryString.append(baselineTimestamp);
1643  queryString.append("' ORDER BY ");
1644  queryString.append(ID_COLUMN_NAME);
1645  queryString.append(" DESC");
1646 
1647  resultSetPtr = 0;
1648  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
1649  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
1650  PQclear(resultSetPtr);
1651 
1652  resultStatus.code = COPY_FAILED;
1653  resultStatus.message = "Unable to check if there are ";
1654  resultStatus.message.append("intermediate changes in the ");
1655  resultStatus.message.append("target configuration.");
1656  return resultStatus;
1657  }
1658  if (PQntuples(resultSetPtr) > 0) {
1659  resultStatus.code = COPY_FOUND_INTERMEDIATE_UPDATE;
1660  resultStatus.message = "Found intermediate changes in the ";
1661  resultStatus.message.append("target configuration ");
1662  resultStatus.message.append("(e.g. globalConfigId = ");
1663  resultStatus.message.append(PQgetvalue(resultSetPtr, 0, 0));
1664  resultStatus.message.append(").");
1665 
1666  PQclear(resultSetPtr);
1667 
1668  dbCmd = "END";
1669  dbt->ExecuteSQL(dbCmd, resultSetPtr);
1670 
1671  return resultStatus;
1672  }
1673  PQclear(resultSetPtr);
1674  }
1675 
1676  // add the new target row
1677  const NOVADB::Column* colPtr;
1678  std::string columnNamesClause;
1679  std::string valuesClause;
1680  std::vector<std::string> columnNames = dbt->GetColNames();
1681  for (uint32_t idx = 0; idx < columnNames.size(); ++idx) {
1682 
1683  std::string columnName = boost::to_lower_copy(columnNames[idx]);
1684  if (columnName == NamedConfigUtils::ID_COLUMN_NAME) {continue;}
1685  if (columnName == NamedConfigUtils::USAGECOUNT_COLUMN_NAME) {continue;}
1686  if (columnName == NamedConfigUtils::UPDATETIME_COLUMN_NAME) {continue;}
1687  if (columnName == NamedConfigUtils::UPDATEUSER_COLUMN_NAME) {continue;}
1688 
1689  if (columnName == NamedConfigUtils::ISCHANGING_COLUMN_NAME) {
1690  if (columnNamesClause.length() > 0) {
1691  columnNamesClause.append(",");
1692  valuesClause.append(",");
1693  }
1694  columnNamesClause.append(columnName);
1695  valuesClause.append("true");
1696  continue;
1697  }
1698 
1699  if (columnName == NamedConfigUtils::ISCOMPLETE_COLUMN_NAME) {
1700  if (columnNamesClause.length() > 0) {
1701  columnNamesClause.append(",");
1702  valuesClause.append(",");
1703  }
1704  columnNamesClause.append(columnName);
1705  valuesClause.append("false");
1706  continue;
1707  }
1708 
1709  if (columnName == NamedConfigUtils::PARENTID_COLUMN_NAME) {
1710  if (makeParentChildLink) {
1711  if (columnNamesClause.length() > 0) {
1712  columnNamesClause.append(",");
1713  valuesClause.append(",");
1714  }
1715  columnNamesClause.append(columnName);
1716  valuesClause.append(boost::lexical_cast<std::string>
1717  (sourceId.getConfigId()));
1718  }
1719  continue;
1720  }
1721 
1722  if (columnName == NamedConfigUtils::INSERTTIME_COLUMN_NAME) {
1723  if (columnNamesClause.length() > 0) {
1724  columnNamesClause.append(",");
1725  valuesClause.append(",");
1726  }
1727  columnNamesClause.append(columnName);
1728  valuesClause.append("'");
1729  valuesClause.append(NOVADB::Util::GetCurrentTimeAsString());
1730  valuesClause.append("'");
1731  continue;
1732  }
1733 
1734  if (columnName == NamedConfigUtils::INSERTUSER_COLUMN_NAME) {
1735  if (columnNamesClause.length() > 0) {
1736  columnNamesClause.append(",");
1737  valuesClause.append(",");
1738  }
1739  columnNamesClause.append(columnName);
1740  valuesClause.append("'");
1741  valuesClause.append(dbUser);
1742  valuesClause.append("'");
1743  continue;
1744  }
1745 
1747  if (! valuesToOverride.get(columnName, value) &&
1748  ! getFieldValue(sourceCfgDetails, columnName, value)) {
1749  resultStatus.code = COPY_FAILED;
1750  resultStatus.message = "The lookup of the value for the ";
1751  resultStatus.message.append(columnName);
1752  resultStatus.message.append(" column failed.");
1753  return resultStatus;
1754  }
1755 
1756  colPtr = dbt->GetCol(columnName);
1757  std::string columnType = "string";
1758  if (colPtr != 0) {
1759  columnType = colPtr->Type();
1760  }
1761 
1762  if (columnNamesClause.length() > 0) {
1763  columnNamesClause.append(",");
1764  valuesClause.append(",");
1765  }
1766  columnNamesClause.append(columnName);
1767  if (columnType == "string" || columnType == "timestamp") {
1768  valuesClause.append("'");
1769  valuesClause.append(value);
1770  valuesClause.append("'");
1771  }
1772  else if (columnType == "bool") {
1773  try {
1774  int intValue = boost::lexical_cast<int>(value);
1775  if (intValue) {
1776  valuesClause.append("true");
1777  }
1778  else {
1779  valuesClause.append("false");
1780  }
1781  }
1782  catch (...) {
1783  valuesClause.append(value);
1784  }
1785  }
1786  else {
1787  valuesClause.append(value);
1788  }
1789  }
1790 
1791  std::string insertString = "INSERT INTO ";
1792  insertString.append(dbt->Schema() + "." + dbt->Name());
1793  insertString.append(" (");
1794  insertString.append(columnNamesClause);
1795  insertString.append(") VALUES (");
1796  insertString.append(valuesClause);
1797  insertString.append(")");
1798 
1799  resultSetPtr = 0;
1800  if (! dbt->ExecuteSQL(insertString, resultSetPtr) ||
1801  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
1802  PQclear(resultSetPtr);
1803 
1804  resultStatus.code = COPY_FAILED;
1805  resultStatus.message = "The writing of the new global configuration ";
1806  resultStatus.message.append("into the database failed.");
1807  return resultStatus;
1808  }
1809  PQclear(resultSetPtr);
1810  if (! dbt->GetCurrSeqVal(NamedConfigUtils::ID_COLUMN_NAME, resultId)) {
1811  resultStatus.code = COPY_FAILED;
1812  resultStatus.message = "The lookup of the new global configuration ";
1813  resultStatus.message.append("ID failed.");
1814  return resultStatus;
1815  }
1816 
1817  // end the transaction (thereby freeing the lock on the table)
1818  dbCmd = "END";
1819  dbt->ExecuteSQL(dbCmd, resultSetPtr);
1820  PQclear(resultSetPtr);
1821 
1822  resultStatus.code = COPY_SUCCEEDED;
1823  resultStatus.message = "Success";
1824  return resultStatus;
1825 }
1826 
1828 copySubsystemConfig(const IDSpec& sourceId, bool makeParentChildLink,
1829  const SimpleParameterSet& valuesToOverride,
1830  std::string baselineTimestamp,
1831  bool overrideIntermediateUpdate,
1832  int64_t& resultId,
1833  const std::string& subsystemNamesTableFile)
1834 {
1835  novadaq::Status resultStatus;
1836  PGresult* resultSetPtr;
1837  boost::shared_ptr<NOVADB::Table> dbt;
1838  if (sourceId.isSlowControlsConfiguration() &&
1839  subsystemNamesTableFile == DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE) {
1840  dbt.reset(new NOVADB::
1842  }
1843  else {
1844  dbt.reset(new NOVADB::Table(subsystemNamesTableFile.c_str()));
1845  }
1846  std::string daqEnv =
1847  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
1848  dbt->SetDetector(daqEnv);
1849  dbt->SetTableType(NOVADB::kDAQTable);
1850  std::string dbUser =
1851  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
1852  if (dbUser.length() > 0) {
1853  dbt->SetUser(dbUser);
1854  }
1855  else {
1856  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("USER");
1857  }
1858  dbt->GetConnection();
1859 
1860  // look up the parameters associated with the source configuration
1861  NamedConfigSelectionCriteria selections;
1862  selections[ID_COLUMN_NAME] =
1863  boost::lexical_cast<std::string>(sourceId.getConfigId());
1864  NamedConfigDetailsPtr sourceCfgDetails = _getDetails(dbt, selections);
1865  if (sourceCfgDetails.get() == 0) {
1866  resultStatus.code = COPY_FAILED;
1867  resultStatus.message = "The lookup of the input subsystem ";
1868  resultStatus.message.append("configuration ID failed.");
1869  return resultStatus;
1870  }
1871  std::string sourceConfigName;
1872  if (! getFieldValue(sourceCfgDetails, NAME_COLUMN_NAME,
1873  sourceConfigName)) {
1874  resultStatus.code = COPY_FAILED;
1875  resultStatus.message = "Unable to determine the configuration name ";
1876  resultStatus.message.append("for the source configuration.");
1877  return resultStatus;
1878  }
1879  std::string sourceDcmOpMode;
1880  if (! getFieldValue(sourceCfgDetails, DCMOPMODE_COLUMN_NAME,
1881  sourceDcmOpMode)) {
1882  resultStatus.code = COPY_FAILED;
1883  resultStatus.message = "Unable to determine the DCM operating mode ";
1884  resultStatus.message.append("for the source configuration.");
1885  return resultStatus;
1886  }
1887  std::string sourceDetectorName;
1888  if (! getFieldValue(sourceCfgDetails, DETECTORNAME_COLUMN_NAME,
1889  sourceDetectorName)) {
1890  resultStatus.code = COPY_FAILED;
1891  resultStatus.message = "Unable to determine the detector name ";
1892  resultStatus.message.append("for the source configuration.");
1893  return resultStatus;
1894  }
1895  std::string sourceSubsystemName;
1896  if (! getFieldValue(sourceCfgDetails, SUBSYSTEMNAME_COLUMN_NAME,
1897  sourceSubsystemName)) {
1898  resultStatus.code = COPY_FAILED;
1899  resultStatus.message = "Unable to determine the subsystem name ";
1900  resultStatus.message.append("for the source configuration.");
1901  return resultStatus;
1902  }
1903  std::string sourceConfigType;
1904  if (! getFieldValue(sourceCfgDetails, CONFIGTYPE_COLUMN_NAME,
1905  sourceConfigType)) {
1906  resultStatus.code = COPY_FAILED;
1907  resultStatus.message = "Unable to determine the configuration ";
1908  resultStatus.message.append("type for the source configuration.");
1909  return resultStatus;
1910  }
1911  std::string sourceTimestamp;
1912  if (! getFieldValue(sourceCfgDetails, INSERTTIME_COLUMN_NAME,
1913  sourceTimestamp)) {
1914  resultStatus.code = COPY_FAILED;
1915  resultStatus.message = "Unable to determine the timestamp for the ";
1916  resultStatus.message.append("source configuration.");
1917  return resultStatus;
1918  }
1919 
1920  // determine the values of the parameters that we'll use to identify
1921  // the target configuration
1922  bool targetAndSourceHaveSameKey = true;
1923  std::string targetConfigName;
1924  if (valuesToOverride.get(NAME_COLUMN_NAME, targetConfigName)) {
1925  if (targetConfigName != sourceConfigName) {
1926  targetAndSourceHaveSameKey = false;
1927  }
1928  }
1929  else {
1930  targetConfigName = sourceConfigName;
1931  }
1932  std::string targetDcmOpMode;
1933  if (valuesToOverride.get(DCMOPMODE_COLUMN_NAME, targetDcmOpMode)) {
1934  if (targetDcmOpMode != sourceDcmOpMode) {
1935  targetAndSourceHaveSameKey = false;
1936  }
1937  }
1938  else {
1939  targetDcmOpMode = sourceDcmOpMode;
1940  }
1941  std::string targetDetectorName;
1942  if (valuesToOverride.get(DETECTORNAME_COLUMN_NAME, targetDetectorName)) {
1943  if (targetDetectorName != sourceDetectorName) {
1944  targetAndSourceHaveSameKey = false;
1945  }
1946  }
1947  else {
1948  targetDetectorName = sourceDetectorName;
1949  }
1950  std::string targetSubsystemName;
1951  if (valuesToOverride.get(SUBSYSTEMNAME_COLUMN_NAME, targetSubsystemName)) {
1952  if (targetSubsystemName != sourceSubsystemName) {
1953  targetAndSourceHaveSameKey = false;
1954  }
1955  }
1956  else {
1957  targetSubsystemName = sourceSubsystemName;
1958  }
1959  std::string targetConfigType;
1960  if (valuesToOverride.get(CONFIGTYPE_COLUMN_NAME, targetConfigType)) {
1961  if (targetConfigType != sourceConfigType) {
1962  targetAndSourceHaveSameKey = false;
1963  }
1964  }
1965  else {
1966  targetConfigType = sourceConfigType;
1967  }
1968 
1969  // lock the table
1970  std::string dbCmd = "BEGIN";
1971  resultSetPtr = 0;
1972  if (! dbt->ExecuteSQL(dbCmd, resultSetPtr) ||
1973  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
1974  PQclear(resultSetPtr);
1975 
1976  resultStatus.code = COPY_FAILED;
1977  resultStatus.message = "Unable to begin the database transaction.";
1978  return resultStatus;
1979  }
1980  PQclear(resultSetPtr);
1981  dbCmd = "LOCK TABLE ";
1982  dbCmd.append(dbt->Schema() + "." + dbt->Name());
1983  dbCmd.append(" IN ACCESS EXCLUSIVE MODE");
1984  resultSetPtr = 0;
1985  if (! dbt->ExecuteSQL(dbCmd, resultSetPtr) ||
1986  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
1987  PQclear(resultSetPtr);
1988 
1989  resultStatus.code = COPY_FAILED;
1990  resultStatus.message = "Unable to lock DB table ";
1991  resultStatus.message.append(dbt->Schema() + "." + dbt->Name());
1992  resultStatus.message.append(".");
1993  return resultStatus;
1994  }
1995  PQclear(resultSetPtr);
1996 
1997  // check if the latest instance of the target configuration is changing
1998  std::string queryString = "SELECT ";
1999  queryString.append(ISCHANGING_COLUMN_NAME);
2000  queryString.append(", ");
2001  queryString.append(ID_COLUMN_NAME);
2002  queryString.append(" FROM ");
2003  queryString.append(dbt->Schema() + "." + dbt->Name());
2004  queryString.append(" WHERE ");
2005  queryString.append(NAME_COLUMN_NAME);
2006  queryString.append("='");
2007  queryString.append(targetConfigName);
2008  queryString.append("' AND ");
2009  queryString.append(DCMOPMODE_COLUMN_NAME);
2010  queryString.append("='");
2011  queryString.append(targetDcmOpMode);
2012  queryString.append("' AND ");
2013  queryString.append(DETECTORNAME_COLUMN_NAME);
2014  queryString.append("='");
2015  queryString.append(targetDetectorName);
2016  queryString.append("' AND ");
2017  queryString.append(SUBSYSTEMNAME_COLUMN_NAME);
2018  queryString.append("='");
2019  queryString.append(targetSubsystemName);
2020  queryString.append("' AND ");
2021  queryString.append(CONFIGTYPE_COLUMN_NAME);
2022  queryString.append("='");
2023  queryString.append(targetConfigType);
2024  queryString.append("' ORDER BY ");
2025  queryString.append(ID_COLUMN_NAME);
2026  queryString.append(" DESC LIMIT 1");
2027 
2028  resultSetPtr = 0;
2029  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
2030  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
2031  PQclear(resultSetPtr);
2032 
2033  resultStatus.code = COPY_FAILED;
2034  resultStatus.message = "Unable to check if the latest instance ";
2035  resultStatus.message.append("of the target configuration ");
2036  resultStatus.message.append("is changing.");
2037  return resultStatus;
2038  }
2039  if (PQntuples(resultSetPtr) > 0) {
2040  std::string resultString = PQgetvalue(resultSetPtr, 0, 0);
2041  boost::to_lower(resultString);
2042  if (resultString == "t") {
2043  resultStatus.code = COPY_FOUND_UPDATE_IN_PROGRESS;
2044  resultStatus.message = "Concurrent changes are in progress ";
2045  resultStatus.message.append("(subsystemConfigId = ");
2046  resultStatus.message.append(PQgetvalue(resultSetPtr, 0, 1));
2047  resultStatus.message.append(").");
2048 
2049  PQclear(resultSetPtr);
2050 
2051  dbCmd = "END";
2052  dbt->ExecuteSQL(dbCmd, resultSetPtr);
2053 
2054  return resultStatus;
2055  }
2056  }
2057  PQclear(resultSetPtr);
2058 
2059  // check if there are intermediate changes to the target configuration
2060  if (! overrideIntermediateUpdate) {
2061  boost::trim(baselineTimestamp);
2062  if (baselineTimestamp.length() == 0) {
2063  if (targetAndSourceHaveSameKey) {
2064  baselineTimestamp = sourceTimestamp;
2065  }
2066  else {
2067  baselineTimestamp = NOVADB::Util::GetFarPastTimeAsString();
2068  }
2069  }
2070 
2071  queryString = "SELECT ";
2072  queryString.append(ID_COLUMN_NAME);
2073  queryString.append(" FROM ");
2074  queryString.append(dbt->Schema() + "." + dbt->Name());
2075  queryString.append(" WHERE ");
2076  queryString.append(NAME_COLUMN_NAME);
2077  queryString.append("='");
2078  queryString.append(targetConfigName);
2079  queryString.append("' AND ");
2080  queryString.append(DCMOPMODE_COLUMN_NAME);
2081  queryString.append("='");
2082  queryString.append(targetDcmOpMode);
2083  queryString.append("' AND ");
2084  queryString.append(DETECTORNAME_COLUMN_NAME);
2085  queryString.append("='");
2086  queryString.append(targetDetectorName);
2087  queryString.append("' AND ");
2088  queryString.append(SUBSYSTEMNAME_COLUMN_NAME);
2089  queryString.append("='");
2090  queryString.append(targetSubsystemName);
2091  queryString.append("' AND ");
2092  queryString.append(CONFIGTYPE_COLUMN_NAME);
2093  queryString.append("='");
2094  queryString.append(targetConfigType);
2095  queryString.append("' AND ");
2096  queryString.append(INSERTTIME_COLUMN_NAME);
2097  queryString.append(">'");
2098  queryString.append(baselineTimestamp);
2099  queryString.append("' ORDER BY ");
2100  queryString.append(ID_COLUMN_NAME);
2101  queryString.append(" DESC");
2102 
2103  resultSetPtr = 0;
2104  if (! dbt->ExecuteSQL(queryString, resultSetPtr) ||
2105  PQresultStatus(resultSetPtr) != PGRES_TUPLES_OK) {
2106  PQclear(resultSetPtr);
2107 
2108  resultStatus.code = COPY_FAILED;
2109  resultStatus.message = "Unable to check if there are ";
2110  resultStatus.message.append("intermediate changes in the ");
2111  resultStatus.message.append("target configuration.");
2112  return resultStatus;
2113  }
2114  if (PQntuples(resultSetPtr) > 0) {
2115  resultStatus.code = COPY_FOUND_INTERMEDIATE_UPDATE;
2116  resultStatus.message = "Found intermediate changes in the ";
2117  resultStatus.message.append("target configuration ");
2118  resultStatus.message.append("(e.g. subsystemConfigId = ");
2119  resultStatus.message.append(PQgetvalue(resultSetPtr, 0, 0));
2120  resultStatus.message.append(").");
2121 
2122  PQclear(resultSetPtr);
2123 
2124  dbCmd = "END";
2125  dbt->ExecuteSQL(dbCmd, resultSetPtr);
2126 
2127  return resultStatus;
2128  }
2129  PQclear(resultSetPtr);
2130  }
2131 
2132  // add the new target row
2133  const NOVADB::Column* colPtr;
2134  std::string columnNamesClause;
2135  std::string valuesClause;
2136  std::vector<std::string> columnNames = dbt->GetColNames();
2137  for (uint32_t idx = 0; idx < columnNames.size(); ++idx) {
2138 
2139  std::string columnName = boost::to_lower_copy(columnNames[idx]);
2140  if (columnName == NamedConfigUtils::ID_COLUMN_NAME) {continue;}
2141  if (columnName == NamedConfigUtils::USAGECOUNT_COLUMN_NAME) {continue;}
2142  if (columnName == NamedConfigUtils::UPDATETIME_COLUMN_NAME) {continue;}
2143  if (columnName == NamedConfigUtils::UPDATEUSER_COLUMN_NAME) {continue;}
2144 
2145  if (columnName == NamedConfigUtils::ISCHANGING_COLUMN_NAME) {
2146  if (columnNamesClause.length() > 0) {
2147  columnNamesClause.append(",");
2148  valuesClause.append(",");
2149  }
2150  columnNamesClause.append(columnName);
2151  valuesClause.append("true");
2152  continue;
2153  }
2154 
2155  if (columnName == NamedConfigUtils::ISCOMPLETE_COLUMN_NAME) {
2156  if (columnNamesClause.length() > 0) {
2157  columnNamesClause.append(",");
2158  valuesClause.append(",");
2159  }
2160  columnNamesClause.append(columnName);
2161  valuesClause.append("false");
2162  continue;
2163  }
2164 
2165  if (columnName == NamedConfigUtils::PARENTID_COLUMN_NAME) {
2166  if (makeParentChildLink) {
2167  if (columnNamesClause.length() > 0) {
2168  columnNamesClause.append(",");
2169  valuesClause.append(",");
2170  }
2171  columnNamesClause.append(columnName);
2172  valuesClause.append(boost::lexical_cast<std::string>
2173  (sourceId.getConfigId()));
2174  }
2175  continue;
2176  }
2177 
2178  if (columnName == NamedConfigUtils::INSERTTIME_COLUMN_NAME) {
2179  if (columnNamesClause.length() > 0) {
2180  columnNamesClause.append(",");
2181  valuesClause.append(",");
2182  }
2183  columnNamesClause.append(columnName);
2184  valuesClause.append("'");
2185  valuesClause.append(NOVADB::Util::GetCurrentTimeAsString());
2186  valuesClause.append("'");
2187  continue;
2188  }
2189 
2190  if (columnName == NamedConfigUtils::INSERTUSER_COLUMN_NAME) {
2191  if (columnNamesClause.length() > 0) {
2192  columnNamesClause.append(",");
2193  valuesClause.append(",");
2194  }
2195  columnNamesClause.append(columnName);
2196  valuesClause.append("'");
2197  valuesClause.append(dbUser);
2198  valuesClause.append("'");
2199  continue;
2200  }
2201 
2203  if (! valuesToOverride.get(columnName, value) &&
2204  ! getFieldValue(sourceCfgDetails, columnName, value)) {
2205  resultStatus.code = COPY_FAILED;
2206  resultStatus.message = "The lookup of the value for the ";
2207  resultStatus.message.append(columnName);
2208  resultStatus.message.append(" column failed.");
2209  return resultStatus;
2210  }
2211 
2212  colPtr = dbt->GetCol(columnName);
2213  std::string columnType = "string";
2214  if (colPtr != 0) {
2215  columnType = colPtr->Type();
2216  }
2217 
2218  if (columnNamesClause.length() > 0) {
2219  columnNamesClause.append(",");
2220  valuesClause.append(",");
2221  }
2222  columnNamesClause.append(columnName);
2223  if (columnType == "string" || columnType == "timestamp") {
2224  valuesClause.append("'");
2225  valuesClause.append(value);
2226  valuesClause.append("'");
2227  }
2228  else if (columnType == "bool") {
2229  try {
2230  int intValue = boost::lexical_cast<int>(value);
2231  if (intValue) {
2232  valuesClause.append("true");
2233  }
2234  else {
2235  valuesClause.append("false");
2236  }
2237  }
2238  catch (...) {
2239  valuesClause.append(value);
2240  }
2241  }
2242  else {
2243  valuesClause.append(value);
2244  }
2245  }
2246 
2247  std::string insertString = "INSERT INTO ";
2248  insertString.append(dbt->Schema() + "." + dbt->Name());
2249  insertString.append(" (");
2250  insertString.append(columnNamesClause);
2251  insertString.append(") VALUES (");
2252  insertString.append(valuesClause);
2253  insertString.append(")");
2254 
2255  resultSetPtr = 0;
2256  if (! dbt->ExecuteSQL(insertString, resultSetPtr) ||
2257  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
2258  PQclear(resultSetPtr);
2259 
2260  resultStatus.code = COPY_FAILED;
2261  resultStatus.message = "The writing of the new subsystem ";
2262  resultStatus.message.append("configuration into the database failed.");
2263  return resultStatus;
2264  }
2265  PQclear(resultSetPtr);
2266  if (! dbt->GetCurrSeqVal(NamedConfigUtils::ID_COLUMN_NAME, resultId)) {
2267  resultStatus.code = COPY_FAILED;
2268  resultStatus.message = "The lookup of the new subsystem ";
2269  resultStatus.message.append("configuration ID failed.");
2270  return resultStatus;
2271  }
2272 
2273  // end the transaction (thereby freeing the lock on the table)
2274  dbCmd = "END";
2275  dbt->ExecuteSQL(dbCmd, resultSetPtr);
2276  PQclear(resultSetPtr);
2277 
2278  resultStatus.code = COPY_SUCCEEDED;
2279  resultStatus.message = "Success";
2280  return resultStatus;
2281 }
2282 
2283 bool NamedConfigUtils::
2284 markConfigDone(const IDSpec& idSpec, bool alsoComplete,
2285  const std::string& tableFile)
2286 {
2287  PGresult* resultSetPtr;
2288  const NOVADB::Column* colPtr;
2289  boost::shared_ptr<NOVADB::Table> dbt;
2290  if (tableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
2291  if (idSpec.isGlobalConfiguration()) {
2292  if (idSpec.isDAQConfiguration()) {
2293  dbt.reset(new NOVADB::
2295  }
2296  else { // slow controls
2297  dbt.reset(new NOVADB::
2299  }
2300  }
2301  else { // subsystem
2302  if (idSpec.isDAQConfiguration()) {
2303  dbt.reset(new NOVADB::
2305  }
2306  else { // slow controls
2307  dbt.reset(new NOVADB::
2309  }
2310  }
2311  }
2312  else {
2313  dbt.reset(new NOVADB::Table(tableFile.c_str()));
2314  }
2315  std::string daqEnv =
2316  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
2317  dbt->SetDetector(daqEnv);
2318  dbt->SetTableType(NOVADB::kDAQTable);
2319  std::string dbUser =
2320  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
2321  if (dbUser.length() > 0) {
2322  dbt->SetUser(dbUser);
2323  }
2324  else {
2325  dbUser = novadaq::EnvVarCache::getInstance().getEnvVar("USER");
2326  }
2327  dbt->GetConnection();
2328 
2329  // lock the table
2330  std::string dbCmd = "BEGIN";
2331  resultSetPtr = 0;
2332  if (! dbt->ExecuteSQL(dbCmd, resultSetPtr) ||
2333  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
2334  PQclear(resultSetPtr);
2335  return false;
2336  }
2337  PQclear(resultSetPtr);
2338  dbCmd = "LOCK TABLE ";
2339  dbCmd.append(dbt->Schema() + "." + dbt->Name());
2340  dbCmd.append(" IN ACCESS EXCLUSIVE MODE");
2341  resultSetPtr = 0;
2342  if (! dbt->ExecuteSQL(dbCmd, resultSetPtr) ||
2343  PQresultStatus(resultSetPtr) != PGRES_COMMAND_OK) {
2344  PQclear(resultSetPtr);
2345  return false;
2346  }
2347  PQclear(resultSetPtr);
2348 
2349  // update the flag(s)
2350  std::string updateString = "UPDATE ";
2351  updateString.append(dbt->Schema() + "." + dbt->Name());
2352  updateString.append(" SET ");
2353  updateString.append(ISCHANGING_COLUMN_NAME);
2354  updateString.append("=false");
2355  if (alsoComplete) {
2356  updateString.append(", ");
2357  updateString.append(ISCOMPLETE_COLUMN_NAME);
2358  updateString.append("=true");
2359  }
2360 
2361  colPtr = dbt->GetCol(UPDATETIME_COLUMN_NAME.c_str());
2362  if (colPtr != 0) {
2363  updateString.append(", ");
2364  updateString.append(UPDATETIME_COLUMN_NAME);
2365  updateString.append("='");
2366  updateString.append(NOVADB::Util::GetCurrentTimeAsString());
2367  updateString.append("'");
2368  }
2369 
2370  colPtr = dbt->GetCol(UPDATEUSER_COLUMN_NAME.c_str());
2371  if (colPtr != 0) {
2372  updateString.append(", ");
2373  updateString.append(UPDATEUSER_COLUMN_NAME);
2374  updateString.append("='");
2375  updateString.append(dbUser);
2376  updateString.append("'");
2377  }
2378 
2379  updateString.append(" WHERE ");
2380  updateString.append(ID_COLUMN_NAME);
2381  updateString.append("=");
2382  updateString.append(boost::lexical_cast<std::string>
2383  (idSpec.getConfigId()));
2384 
2385  resultSetPtr = 0;
2386  bool status = dbt->ExecuteSQL(updateString, resultSetPtr);
2387  PQclear(resultSetPtr);
2388 
2389  // end the transaction (thereby freeing the lock on the table)
2390  dbCmd = "END";
2391  dbt->ExecuteSQL(dbCmd, resultSetPtr);
2392  PQclear(resultSetPtr);
2393 
2394  return status;
2395 }
2396 
2397 bool NamedConfigUtils::
2398 incrementUsageCount(const IDSpec& idSpec, const std::string& tableFile)
2399 {
2400  boost::shared_ptr<NOVADB::Table> dbt;
2401  if (tableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
2402  if (idSpec.isGlobalConfiguration()) {
2403  if (idSpec.isDAQConfiguration()) {
2404  dbt.reset(new NOVADB::
2406  }
2407  else { // slow controls
2408  dbt.reset(new NOVADB::
2410  }
2411  }
2412  else { // subsystem
2413  if (idSpec.isDAQConfiguration()) {
2414  dbt.reset(new NOVADB::
2416  }
2417  else { // slow controls
2418  dbt.reset(new NOVADB::
2420  }
2421  }
2422  }
2423  else {
2424  dbt.reset(new NOVADB::Table(tableFile.c_str()));
2425  }
2426  std::string daqEnv =
2427  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
2428  dbt->SetDetector(daqEnv);
2429  dbt->SetTableType(NOVADB::kDAQTable);
2430  std::string dbUser =
2431  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
2432  if (dbUser.length() > 0) {
2433  dbt->SetUser(dbUser);
2434  }
2435  dbt->GetConnection();
2436 
2437  dbt->Clear();
2438  dbt->SetValidityRange(ID_COLUMN_NAME, idSpec.getConfigId());
2439  if (! dbt->LoadFromDB()) {return false;}
2440  if (dbt->NRow() != 1) {return false;}
2441 
2442  int usageCount = 0;
2443  NOVADB::Row* rowPtr = dbt->GetRow(0);
2444  NOVADB::Column* colPtr = rowPtr->Col(USAGECOUNT_COLUMN_NAME);
2445  if (! colPtr->IsNull()) {
2446  if (! colPtr->Get(usageCount)) {return false;}
2447  }
2448  ++usageCount;
2449 
2450  rowPtr->Update(USAGECOUNT_COLUMN_NAME, usageCount);
2451  if (! dbt->WriteToDB()) {return false;}
2452 
2453  return true;
2454 }
2455 
2456 /**
2457  * Fetches the full set of details for the specified named
2458  * configuration *and* all of its ancestors.
2459  *
2460  * The details of the requested configuration are first in the returned
2461  * list, followed by its parent then grandparent, etc. If the
2462  * requested configuration has no ancestors, then only the details of
2463  * the requested configuration will be returned in the list.
2464  *
2465  * NOTE that this method assumes certain column names for the database
2466  * table that contains the configuration names. If any of these
2467  * assumptions are not valid for the given globalNamesTableFile,
2468  * then this method will always return an empty list.
2469  *
2470  * @param globalNameSpec The specification of the named global
2471  * configuration of interest.
2472  * @param globalNamesTableFile The name of the XML file (with any
2473  * needed path information) that contains the definition of the
2474  * database table that contains the named configurations.
2475  *
2476  * @returns the list of configuration details.
2477  */
2478 std::vector<NamedConfigUtils::NamedConfigDetailsPtr> NamedConfigUtils::
2480  const std::string& globalNamesTableFile)
2481 {
2482  std::vector<NamedConfigDetailsPtr> emptyList;
2483  int64_t globalConfigId;
2484 
2485  boost::shared_ptr<NOVADB::Table> dbt;
2486  if (globalNameSpec.isSlowControlsConfiguration() &&
2487  globalNamesTableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
2488  dbt.reset(new NOVADB::Table(DEFAULT_DCS_GLOBAL_NAMES_TABLE_FILE.c_str()));
2489  }
2490  else {
2491  dbt.reset(new NOVADB::Table(globalNamesTableFile.c_str()));
2492  }
2493  std::string daqEnv =
2494  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
2495  dbt->SetDetector(daqEnv);
2496  dbt->SetTableType(NOVADB::kDAQTable);
2497  std::string dbUser =
2498  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
2499  if (dbUser.length() > 0) {
2500  dbt->SetUser(dbUser);
2501  }
2502  dbt->GetConnection();
2503 
2504  NamedConfigSelectionCriteria selections;
2505  selections[NAME_COLUMN_NAME] = globalNameSpec.getConfigName();
2506  selections[DCMOPMODE_COLUMN_NAME] = globalNameSpec.getDCMOpMode();
2507  selections[DETECTORID_COLUMN_NAME] = globalNameSpec.getDetectorId();
2508  if (globalNameSpec.hasTimestamp()) {
2509  selections[INSERTTIME_COLUMN_NAME] = globalNameSpec.getTimestamp();
2510  }
2511  if (! globalNameSpec.skipInvalidStateTest()) {
2512  selections[ISOBSOLETE_COLUMN_NAME] = "false";
2513  selections[ISCHANGING_COLUMN_NAME] = "false";
2514  selections[ISCOMPLETE_COLUMN_NAME] = "true";
2515  }
2516 
2517  if (! _getId(dbt, selections, globalConfigId)) {
2518  return emptyList;
2519  }
2520 
2521  IDSpec globalIdSpec(globalConfigId, IDSpec::GLOBAL,
2522  (globalNameSpec.isSlowControlsConfiguration() ?
2524  return getConfigDetailAncestry(globalIdSpec, globalNamesTableFile);
2525 }
2526 
2527 /**
2528  * Fetches the full set of details for the specified named
2529  * configuration *and* all of its ancestors.
2530  *
2531  * The details of the requested configuration are first in the returned
2532  * list, followed by its parent then grandparent, etc. If the
2533  * requested configuration has no ancestors, then only the details of
2534  * the requested configuration will be returned in the list.
2535  *
2536  * NOTE that this method assumes certain column names for the database
2537  * table that contains the configuration names. If any of these
2538  * assumptions are not valid for the tableFile that is given (or
2539  * (inferred), then this method will always return an empty list.
2540  *
2541  * @param idSpec The ID-based specification of the named configuration
2542  * of interest.
2543  * @param tableFile The name of the XML file (with any
2544  * needed path information) that contains the definition of the
2545  * database table that contains the named configurations.
2546  *
2547  * @returns the list of configuration details.
2548  */
2549 std::vector<NamedConfigUtils::NamedConfigDetailsPtr> NamedConfigUtils::
2551  const std::string& tableFile)
2552 {
2553  // I need to revisit this method to make it more efficient - KAB
2554 
2555  std::vector<NamedConfigDetailsPtr> emptyList;
2556  std::vector<NamedConfigDetailsPtr> detailsList;
2557  std::vector<int64_t> idList;
2558 
2559  boost::shared_ptr<NOVADB::Table> dbt;
2560  if (tableFile == DEFAULT_GLOBAL_NAMES_TABLE_FILE) {
2561  if (idSpec.isGlobalConfiguration()) {
2562  if (idSpec.isDAQConfiguration()) {
2563  dbt.reset(new NOVADB::
2565  }
2566  else { // slow controls
2567  dbt.reset(new NOVADB::
2569  }
2570  }
2571  else { // subsystem
2572  if (idSpec.isDAQConfiguration()) {
2573  dbt.reset(new NOVADB::
2575  }
2576  else { // slow controls
2577  dbt.reset(new NOVADB::
2579  }
2580  }
2581  }
2582  else {
2583  dbt.reset(new NOVADB::Table(tableFile.c_str()));
2584  }
2585  std::string daqEnv =
2586  novadaq::EnvVarCache::getInstance().getEnvVar("NOVADAQ_ENVIRONMENT");
2587  dbt->SetDetector(daqEnv);
2588  dbt->SetTableType(NOVADB::kDAQTable);
2589  std::string dbUser =
2590  novadaq::EnvVarCache::getInstance().getEnvVar("CFGMGR_DB_USER");
2591  if (dbUser.length() > 0) {
2592  dbt->SetUser(dbUser);
2593  }
2594  dbt->GetConnection();
2595 
2596  idList.push_back(idSpec.getConfigId());
2597  uint32_t previousSize = idList.size() - 1;
2598 
2599  while (idList.size() > previousSize) {
2600  previousSize = idList.size();
2601  if (! _findNextAncestor(dbt, idList)) {
2602  return emptyList;
2603  }
2604  }
2605 
2606  for (uint32_t cfgIdx = 0; cfgIdx < idList.size(); ++cfgIdx) {
2607  dbt->Clear();
2608  dbt->SetValidityRange(ID_COLUMN_NAME, idList[cfgIdx]);
2609  if (! dbt->LoadFromDB() || dbt->NRow() != 1) {
2610  return emptyList;
2611  }
2612  NamedConfigDetailsPtr detailsPtr(new NamedConfigDetails());
2613  std::string columnValue;
2614  NOVADB::Row* rowPtr = dbt->GetRow(0);
2615  for (int idx = 0; idx < dbt->NCol(); ++idx) {
2616  NOVADB::Column& colRef = rowPtr->Col(idx);
2617  if (colRef.IsNull()) {
2618  (*detailsPtr)[colRef.Name()] = "";
2619  }
2620  else if (colRef.Get(columnValue)) {
2621  (*detailsPtr)[colRef.Name()] = columnValue;
2622  }
2623  else {
2624  return emptyList;
2625  }
2626  }
2627  detailsList.push_back(detailsPtr);
2628  }
2629  return detailsList;
2630 }
2631 
2632 /**
2633  * Returns the specified field from the details collection. If the
2634  * requested field is not found, this method returns false.
2635  */
2636 bool NamedConfigUtils::
2638  const std::string& fieldName,
2639  std::string& fieldValue)
2640 {
2641  if (details.get() == 0) {return false;}
2642  NamedConfigDetails::const_iterator iter = details->find(fieldName);
2643  if (iter != details->end()) {
2644  fieldValue = iter->second;
2645  return true;
2646  }
2647  return false;
2648 }
2649 
2650 /**
2651  * Fetches the column values for the specified selection criteria.
2652  *
2653  * @param dbt A shared pointer to the database table that contains
2654  * the named configurations.
2655  * @param selections The selection criteria.
2656  *
2657  * @returns an empty pointer if something failed, otherwise valid details
2658  */
2660 _getDetails(const boost::shared_ptr<NOVADB::Table>& dbt,
2661  const NamedConfigSelectionCriteria& selections)
2662 {
2663  NamedConfigDetailsPtr detailsPtr;
2664  dbt->Clear();
2665 
2666  NamedConfigSelectionCriteria::const_iterator iter;
2667  NamedConfigSelectionCriteria::const_iterator iterEnd =
2668  selections.end();
2669  for (iter = selections.begin(); iter != iterEnd; ++iter) {
2670  std::string columnName = iter->first;
2671  std::string lowBound = iter->second;
2672  std::string highBound = iter->second;
2673  if (columnName == INSERTTIME_COLUMN_NAME) {
2675  }
2676  if (! dbt->SetValidityRange(columnName, lowBound, highBound)) {
2677  return detailsPtr;
2678  }
2679  }
2680 
2681  // explicitly request that later entries be returned first
2682  if (! dbt->AddOrderColumn(ID_COLUMN_NAME)) {return detailsPtr;}
2683  dbt->SetOrderDesc();
2684  //dbt->SetVerbosity(1);
2685  if (dbt->LoadFromDB() && dbt->NRow() > 0) {
2686  NamedConfigDetailsPtr tmpDetailsPtr(new NamedConfigDetails());
2687  std::string columnValue;
2688  NOVADB::Row* rowPtr = dbt->GetRow(0);
2689  for (int idx = 0; idx < dbt->NCol(); ++idx) {
2690  NOVADB::Column& colRef = rowPtr->Col(idx);
2691  if (colRef.IsNull()) {
2692  (*tmpDetailsPtr)[colRef.Name()] = "";
2693  }
2694  else if (colRef.Get(columnValue)) {
2695  (*tmpDetailsPtr)[colRef.Name()] = columnValue;
2696  }
2697  else {
2698  return detailsPtr;
2699  }
2700  }
2701  detailsPtr = tmpDetailsPtr;
2702  }
2703 
2704  return detailsPtr;
2705 }
2706 
2707 /**
2708  * Fetches the database ID for the specified selection criteria.
2709  *
2710  * @param dbt A shared pointer to the database table that contains
2711  * the named configurations.
2712  * @param selections The selection criteria.
2713  * @param id The database ID of the named configuration [output parameter].
2714  * (If the status returned by this method is false, then the value
2715  * returned in this parameter is undefined.)
2716  *
2717  * @returns true if the lookup of the ID of the specified named
2718  * configuration worked, false if not.
2719  */
2720 bool NamedConfigUtils::
2721 _getId(const boost::shared_ptr<NOVADB::Table>& dbt,
2722  const NamedConfigSelectionCriteria& selections,
2723  int64_t& id)
2724 {
2725  NamedConfigDetailsPtr detailsPtr = _getDetails(dbt, selections);
2726 
2727  std::string tmpString;
2728  if (! getFieldValue(detailsPtr, ID_COLUMN_NAME, tmpString)) {return false;}
2729 
2730  try {id = boost::lexical_cast<int64_t>(tmpString);}
2731  catch (...) {return false;}
2732 
2733  return true;
2734 }
2735 
2736 /**
2737  * Finds the next ancestor in the specified list of named configuration
2738  * IDs and adds it to the list.
2739  *
2740  * If there is no ancestor for the latest ID in the list, this method
2741  * returns true, but the idList is unchanged.
2742  *
2743  * @param dbt A shared pointer to the database table that contains
2744  * the named configurations.
2745  * @param idList The list of database IDs for the set of
2746  * named configurations [input/output parameter].
2747  * (If the status returned by this method is false, then the
2748  * values returned in this parameter are undefined.)
2749  *
2750  * @returns true if the lookup of the next ancestor ID worked, false if not.
2751  */
2752 bool NamedConfigUtils::
2753 _findNextAncestor(const boost::shared_ptr<NOVADB::Table>& dbt,
2754  std::vector<int64_t>& idList)
2755 {
2756  if (idList.size() < 1) {return false;}
2757 
2758  dbt->Clear();
2759  int64_t oldestId = idList[idList.size()-1];
2760  dbt->SetValidityRange(ID_COLUMN_NAME, oldestId);
2761  if (dbt->LoadFromDB()) {
2762  if (dbt->NRow() == 1) {
2763  NOVADB::Row* rowPtr = dbt->GetRow(0);
2764  NOVADB::Column* colPtr = rowPtr->Col(PARENTID_COLUMN_NAME);
2765  if (colPtr->IsNull()) {
2766  return true;
2767  }
2768  int64_t parentId;
2769  if (colPtr->Get(parentId)) {
2770  idList.push_back(parentId);
2771  return true;
2772  }
2773  }
2774  }
2775  return false;
2776 }
2777 
2778 /**
2779  * Finds the next child in the specified list of named configuration
2780  * IDs and adds it to the list.
2781  *
2782  * If there is no child for the latest ID in the list, this method
2783  * returns true, but the idList is unchanged.
2784  *
2785  * @param dbt A shared pointer to the database table that contains
2786  * the named configurations.
2787  * @param idList The list of database IDs for the set of
2788  * named configurations [input/output parameter].
2789  * (If the status returned by this method is false, then the
2790  * values returned in this parameter are undefined.)
2791  *
2792  * @returns true if the lookup of the next child ID worked, false if not.
2793  */
2794 bool NamedConfigUtils::
2795 _findNextChild(const boost::shared_ptr<NOVADB::Table>& dbt,
2796  std::vector<int64_t>& idList)
2797 {
2798  if (idList.size() < 1) {return false;}
2799 
2800  dbt->Clear();
2801  int64_t newestId = idList[idList.size()-1];
2802  dbt->SetValidityRange(PARENTID_COLUMN_NAME, newestId);
2803  dbt->SetValidityRange(ISOBSOLETE_COLUMN_NAME, false);
2804  dbt->SetValidityRange(ISCHANGING_COLUMN_NAME, false);
2805  dbt->SetValidityRange(ISCOMPLETE_COLUMN_NAME, true);
2806  if (! dbt->LoadFromDB()) {return false;}
2807 
2808  if (dbt->NRow() == 0) {return true;}
2809 
2810  NOVADB::Row* rowPtr = dbt->GetRow(0);
2811  NOVADB::Column* colPtr = rowPtr->Col(ID_COLUMN_NAME);
2812  int64_t thisId;
2813  if (! colPtr->Get(thisId)) {return false;}
2814 
2815  idList.push_back(thisId);
2816  return true;
2817 }
2818 
2819 } // end of namespace daqconfig
2820 } // end of namespace dbutils
static bool getSubsystemConfigId(const SubsystemNameSpec &subsystemNameSpec, int64_t &subsystemConfigId, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
static const std::string GLOBALCFGID_COLUMN_NAME
std::string getDetectorId() const
static const std::string USAGECOUNT_COLUMN_NAME
std::vector< GlobalNameSpec > GlobalNameSpecList
static const std::string ISCHANGING_COLUMN_NAME
static const std::string DESCRIPTION_COLUMN_NAME
static bool getGlobalConfigId(const GlobalNameSpec &globalNameSpec, int64_t &globalConfigId, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string DEFAULT_GLOBAL_NAMES_TABLE_FILE
bool isSlowControlsConfiguration() const
Definition: IDSpec.h:42
int status
Definition: fabricate.py:1613
boost::shared_ptr< NamedConfigDetails > NamedConfigDetailsPtr
static const std::string DEFAULT_DCS_GLOBAL_NAMES_TABLE_FILE
static bool getAvailableSubsystemConfigs(IDSpec::MAJOR_SYSTEM_TYPE daqOrSlowControls, const std::string &detectorName, const std::string &subsystemName, const std::string &configType, SubsystemNameSpecMap &resultsTable, int maxDetailCountPerSummary=10, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
static bool getConfigIdAncestry(const IDSpec &idSpec, std::vector< int64_t > &idList, const std::string &tableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static GlobalNameSpecPtr getNewestInstanceOfLatestUsedDAQGlobalConfig(const std::string &detectorName, const int &partitionNumber, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static bool getSubsystemConfigIdsFromGlobalId(const IDSpec &idSpec, std::vector< int64_t > &idList, std::vector< SubsystemNameSpec > &subsystemNameSpecList, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
static bool getAvailableGlobalConfigs(IDSpec::MAJOR_SYSTEM_TYPE daqOrSlowControls, const std::string &detectorName, GlobalNameSpecMap &resultsTable, int maxDetailCountPerSummary=10, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
int64_t getConfigId() const
Definition: IDSpec.h:36
static std::string GetCurrentTimeAsString()
Definition: Util.cpp:34
static const std::string INSERTTIME_COLUMN_NAME
static EnvVarCache & getInstance()
Definition: EnvVarCache.cpp:12
static const int32_t COPY_FOUND_INTERMEDIATE_UPDATE
int32_t code
Definition: Status.h:22
static const std::string DETECTORID_COLUMN_NAME
string trim(string in)
Definition: rootgINukeVal.C:65
static bool _findNextChild(const boost::shared_ptr< nova::database::Table > &dbt, std::vector< int64_t > &idList)
bool Update(std::string cname, T value)
Definition: Row.h:37
std::map< SubsystemNameSpec, std::vector< SubsystemNameSpec > > SubsystemNameSpecMap
static const std::string ISCOMPLETE_COLUMN_NAME
std::map< std::string, std::string > NamedConfigSelectionCriteria
static NamedConfigDetailsPtr _getDetails(const boost::shared_ptr< nova::database::Table > &dbt, const NamedConfigSelectionCriteria &selections)
std::map< GlobalNameSpec, std::vector< GlobalNameSpec > > GlobalNameSpecMap
static bool getSubsystemConfigIdAncestry(const SubsystemNameSpec &subsystemNameSpec, std::vector< int64_t > &idList, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
static NamedConfigDetailsPtr getNewestGlobalConfigFromSubsystemName(const SubsystemNameSpec &subsystemNameSpec, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string DCMOPMODE_COLUMN_NAME
static const std::string CONFIGTYPE_COLUMN_NAME
static bool incrementUsageCount(const IDSpec &idSpec, const std::string &tableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
bool get(const std::string &key, T &resultValue) const
static std::vector< NamedConfigDetailsPtr > getSubsystemConfigsFromGlobalId(const IDSpec &idSpec, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
const XML_Char int const XML_Char * value
Definition: expat.h:331
static novadaq::Status copyGlobalConfig(const IDSpec &sourceId, bool makeParentChildLink, const SimpleParameterSet &valuesToOverride, std::string baselineTimestamp, bool overrideIntermediateUpdate, int64_t &resultId, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string UPDATEUSER_COLUMN_NAME
boost::shared_ptr< GlobalNameSpec > GlobalNameSpecPtr
static const std::string DETECTORNAME_COLUMN_NAME
static const std::string UPDATETIME_COLUMN_NAME
static const std::string ID_COLUMN_NAME
std::string getDCMOpMode() const
std::string getTimestamp() const
bool Get(T &val) const
Definition: Column.h:53
static const std::string SUBSYSTEMNAME_COLUMN_NAME
static std::vector< NamedConfigDetailsPtr > getConfigDetailAncestry(const IDSpec &idSpec, const std::string &tableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
bool IsNull() const
Definition: Column.h:39
pg_result PGresult
Definition: Table.h:25
static novadaq::Status copySubsystemConfig(const IDSpec &sourceId, bool makeParentChildLink, const SimpleParameterSet &valuesToOverride, std::string baselineTimestamp, bool overrideIntermediateUpdate, int64_t &resultId, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
static bool _getId(const boost::shared_ptr< nova::database::Table > &dbt, const NamedConfigSelectionCriteria &selections, int64_t &id)
static bool getSubsystemConfigIdFromGlobalName(const GlobalNameSpec &globalNameSpec, const std::string &subsystemName, const std::string &subsystemConfigType, int64_t &subsystemConfigId, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
static NamedConfigDetailsPtr getNewestGlobalConfigFromSubsystemId(const IDSpec &idSpec, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
static const std::string NDOS_DETECTOR_NAME
std::string Name() const
Definition: Column.h:35
static const std::string DEFAULT_DCS_SUBSYSTEM_NAMES_TABLE_FILE
static NamedConfigDetailsPtr getNewestGlobalConfigFromGlobalId(const IDSpec &idSpec, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string FAR_DETECTOR_NAME
std::map< std::string, std::string > NamedConfigDetails
static bool _findNextAncestor(const boost::shared_ptr< nova::database::Table > &dbt, std::vector< int64_t > &idList)
static const int32_t COPY_FOUND_UPDATE_IN_PROGRESS
struct Table Table
Definition: TexBuilder.h:2
std::string getEnvVar(std::string name)
Definition: EnvVarCache.cpp:33
std::string message
Definition: Status.h:24
static const std::string PARENTID_COLUMN_NAME
static std::string GetFarPastTimeAsString()
Definition: Util.cpp:60
std::string getConfigName() const
static bool markConfigDone(const IDSpec &idSpec, bool alsoComplete=false, const std::string &tableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string ISOBSOLETE_COLUMN_NAME
static bool getRecentGlobalConfigs(IDSpec::MAJOR_SYSTEM_TYPE daqOrSlowControls, const std::string &detectorName, int resultOffset, int resultLimit, GlobalNameSpecList &resultList, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE
static bool getSubsystemConfigIdFromGlobalId(const IDSpec &idSpec, const std::string &subsystemName, const std::string &subsystemConfigType, int64_t &subsystemConfigId, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
bool isDAQConfiguration() const
Definition: IDSpec.h:41
static bool getFieldValue(const NamedConfigDetailsPtr &details, const std::string &fieldName, std::string &fieldValue)
static const std::string LATEST_TIME_STRING
static bool DetNameOk(std::string name)
static const std::string NAME_COLUMN_NAME
static bool getGlobalConfigIdAncestry(const GlobalNameSpec &globalNameSpec, std::vector< int64_t > &idList, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)
static const std::string INSERTUSER_COLUMN_NAME
static const std::string SUBSYSCFGID_COLUMN_NAME
static const std::string NEAR_DETECTOR_NAME
std::string Type() const
Definition: Column.h:36
detName
Definition: mkDefs.py:106
bool isGlobalConfiguration() const
Definition: IDSpec.h:38
static bool getSubsystemConfigIdAncestryFromGlobalId(const IDSpec &globalConfigId, const std::string &subsystemName, const std::string &subsystemConfigType, std::vector< int64_t > &idList, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE, const std::string &subsystemNamesTableFile=DEFAULT_SUBSYSTEM_NAMES_TABLE_FILE)
Column & Col(int i)
Definition: Row.h:51
static std::vector< NamedConfigDetailsPtr > getGlobalConfigDetailAncestry(const GlobalNameSpec &globalNameSpec, const std::string &globalNamesTableFile=DEFAULT_GLOBAL_NAMES_TABLE_FILE)