Skip to content

Commit

Permalink
Merge pull request #280 from sy-c/master
Browse files Browse the repository at this point in the history
v2.25.0
  • Loading branch information
sy-c committed Jun 25, 2024
2 parents 0c165e6 + 3c435d1 commit ef81fda
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 1 deletion.
9 changes: 9 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ Equipments should be prefixed as `[equipment-...]`.
Consumers should be prefixed as `[consumer-...]`.
General settings are defined in section `[readout]`.

Section names ending with `-*` can be used to define default parameters. They are applied to all section with similar names. Existing key-value pairs are not overwritten, but are defined according to defaults if they don't exist. For example, it is possible to define the TFperiod for all equipments by adding a section named `[equipment-*]` with `TFperiod=32`.

Values can be symbolic links to a value stored in another configuration file. The syntax is: @LINK,URI,entryPoint,path
For example: @LINK,file:/local/readout-test-config-link1.cfg,,bank.size
Parameters are similar to the command-line arguments of o2-readout-exe, see ```Usage``` below.
Files are cached, i.e. the corresponding configuration tree is loaded only once if several values use a link to the same URI/entryPoint.
Links substitutions are done at the end of the configuration tree aggregation (sections merging, etc).
It is done recursively (up to 5 iterations, after which it fails to avoid circular dependencies).

Comments can be added by starting a line with the # sign. Inline comments (# later in the line) are not accepted.
Documented example files are provided with the source code and distribution.

Expand Down
4 changes: 4 additions & 0 deletions doc/releaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -628,3 +628,7 @@ This file describes the main feature changes for each readout.exe released versi
## v2.24.0 - 18/06/2024
- Updated configuration parameters:
- equipment-rorc-*: added parameters firmwareVersionsDenied and firmwareVersionsAllowed, to enforce the check of firmware for specific versions. By default, v3.10.0 (e4a5a46e) is denied and all other allowed: it is the default version in CRU flash and should be updated to a more recent one at boot time.

## v2.25.0 - 25/06/2024
- Updated configuration parameters:
- Values can be a link to a value stored in another file.
2 changes: 1 addition & 1 deletion src/ReadoutVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#define READOUT_VERSION "2.24.0"
#define READOUT_VERSION "2.25.0"

92 changes: 92 additions & 0 deletions src/mainReadout.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,98 @@ int Readout::_configure(const boost::property_tree::ptree& properties)
pos = cfg.get().erase(pos);
}

// resolve "symlinks"
int cfgLinksErrors = 0;
struct ConfigCache {
std::string URI;
std::string EntryPoint;
std::unique_ptr<ConfigFile> cfg;
};
std::vector<ConfigCache> cfgCache;
int nSubstitutions = 0;
std::function<void(boost::property_tree::ptree &, const std::string &)> resolveLinks;
resolveLinks = [&resolveLinks, &cfgLinksErrors, &cfgCache, &loadConfig, &nSubstitutions](boost::property_tree::ptree &pt, const std::string &key) -> void {
if (pt.empty()) {
std::string value = pt.data();
const std::string keywordLink = "@LINK";
if (value.compare(0, keywordLink.length(), keywordLink) == 0) {
// this is a symlink
// extract reference
// syntax: @LINK,URI,EntryPoint,Path
std::vector<std::string> linkArgs;
getListFromString(value, linkArgs, ',');
if (linkArgs.size() != 4) {
theLog.log(LogErrorSupport_(3102), "Failed to parse link: %s = %s", key.c_str(), value.c_str());
cfgLinksErrors++;
return;
}
const char* cfgLinkUri = linkArgs[1].c_str();
const char* cfgLinkEntryPoint = linkArgs[2].c_str();
const char* cfgLinkPath = linkArgs[3].c_str();
// search for file in cache
unsigned int ix = 0;
for(;ix < cfgCache.size(); ix++) {
if ((cfgCache[ix].URI == cfgLinkUri) && (cfgCache[ix].EntryPoint == cfgLinkEntryPoint)) {
break;
}
}
if (ix == cfgCache.size()) {
// no match in cache, add it
try {
auto cfg = std::make_unique<ConfigFile>();
if (cfg==nullptr) {
throw __LINE__;
}
if (loadConfig(cfgLinkUri, cfgLinkEntryPoint, *cfg)) {
throw __LINE__;
}
cfgCache.push_back({cfgLinkUri, cfgLinkEntryPoint, std::move(cfg)});
}
catch(...) {
theLog.log(LogErrorSupport_(3102), "Failed to load linked configuration %s %s", cfgLinkUri, cfgLinkEntryPoint);
cfgLinksErrors++;
return;
}
theLog.log(LogInfoSupport, "Reading linked configuration from %s %s", cfgLinkUri, cfgLinkEntryPoint);
}
// at this stage we now have a valid config in cache at index ix
// get value from linked config
std::string linkValue;
if (cfgCache[ix].cfg->getOptionalValue<std::string>(cfgLinkPath, linkValue)) {
theLog.log(LogErrorSupport_(3102), "Failed to get link value: %s = %s", key.c_str(), value.c_str());
cfgLinksErrors++;
return;
}
theLog.log(LogInfoDevel_(3002), "Link substituted : %s = %s -> %s", key.c_str(), value.c_str(), linkValue.c_str());
pt.data() = linkValue;
nSubstitutions++;
}
return;
}
for (boost::property_tree::ptree::iterator pos = pt.begin(); pos != pt.end();++pos) {
//printf("%s\n", pos->first.c_str());
resolveLinks(pos->second, pos->first.c_str());
}
};
int maxLoops = 5;
for (int i = 0; i <= maxLoops; i++) {
if (i == maxLoops) {
theLog.log(LogErrorSupport_(3100), "Links not fully resolved after %d iterations, there might be some circular dependencies in the configuration", maxLoops);
cfgLinksErrors++;
break;
}
nSubstitutions = 0;
resolveLinks(cfg.get(),"");
if (nSubstitutions == 0) {
break;
}
}
if (cfgLinksErrors) {
theLog.log(LogErrorSupport_(3100), "Some links in the configuration could not be resolved");
return -1;
}


// extract optional configuration parameters
// configuration parameter: | readout | customCommands | string | | List of key=value pairs defining some custom shell commands to be executed at before/after state change commands. |
if (customCommandsShellPid) {
Expand Down

0 comments on commit ef81fda

Please sign in to comment.