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.getDataColumnSize() != 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 viewPair.second.getSourceColumnNames().size() > 3 &&
00266 col<viewPair.second.getSourceColumnNames().size()-3;++col,srcColNameIt++)
00267 if(*srcColNameIt !=
00268 needleView->getColumnsInfo()[col].getName())
00269 match = false;
00270
00271 for(unsigned int row=0;match && row<rows;++row)
00272 {
00273 for(unsigned int col=0;col<cols-2;++col)
00274 if(viewPair.second.getDataView()[row][col] !=
00275 needleView->getDataView()[row][col])
00276 { match = false; break; }
00277 }
00278 if(match)
00279 {
00280 __MOUT_INFO__ << "Duplicate version found: " << viewPair.first << std::endl;
00281 return viewPair.first;
00282 }
00283 }
00284
00285 return ConfigurationVersion();
00286 }
00287
00288
00289 void ConfigurationBase::changeVersionAndActivateView(ConfigurationVersion temporaryVersion,
00290 ConfigurationVersion version)
00291 {
00292 if(configurationViews_.find(temporaryVersion) == configurationViews_.end())
00293 {
00294 __SS__ << "ERROR: Temporary view version " << temporaryVersion << " doesn't exists!" << std::endl;
00295 __MOUT_ERR__ << "\n" << ss.str();
00296 throw std::runtime_error(ss.str());
00297 }
00298 if(version.isInvalid())
00299 {
00300 __SS__ << "ERROR: Attempting to create an invalid version " << version <<
00301 "! Did you really run out of versions? (this should never happen)" << std::endl;
00302 __MOUT_ERR__ << "\n" << ss.str();
00303 throw std::runtime_error(ss.str());
00304 }
00305
00306 if(configurationViews_.find(version) != configurationViews_.end())
00307 __MOUT_WARN__ << "WARNING: View version " << version << " already exists! Overwriting." << std::endl;
00308
00309 configurationViews_[version].copy(configurationViews_[temporaryVersion],
00310 version,
00311 configurationViews_[temporaryVersion].getAuthor());
00312 setActiveView(version);
00313 eraseView(temporaryVersion);
00314 }
00315
00316
00317 bool ConfigurationBase::isStored(const ConfigurationVersion &version) const
00318 {
00319 return (configurationViews_.find(version) != configurationViews_.end());
00320 }
00321
00322
00323 bool ConfigurationBase::eraseView(ConfigurationVersion version)
00324 {
00325 if(!isStored(version))
00326 return false;
00327
00328 if(activeConfigurationView_ &&
00329 getViewVersion() == version)
00330 deactivate();
00331
00332 configurationViews_.erase(version);
00333
00334 return true;
00335 }
00336
00337
00338 const std::string& ConfigurationBase::getConfigurationName(void) const
00339 {
00340 return configurationName_;
00341 }
00342
00343
00344 const std::string& ConfigurationBase::getConfigurationDescription(void) const
00345 {
00346 return configurationDescription_;
00347 }
00348
00349
00350 const ConfigurationVersion& ConfigurationBase::getViewVersion(void) const
00351 {
00352 return getView().getVersion();
00353 }
00354
00355
00356
00357
00358
00359 bool ConfigurationBase::latestAndMockupColumnNumberMismatch(void) const
00360 {
00361 std::set<ConfigurationVersion> retSet = getStoredVersions();
00362 if(retSet.size() && !retSet.rbegin()->isTemporaryVersion())
00363 {
00364 return configurationViews_.find(*(retSet.rbegin()))->second.getNumberOfColumns() !=
00365 mockupConfigurationView_.getNumberOfColumns();
00366 }
00367
00368 return true;
00369 }
00370
00371
00372 std::set<ConfigurationVersion> ConfigurationBase::getStoredVersions(void) const
00373 {
00374 std::set<ConfigurationVersion> retSet;
00375 for(auto &configs:configurationViews_)
00376 retSet.emplace(configs.first);
00377 return retSet;
00378 }
00379
00380
00381
00382
00383
00384 unsigned int ConfigurationBase::getNumberOfStoredViews(void) const
00385 {
00386 unsigned int sz = 0;
00387 for(auto &viewPair : configurationViews_)
00388 if(viewPair.first.isTemporaryVersion()) continue;
00389 else if(viewPair.first.isInvalid())
00390 {
00391
00392
00393
00394
00395
00396
00397
00398 __MOUT__ << "There is an invalid version now!.. where did it come from?" << std::endl;
00399 }
00400 else ++sz;
00401 return sz;
00402 }
00403
00404
00405 const ConfigurationView& ConfigurationBase::getView(void) const
00406 {
00407 if(!activeConfigurationView_)
00408 {
00409 __SS__ << "activeConfigurationView_ pointer is null! (...likely the active view was not setup properly. Check your system setup.)";
00410 throw std::runtime_error(ss.str());
00411 }
00412 return *activeConfigurationView_;
00413 }
00414
00415
00416 ConfigurationView* ConfigurationBase::getViewP(void)
00417 {
00418 if(!activeConfigurationView_)
00419 {
00420 __SS__ << "activeConfigurationView_ pointer is null! (...likely the active view was not setup properly. Check your system setup.)";
00421 throw std::runtime_error(ss.str());
00422 }
00423 return activeConfigurationView_;
00424 }
00425
00426
00427 ConfigurationView* ConfigurationBase::getMockupViewP(void)
00428 {
00429 return &mockupConfigurationView_;
00430 }
00431
00432
00433 void ConfigurationBase::setConfigurationName(const std::string &configurationName)
00434 {
00435 configurationName_ = configurationName;
00436 }
00437
00438
00439 void ConfigurationBase::setConfigurationDescription(const std::string &configurationDescription)
00440 {
00441 configurationDescription_ = configurationDescription;
00442 }
00443
00444
00445
00446
00447 void ConfigurationBase::deactivate()
00448 {
00449 activeConfigurationView_ = 0;
00450 }
00451
00452
00453
00454 bool ConfigurationBase::isActive()
00455 {
00456 return activeConfigurationView_?true:false;
00457 }
00458
00459
00460 bool ConfigurationBase::setActiveView(ConfigurationVersion version)
00461 {
00462 if(!isStored(version))
00463 {
00464
00465 __SS__ << "\nsetActiveView() ERROR: View with version " << version <<
00466 " has never been stored before!" << std::endl;
00467 __MOUT_ERR__ << "\n" << ss.str();
00468 throw std::runtime_error(ss.str());
00469 return false;
00470 }
00471 activeConfigurationView_ = &configurationViews_[version];
00472
00473 if(configurationViews_[version].getVersion() != version)
00474 {
00475 __SS__ << "Something has gone very wrong with the version handling!" << std::endl;
00476 throw std::runtime_error(ss.str());
00477 }
00478
00479 return true;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 ConfigurationVersion ConfigurationBase::copyView (const ConfigurationView &sourceView,
00492 ConfigurationVersion destinationVersion, const std::string &author)
00493 throw(std::runtime_error)
00494 {
00495
00496 if(sourceView.getNumberOfColumns() !=
00497 mockupConfigurationView_.getNumberOfColumns())
00498 {
00499 __SS__ << "Error! Number of Columns of source view must match destination mock-up view." <<
00500 "Dimension of source is [" << sourceView.getNumberOfColumns() <<
00501 "] and of destination mockup is [" <<
00502 mockupConfigurationView_.getNumberOfColumns() << "]." << std::endl;
00503 throw std::runtime_error(ss.str());
00504 }
00505
00506
00507 if(!destinationVersion.isInvalid() &&
00508 configurationViews_.find(sourceView.getVersion()) != configurationViews_.end())
00509 {
00510 __SS__ << "Error! Asked to copy a view with a conflicting version: " <<
00511 sourceView.getVersion() << std::endl;
00512 throw std::runtime_error(ss.str());
00513 }
00514
00515
00516 destinationVersion = createTemporaryView(ConfigurationVersion(),
00517 destinationVersion);
00518
00519 __MOUT__ << "Copying from " << sourceView.getTableName() << "_v" <<
00520 sourceView.getVersion() << " to " << getConfigurationName() << "_v" <<
00521 destinationVersion << std::endl;
00522
00523 try
00524 {
00525 configurationViews_[destinationVersion].copy(sourceView,destinationVersion,author);
00526 }
00527 catch(...)
00528 {
00529 __MOUT_ERR__ << "Failed to copy from " << sourceView.getTableName() << "_v" <<
00530 sourceView.getVersion() << " to " << getConfigurationName() << "_v" <<
00531 destinationVersion << std::endl;
00532 __MOUT_WARN__ << "Deleting the failed destination version " <<
00533 destinationVersion << std::endl;
00534 eraseView(destinationVersion);
00535 throw;
00536 }
00537 return destinationVersion;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547 ConfigurationVersion ConfigurationBase::createTemporaryView(ConfigurationVersion sourceViewVersion,
00548 ConfigurationVersion destTemporaryViewVersion)
00549 {
00550 __MOUT__ << "Configuration: " <<
00551 getConfigurationName()<< std::endl;
00552
00553 __MOUT__ << "Num of Views: " <<
00554 configurationViews_.size() << " (Temporary Views: " <<
00555 (configurationViews_.size() - getNumberOfStoredViews()) << ")" << std::endl;
00556
00557 ConfigurationVersion tmpVersion = destTemporaryViewVersion;
00558 if(tmpVersion.isInvalid()) tmpVersion = ConfigurationVersion::getNextTemporaryVersion();
00559 while(isStored(tmpVersion) &&
00560 !(tmpVersion = ConfigurationVersion::getNextTemporaryVersion(tmpVersion)).isInvalid());
00561 if(isStored(tmpVersion) || tmpVersion.isInvalid())
00562 {
00563 __MOUT_ERR__ << "Invalid destination temporary version: " <<
00564 destTemporaryViewVersion << ". Expected next temporary version < " << tmpVersion << std::endl;
00565 throw std::runtime_error("Invalid temporary version destination");
00566 }
00567
00568 if(sourceViewVersion == ConfigurationVersion::INVALID ||
00569 configurationViews_.find(sourceViewVersion) == configurationViews_.end())
00570 {
00571 if(sourceViewVersion != -1)
00572 {
00573 __MOUT_ERR__ << "ERROR: sourceViewVersion " << sourceViewVersion << " not found" << std::endl;
00574 throw std::runtime_error("Invalid source version. Version requested is not stored (yet?) or does not exist.");
00575 }
00576 __MOUT__ << "Using Mock-up view" << std::endl;
00577 configurationViews_[tmpVersion].copy(mockupConfigurationView_,
00578 tmpVersion,
00579 mockupConfigurationView_.getAuthor());
00580 }
00581 else
00582 {
00583 try
00584 {
00585 configurationViews_[tmpVersion].copy(configurationViews_[sourceViewVersion],
00586 tmpVersion,
00587 configurationViews_[sourceViewVersion].getAuthor());
00588 }
00589 catch(...)
00590 {
00591 __MOUT_WARN__ << "createTemporaryView() Source view failed init(). " <<
00592 "This is being ignored (hopefully the new copy is being fixed)." << std::endl;
00593 }
00594 }
00595
00596 return tmpVersion;
00597 }
00598
00599
00600
00601
00602
00603 ConfigurationVersion ConfigurationBase::getNextTemporaryVersion() const
00604 {
00605 ConfigurationVersion tmpVersion;
00606
00607
00608 if(configurationViews_.size() != 0 && configurationViews_.begin()->first.isTemporaryVersion())
00609 tmpVersion =
00610 ConfigurationVersion::getNextTemporaryVersion(configurationViews_.begin()->first);
00611 else
00612 tmpVersion = ConfigurationVersion::getNextTemporaryVersion();
00613
00614
00615 if(isStored(tmpVersion) || tmpVersion.isInvalid() || !tmpVersion.isTemporaryVersion())
00616 {
00617 __MOUT_ERR__ << "Invalid destination temporary version: " <<
00618 tmpVersion << std::endl;
00619 throw std::runtime_error("Invalid temporary version found");
00620 }
00621 return tmpVersion;
00622 }
00623
00624
00625
00626
00627
00628 ConfigurationVersion ConfigurationBase::getNextVersion() const
00629 {
00630 ConfigurationVersion tmpVersion;
00631
00632
00633 if(configurationViews_.size() != 0 && !configurationViews_.rbegin()->first.isTemporaryVersion())
00634 tmpVersion =
00635 ConfigurationVersion::getNextVersion(configurationViews_.rbegin()->first);
00636 else
00637 tmpVersion = ConfigurationVersion::getNextVersion();
00638
00639
00640 if(isStored(tmpVersion) || tmpVersion.isInvalid() || tmpVersion.isTemporaryVersion())
00641 {
00642 __MOUT_ERR__ << "Invalid destination next version: " <<
00643 tmpVersion << std::endl;
00644 throw std::runtime_error("Invalid next version found");
00645 }
00646 return tmpVersion;
00647 }
00648
00649
00650
00651
00652
00653 ConfigurationView* ConfigurationBase::getTemporaryView(ConfigurationVersion temporaryVersion)
00654 {
00655 if(!temporaryVersion.isTemporaryVersion() ||
00656 !isStored(temporaryVersion))
00657 {
00658 __MOUT_ERR__ << getConfigurationName() << ":: Error! Temporary version not found!" << std::endl;
00659 throw std::runtime_error("Invalid temporary version");
00660 }
00661 return &configurationViews_[temporaryVersion];
00662 }
00663
00664
00665
00666
00667
00668
00669 std::string ConfigurationBase::convertToCaps(std::string& str, bool isConfigName)
00670 throw(std::runtime_error)
00671 {
00672
00673 unsigned int configPos = (unsigned int)std::string::npos;
00674 if(isConfigName && (configPos = str.find("Configuration")) !=
00675 str.size() - strlen("Configuration"))
00676 str += "Configuration";
00677
00678
00679
00680
00681
00682
00683 std::string capsStr = "";
00684 for(unsigned int c=0;c<str.size();++c)
00685 if(str[c] >= 'A' && str[c] <= 'Z')
00686 {
00687
00688 if(c == configPos ||
00689 (c && str[c-1] >= 'a' && str[c-1] <= 'z') ||
00690 (c && str[c-1] >= 'A' && str[c-1] <= 'Z' &&
00691 c+1 < str.size() && str[c+1] >= 'a' && str[c+1] <= 'z')
00692 )
00693 capsStr += "_";
00694 capsStr += str[c];
00695 }
00696 else if(str[c] >= 'a' && str[c] <= 'z')
00697 capsStr += char(str[c] -32);
00698 else if(str[c] >= '0' && str[c] <= '9')
00699 capsStr += str[c];
00700 else
00701 throw std::runtime_error(std::string("ConfigurationBase::convertToCaps::") +
00702 "Invalid character found in name (allowed: A-Z, a-z, 0-9):" +
00703 str );
00704
00705 return capsStr;
00706 }
00707
00708
00709
00710