00001 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationBase.h"
00002 #include "otsdaq-core/ConfigurationDataFormats/ConfigurationInfoReader.h"
00003
00004 #include <iostream>
00005 #include <typeinfo>
00006
00007
00008 using namespace ots;
00009
00010
00011 #undef __MF_SUBJECT__
00012 #define __MF_SUBJECT__ "ConfigurationBase"
00013 #undef __MF_HDR__
00014 #define __MF_HDR__ __COUT_HDR_FL__ << getConfigurationName() << ": "
00015
00016
00017
00018
00019
00020
00021
00022 ConfigurationBase::ConfigurationBase(std::string configurationName,
00023 std::string *accumulatedExceptions)
00024 : MAX_VIEWS_IN_CACHE (5)
00025 , configurationName_ (configurationName)
00026 , activeConfigurationView_(0)
00027 {
00028
00029 ConfigurationInfoReader configurationInfoReader(accumulatedExceptions);
00030 try
00031 {
00032 std::string returnedExceptions = configurationInfoReader.read(this);
00033
00034 if(returnedExceptions != "")
00035 __MOUT_ERR__ << returnedExceptions << std::endl;
00036
00037 if(accumulatedExceptions) *accumulatedExceptions += std::string("\n") + returnedExceptions;
00038 }
00039 catch(...)
00040 {
00041 __SS__ << "Failure in configurationInfoReader.read(this)" << std::endl;
00042 __MOUT_ERR__ << "\n" << ss.str();
00043 if(accumulatedExceptions) *accumulatedExceptions += std::string("\n") +
00044 ss.str();
00045 else throw;
00046 return;
00047 }
00048
00049
00050 try
00051 {
00052 getMockupViewP()->init();
00053 }
00054 catch(std::runtime_error& e)
00055 {
00056 if(accumulatedExceptions) *accumulatedExceptions += std::string("\n") + e.what();
00057 else throw;
00058 }
00059 }
00060
00061
00062
00063
00064
00065 ConfigurationBase::ConfigurationBase(void)
00066 : MAX_VIEWS_IN_CACHE (1)
00067 , configurationName_ ("")
00068 , activeConfigurationView_(0)
00069 {
00070 }
00071
00072
00073 ConfigurationBase::~ConfigurationBase(void)
00074 {
00075 }
00076
00077
00078 std::string ConfigurationBase::getTypeId()
00079 {
00080 return typeid(this).name();
00081 }
00082
00083
00084 void ConfigurationBase::init(ConfigurationManager *configurationManager)
00085 {
00086
00087 }
00088
00089
00090 void ConfigurationBase::reset(bool keepTemporaryVersions)
00091 {
00092
00093 deactivate();
00094 if(keepTemporaryVersions)
00095 trimCache(0);
00096 else
00097 configurationViews_.clear();
00098 }
00099
00100
00101 void ConfigurationBase::print(std::ostream &out) const
00102 {
00103
00104 if(!activeConfigurationView_)
00105 {
00106 __MOUT_ERR__ << "ERROR: No active view set" << std::endl;
00107 return;
00108 }
00109 activeConfigurationView_->print(out);
00110 }
00111
00112
00113
00114
00115 void ConfigurationBase::setupMockupView(ConfigurationVersion version)
00116 {
00117 if(!isStored(version))
00118 {
00119 configurationViews_[version].copy(mockupConfigurationView_,
00120 version,
00121 mockupConfigurationView_.getAuthor());
00122 trimCache();
00123 if(!isStored(version))
00124 {
00125 __SS__ << "\nsetupMockupView() IMPOSSIBLE ERROR: trimCache() is deleting the latest view version " <<
00126 version << "!" << std::endl;
00127 __MOUT_ERR__ << "\n" << ss.str();
00128 throw std::runtime_error(ss.str());
00129 }
00130 }
00131 else
00132 {
00133 __SS__ << "\nsetupMockupView() ERROR: View to fill with mockup already exists: " << version
00134 << ". Cannot overwrite!" << std::endl;
00135 __MOUT_ERR__ << "\n" << ss.str();
00136 throw std::runtime_error(ss.str());
00137 }
00138 }
00139
00140
00141
00142
00143
00144
00145
00146 void ConfigurationBase::trimCache(unsigned int trimSize)
00147 {
00148
00149
00150 if(trimSize == (unsigned int)-1)
00151 trimSize = MAX_VIEWS_IN_CACHE;
00152
00153 int i=0;
00154 while(getNumberOfStoredViews() > trimSize)
00155 {
00156 ConfigurationVersion versionToDelete;
00157 time_t stalestTime = -1;
00158
00159 for(auto &viewPair : configurationViews_)
00160 if(!viewPair.first.isTemporaryVersion())
00161 {
00162 if(stalestTime == -1 ||
00163 viewPair.second.getLastAccessTime() < stalestTime)
00164 {
00165 versionToDelete = viewPair.first;
00166 stalestTime = viewPair.second.getLastAccessTime();
00167 if(!trimSize) break;
00168 }
00169 }
00170
00171 if(versionToDelete.isInvalid())
00172 {
00173 __SS__ << "Can NOT have a stored view with an invalid version!";
00174 throw std::runtime_error(ss.str());
00175 }
00176
00177 eraseView(versionToDelete);
00178 }
00179 }
00180
00181
00182
00183
00184
00185
00186 void ConfigurationBase::trimTemporary(ConfigurationVersion targetVersion)
00187 {
00188 if(targetVersion.isInvalid())
00189 {
00190 for(auto it = configurationViews_.begin(); it != configurationViews_.end(); )
00191 {
00192 if(it->first.isTemporaryVersion())
00193 {
00194 __MOUT__ << "Trimming temporary version: " << it->first << std::endl;
00195 if(activeConfigurationView_ &&
00196 getViewVersion() == it->first)
00197 deactivate();
00198 configurationViews_.erase(it++);
00199 }
00200 else
00201 ++it;
00202 }
00203 }
00204 else if(targetVersion.isTemporaryVersion())
00205 {
00206 __MOUT__ << "Trimming temporary version: " << targetVersion << std::endl;
00207 eraseView(targetVersion);
00208 }
00209 else
00210 {
00211
00212 __SS__ << "Temporary trim target was a persistent version: " <<
00213 targetVersion << std::endl;
00214 __MOUT_ERR__ << "\n" << ss.str();
00215 throw std::runtime_error(ss.str());
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 ConfigurationVersion ConfigurationBase::checkForDuplicate(ConfigurationVersion needleVersion,
00229 ConfigurationVersion ignoreVersion) const
00230 {
00231 auto needleIt = configurationViews_.find(needleVersion);
00232 if(needleIt == configurationViews_.end())
00233 {
00234
00235 __SS__ << "needleVersion does not exist: " <<
00236 needleVersion << std::endl;
00237 __MOUT_ERR__ << "\n" << ss.str();
00238 throw std::runtime_error(ss.str());
00239 }
00240
00241 const ConfigurationView *needleView = &(needleIt->second);
00242 unsigned int rows = needleView->getNumberOfRows();
00243 unsigned int cols = needleView->getNumberOfColumns();
00244
00245 bool match;
00246
00247
00248 for(auto &viewPair: configurationViews_)
00249 {
00250 if(viewPair.first == needleVersion) continue;
00251 if(viewPair.first == ignoreVersion) continue;
00252
00253 if(viewPair.second.getNumberOfRows() != rows)
00254 continue;
00255
00256 if(viewPair.second.getSourceColumnSize() != cols ||
00257 viewPair.second.getSourceColumnMismatch() != 0)
00258 continue;
00259
00260
00261 match = true;
00262
00263 auto srcColNameIt = viewPair.second.getSourceColumnNames().begin();
00264 for(unsigned int col=0; match &&
00265 col<viewPair.second.getSourceColumnNames().size()-3;++col,srcColNameIt++)
00266 if(*srcColNameIt !=
00267 needleView->getColumnsInfo()[col].getName())
00268 match = false;
00269
00270 for(unsigned int row=0;match && row<rows;++row)
00271 {
00272 for(unsigned int col=0;col<cols-2;++col)
00273 if(viewPair.second.getDataView()[row][col] !=
00274 needleView->getDataView()[row][col])
00275 { match = false; break; }
00276 }
00277 if(match)
00278 {
00279 __MOUT_INFO__ << "Duplicate version found: " << viewPair.first << std::endl;
00280 return viewPair.first;
00281 }
00282 }
00283
00284 return ConfigurationVersion();
00285 }
00286
00287
00288 void ConfigurationBase::changeVersionAndActivateView(ConfigurationVersion temporaryVersion,
00289 ConfigurationVersion version)
00290 {
00291 if(configurationViews_.find(temporaryVersion) == configurationViews_.end())
00292 {
00293 __SS__ << "ERROR: Temporary view version " << temporaryVersion << " doesn't exists!" << std::endl;
00294 __MOUT_ERR__ << "\n" << ss.str();
00295 throw std::runtime_error(ss.str());
00296 }
00297 if(version.isInvalid())
00298 {
00299 __SS__ << "ERROR: Attempting to create an invalid version " << version <<
00300 "! Did you really run out of versions? (this should never happen)" << std::endl;
00301 __MOUT_ERR__ << "\n" << ss.str();
00302 throw std::runtime_error(ss.str());
00303 }
00304
00305 if(configurationViews_.find(version) != configurationViews_.end())
00306 __MOUT_WARN__ << "WARNING: View version " << version << " already exists! Overwriting." << std::endl;
00307
00308 configurationViews_[version].copy(configurationViews_[temporaryVersion],
00309 version,
00310 configurationViews_[temporaryVersion].getAuthor());
00311 setActiveView(version);
00312 eraseView(temporaryVersion);
00313 }
00314
00315
00316 bool ConfigurationBase::isStored(const ConfigurationVersion &version) const
00317 {
00318 return (configurationViews_.find(version) != configurationViews_.end());
00319 }
00320
00321
00322 bool ConfigurationBase::eraseView(ConfigurationVersion version)
00323 {
00324 if(!isStored(version))
00325 return false;
00326
00327 if(activeConfigurationView_ &&
00328 getViewVersion() == version)
00329 deactivate();
00330
00331 configurationViews_.erase(version);
00332
00333 return true;
00334 }
00335
00336
00337 const std::string& ConfigurationBase::getConfigurationName(void) const
00338 {
00339 return configurationName_;
00340 }
00341
00342
00343 const std::string& ConfigurationBase::getConfigurationDescription(void) const
00344 {
00345 return configurationDescription_;
00346 }
00347
00348
00349 const ConfigurationVersion& ConfigurationBase::getViewVersion(void) const
00350 {
00351 return getView().getVersion();
00352 }
00353
00354
00355
00356
00357
00358 bool ConfigurationBase::latestAndMockupColumnNumberMismatch(void) const
00359 {
00360 std::set<ConfigurationVersion> retSet = getStoredVersions();
00361 if(retSet.size() && !retSet.rbegin()->isTemporaryVersion())
00362 {
00363 return configurationViews_.find(*(retSet.rbegin()))->second.getNumberOfColumns() !=
00364 mockupConfigurationView_.getNumberOfColumns();
00365 }
00366
00367 return true;
00368 }
00369
00370
00371 std::set<ConfigurationVersion> ConfigurationBase::getStoredVersions(void) const
00372 {
00373 std::set<ConfigurationVersion> retSet;
00374 for(auto &configs:configurationViews_)
00375 retSet.emplace(configs.first);
00376 return retSet;
00377 }
00378
00379
00380
00381
00382
00383 unsigned int ConfigurationBase::getNumberOfStoredViews(void) const
00384 {
00385 unsigned int sz = 0;
00386 for(auto &viewPair : configurationViews_)
00387 if(viewPair.first.isTemporaryVersion()) continue;
00388 else if(viewPair.first.isInvalid())
00389 {
00390
00391
00392
00393
00394
00395
00396
00397 __MOUT__ << "There is an invalid version now!.. where did it come from?" << std::endl;
00398 }
00399 else ++sz;
00400 return sz;
00401 }
00402
00403
00404 const ConfigurationView& ConfigurationBase::getView(void) const
00405 {
00406 if(!activeConfigurationView_)
00407 {
00408 __SS__ << "activeConfigurationView_ pointer is null! (...likely the active view was not setup properly. Check your system setup.)";
00409 throw std::runtime_error(ss.str());
00410 }
00411 return *activeConfigurationView_;
00412 }
00413
00414
00415 ConfigurationView* ConfigurationBase::getViewP(void)
00416 {
00417 if(!activeConfigurationView_)
00418 {
00419 __SS__ << "activeConfigurationView_ pointer is null! (...likely the active view was not setup properly. Check your system setup.)";
00420 throw std::runtime_error(ss.str());
00421 }
00422 return activeConfigurationView_;
00423 }
00424
00425
00426 ConfigurationView* ConfigurationBase::getMockupViewP(void)
00427 {
00428 return &mockupConfigurationView_;
00429 }
00430
00431
00432 void ConfigurationBase::setConfigurationName(const std::string &configurationName)
00433 {
00434 configurationName_ = configurationName;
00435 }
00436
00437
00438 void ConfigurationBase::setConfigurationDescription(const std::string &configurationDescription)
00439 {
00440 configurationDescription_ = configurationDescription;
00441 }
00442
00443
00444
00445
00446 void ConfigurationBase::deactivate()
00447 {
00448 activeConfigurationView_ = 0;
00449 }
00450
00451
00452
00453 bool ConfigurationBase::isActive()
00454 {
00455 return activeConfigurationView_?true:false;
00456 }
00457
00458
00459 bool ConfigurationBase::setActiveView(ConfigurationVersion version)
00460 {
00461 if(!isStored(version))
00462 {
00463
00464 __SS__ << "\nsetActiveView() ERROR: View with version " << version <<
00465 " has never been stored before!" << std::endl;
00466 __MOUT_ERR__ << "\n" << ss.str();
00467 throw std::runtime_error(ss.str());
00468 return false;
00469 }
00470 activeConfigurationView_ = &configurationViews_[version];
00471
00472 if(configurationViews_[version].getVersion() != version)
00473 {
00474 __SS__ << "Something has gone very wrong with the version handling!" << std::endl;
00475 throw std::runtime_error(ss.str());
00476 }
00477
00478 return true;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 ConfigurationVersion ConfigurationBase::copyView (const ConfigurationView &sourceView,
00491 ConfigurationVersion destinationVersion, const std::string &author)
00492 throw(std::runtime_error)
00493 {
00494
00495 if(sourceView.getNumberOfColumns() !=
00496 mockupConfigurationView_.getNumberOfColumns())
00497 {
00498 __SS__ << "Error! Number of Columns of source view must match destination mock-up view." <<
00499 "Dimension of source is [" << sourceView.getNumberOfColumns() <<
00500 "] and of destination mockup is [" <<
00501 mockupConfigurationView_.getNumberOfColumns() << "]." << std::endl;
00502 throw std::runtime_error(ss.str());
00503 }
00504
00505
00506 if(!destinationVersion.isInvalid() &&
00507 configurationViews_.find(sourceView.getVersion()) != configurationViews_.end())
00508 {
00509 __SS__ << "Error! Asked to copy a view with a conflicting version: " <<
00510 sourceView.getVersion() << std::endl;
00511 throw std::runtime_error(ss.str());
00512 }
00513
00514
00515 destinationVersion = createTemporaryView(ConfigurationVersion(),
00516 destinationVersion);
00517
00518 __MOUT__ << "Copying from " << sourceView.getTableName() << "_v" <<
00519 sourceView.getVersion() << " to " << getConfigurationName() << "_v" <<
00520 destinationVersion << std::endl;
00521
00522 try
00523 {
00524 configurationViews_[destinationVersion].copy(sourceView,destinationVersion,author);
00525 }
00526 catch(...)
00527 {
00528 __MOUT_ERR__ << "Failed to copy from " << sourceView.getTableName() << "_v" <<
00529 sourceView.getVersion() << " to " << getConfigurationName() << "_v" <<
00530 destinationVersion << std::endl;
00531 __MOUT_WARN__ << "Deleting the failed destination version " <<
00532 destinationVersion << std::endl;
00533 eraseView(destinationVersion);
00534 throw;
00535 }
00536 return destinationVersion;
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 ConfigurationVersion ConfigurationBase::createTemporaryView(ConfigurationVersion sourceViewVersion,
00547 ConfigurationVersion destTemporaryViewVersion)
00548 {
00549 __MOUT__ << "Configuration: " <<
00550 getConfigurationName()<< std::endl;
00551
00552 __MOUT__ << "Num of Views: " <<
00553 configurationViews_.size() << " (Temporary Views: " <<
00554 (configurationViews_.size() - getNumberOfStoredViews()) << ")" << std::endl;
00555
00556 ConfigurationVersion tmpVersion = destTemporaryViewVersion;
00557 if(tmpVersion.isInvalid()) tmpVersion = ConfigurationVersion::getNextTemporaryVersion();
00558 while(isStored(tmpVersion) &&
00559 !(tmpVersion = ConfigurationVersion::getNextTemporaryVersion(tmpVersion)).isInvalid());
00560 if(isStored(tmpVersion) || tmpVersion.isInvalid())
00561 {
00562 __MOUT_ERR__ << "Invalid destination temporary version: " <<
00563 destTemporaryViewVersion << ". Expected next temporary version < " << tmpVersion << std::endl;
00564 throw std::runtime_error("Invalid temporary version destination");
00565 }
00566
00567 if(sourceViewVersion == ConfigurationVersion::INVALID ||
00568 configurationViews_.find(sourceViewVersion) == configurationViews_.end())
00569 {
00570 if(sourceViewVersion != -1)
00571 {
00572 __MOUT_ERR__ << "ERROR: sourceViewVersion " << sourceViewVersion << " not found" << std::endl;
00573 throw std::runtime_error("Invalid source version. Version requested is not stored (yet?) or does not exist.");
00574 }
00575 __MOUT__ << "Using Mock-up view" << std::endl;
00576 configurationViews_[tmpVersion].copy(mockupConfigurationView_,
00577 tmpVersion,
00578 mockupConfigurationView_.getAuthor());
00579 }
00580 else
00581 {
00582 try
00583 {
00584 configurationViews_[tmpVersion].copy(configurationViews_[sourceViewVersion],
00585 tmpVersion,
00586 configurationViews_[sourceViewVersion].getAuthor());
00587 }
00588 catch(...)
00589 {
00590 __MOUT_WARN__ << "createTemporaryView() Source view failed init(). " <<
00591 "This is being ignored (hopefully the new copy is being fixed)." << std::endl;
00592 }
00593 }
00594
00595 return tmpVersion;
00596 }
00597
00598
00599
00600
00601
00602 ConfigurationVersion ConfigurationBase::getNextTemporaryVersion() const
00603 {
00604 ConfigurationVersion tmpVersion;
00605
00606
00607 if(configurationViews_.size() != 0 && configurationViews_.begin()->first.isTemporaryVersion())
00608 tmpVersion =
00609 ConfigurationVersion::getNextTemporaryVersion(configurationViews_.begin()->first);
00610 else
00611 tmpVersion = ConfigurationVersion::getNextTemporaryVersion();
00612
00613
00614 if(isStored(tmpVersion) || tmpVersion.isInvalid() || !tmpVersion.isTemporaryVersion())
00615 {
00616 __MOUT_ERR__ << "Invalid destination temporary version: " <<
00617 tmpVersion << std::endl;
00618 throw std::runtime_error("Invalid temporary version found");
00619 }
00620 return tmpVersion;
00621 }
00622
00623
00624
00625
00626
00627 ConfigurationVersion ConfigurationBase::getNextVersion() const
00628 {
00629 ConfigurationVersion tmpVersion;
00630
00631
00632 if(configurationViews_.size() != 0 && !configurationViews_.rbegin()->first.isTemporaryVersion())
00633 tmpVersion =
00634 ConfigurationVersion::getNextVersion(configurationViews_.rbegin()->first);
00635 else
00636 tmpVersion = ConfigurationVersion::getNextVersion();
00637
00638
00639 if(isStored(tmpVersion) || tmpVersion.isInvalid() || tmpVersion.isTemporaryVersion())
00640 {
00641 __MOUT_ERR__ << "Invalid destination next version: " <<
00642 tmpVersion << std::endl;
00643 throw std::runtime_error("Invalid next version found");
00644 }
00645 return tmpVersion;
00646 }
00647
00648
00649
00650
00651
00652 ConfigurationView* ConfigurationBase::getTemporaryView(ConfigurationVersion temporaryVersion)
00653 {
00654 if(!temporaryVersion.isTemporaryVersion() ||
00655 !isStored(temporaryVersion))
00656 {
00657 __MOUT_ERR__ << getConfigurationName() << ":: Error! Temporary version not found!" << std::endl;
00658 throw std::runtime_error("Invalid temporary version");
00659 }
00660 return &configurationViews_[temporaryVersion];
00661 }
00662
00663
00664
00665
00666
00667
00668 std::string ConfigurationBase::convertToCaps(std::string& str, bool isConfigName)
00669 throw(std::runtime_error)
00670 {
00671
00672 unsigned int configPos = (unsigned int)std::string::npos;
00673 if(isConfigName && (configPos = str.find("Configuration")) !=
00674 str.size() - strlen("Configuration"))
00675 str += "Configuration";
00676
00677
00678
00679
00680
00681
00682 std::string capsStr = "";
00683 for(unsigned int c=0;c<str.size();++c)
00684 if(str[c] >= 'A' && str[c] <= 'Z')
00685 {
00686
00687 if(c == configPos ||
00688 (c && str[c-1] >= 'a' && str[c-1] <= 'z') ||
00689 (c && str[c-1] >= 'A' && str[c-1] <= 'Z' &&
00690 c+1 < str.size() && str[c+1] >= 'a' && str[c+1] <= 'z')
00691 )
00692 capsStr += "_";
00693 capsStr += str[c];
00694 }
00695 else if(str[c] >= 'a' && str[c] <= 'z')
00696 capsStr += char(str[c] -32);
00697 else if(str[c] >= '0' && str[c] <= '9')
00698 capsStr += str[c];
00699 else
00700 throw std::runtime_error(std::string("ConfigurationBase::convertToCaps::") +
00701 "Invalid character found in name (allowed: A-Z, a-z, 0-9):" +
00702 str );
00703
00704 return capsStr;
00705 }
00706
00707
00708
00709