Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions otsdaq/ARTDAQSupervisor/ARTDAQSupervisor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@
#include <signal.h>
#include <cerrno>
#include <cstring>
#include <fstream>
#include <regex>

#include "otsdaq/ConfigurationInterface/ConfigurationInterface.h"
#include "otsdaq/Macros/StringMacros.h"
#include "otsdaq/TableCore/TableBase.h"

#define OUT_ON_ERR_SIZE 2000 //tail size of output to include on error

using namespace ots;

XDAQ_INSTANTIATOR_IMPL(ARTDAQSupervisor)

const std::string ARTDAQSupervisor::ARTDAQ_SYSVAR_NAMESPACE = "artdaq";

#define FAKE_CONFIG_NAME "ots_config"
#define DAQINTERFACE_PORT \
std::atoi(__ENV__("ARTDAQ_BASE_PORT")) + \
Expand Down Expand Up @@ -540,6 +547,9 @@ void ARTDAQSupervisor::init(void)
// }
}
start_runner_();

initArtdaqSystemVariables();

__SUP_COUT__ << "Initialized." << __E__;
} // end init()

Expand All @@ -548,6 +558,8 @@ void ARTDAQSupervisor::transitionConfiguring(toolbox::Event::Reference /*event*/
{
__SUP_COUTT__ << "transitionConfiguring" << __E__;

loadArtdaqSystemVariables();

// activate the configuration tree (the first iteration)
if(RunControlStateMachine::getIterationIndex() == 0 &&
RunControlStateMachine::getSubIterationIndex() == 0)
Expand Down Expand Up @@ -2141,3 +2153,145 @@ void ots::ARTDAQSupervisor::start_runner_()
runner_thread_ =
std::make_unique<std::thread>(&ots::ARTDAQSupervisor::daqinterfaceRunner_, this);
} // end start_runner_()

//==============================================================================
std::string ARTDAQSupervisor::getServiceDataFilePath() const
{
return StringMacros::getPersistentSystemVariablesFilePath();
} // end getServiceDataFilePath()

//==============================================================================
void ARTDAQSupervisor::initArtdaqSystemVariables()
{
loadArtdaqSystemVariables();

auto& ns = StringMacros::systemVariables_[ARTDAQ_SYSVAR_NAMESPACE];
__SUP_COUT__ << "Artdaq system variables initialized: "
<< StringMacros::mapToString(ns) << __E__;
} // end initArtdaqSystemVariables()

//==============================================================================
void ARTDAQSupervisor::loadArtdaqSystemVariables()
{
if(StringMacros::loadPersistentSystemVariables())
__SUP_COUT__ << "Loaded artdaq system variables from " << getServiceDataFilePath()
<< __E__;
else
__SUP_COUT__ << "No persisted artdaq system variables file found at "
<< getServiceDataFilePath() << __E__;
} // end loadArtdaqSystemVariables()
Comment on lines +2174 to +2182

//==============================================================================
void ARTDAQSupervisor::saveArtdaqSystemVariables()
{
std::string filePath = getServiceDataFilePath();
std::ofstream file(filePath);
if(!file.is_open())
{
__SUP_SS__ << "Failed to open file for writing artdaq system variables: "
<< filePath << __E__;
__SUP_SS_THROW__;
}

for(auto& [key, value] : StringMacros::systemVariables_[ARTDAQ_SYSVAR_NAMESPACE])
file << key << "=" << value << "\n";

__SUP_COUT__ << "Saved artdaq system variables to " << filePath << __E__;
} // end saveArtdaqSystemVariables()

//==============================================================================
void ARTDAQSupervisor::forceSupervisorPropertyValues(void)
{
CorePropertySupervisorBase::addSupervisorProperty(
CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
"getSystemVariables | getJsonDocuments");
} // end forceSupervisorPropertyValues()

//==============================================================================
void ARTDAQSupervisor::request(const std::string& requestType,
cgicc::Cgicc& cgiIn,
HttpXmlDocument& xmlOut,
const WebUsers::RequestUserInfo& /*userInfo*/)
try
{
__SUP_COUT__ << "ARTDAQSupervisor request: " << requestType << __E__;

if(requestType == "getSystemVariables")
{
for(auto& [key, value] : StringMacros::systemVariables_[ARTDAQ_SYSVAR_NAMESPACE])
xmlOut.addTextElementToData("artdaq_" + key, value);
}
else if(requestType == "setSystemVariable")
{
std::string key = CgiDataUtilities::postData(cgiIn, "key");
std::string value = CgiDataUtilities::postData(cgiIn, "value");

if(key.empty())
{
xmlOut.addTextElementToData("Error", "Variable key must not be empty.");
return;
}
for(char c : key)
if(!std::isalnum(c) && c != '_')
{
xmlOut.addTextElementToData(
"Error",
"Variable key must contain only alphanumeric characters and "
"underscores.");
return;
}
Comment on lines +2226 to +2242

StringMacros::systemVariables_[ARTDAQ_SYSVAR_NAMESPACE][key] = value;
saveArtdaqSystemVariables();

__SUP_COUT__ << "Set artdaq system variable " << key << " = " << value << __E__;
xmlOut.addTextElementToData("Success", "Variable '" + key + "' set.");
}
else if(requestType == "getJsonDocuments")
{
auto* ifc = ConfigurationInterface::getInstance();

std::set<std::string> allTableNames = ifc->getAllTableNames();

for(const auto& tableName : allTableNames)
{
if(tableName.find(TableBase::JSON_DOC_PREPEND) != 0)
continue;

std::string docName = tableName.substr(TableBase::JSON_DOC_PREPEND.size());

TableBase tmpTable(true, tableName);
std::set<TableVersion> versions = ifc->getVersions(&tmpTable);

std::string versionList;
for(const auto& v : versions)
{
if(!versionList.empty())
versionList += ",";
versionList += v.toString();
}

xmlOut.addTextElementToData("jsonDoc_name", docName);
xmlOut.addTextElementToData("jsonDoc_versions", versionList);
}
}
else
{
__SUP_SS__ << "Unknown request type '" << requestType << "' for ARTDAQSupervisor."
<< __E__;
__SUP_COUT__ << ss.str();
xmlOut.addTextElementToData("Error", ss.str());
}
}
catch(const std::runtime_error& e)
{
__SUP_SS__ << "Error handling request '" << requestType << "': " << e.what() << __E__;
__SUP_COUT_ERR__ << ss.str();
xmlOut.addTextElementToData("Error", ss.str());
}
catch(...)
{
__SUP_SS__ << "Unknown error handling request '" << requestType << "'." << __E__;
__SUP_COUT_ERR__ << ss.str();
xmlOut.addTextElementToData("Error", ss.str());
} // end request()
13 changes: 13 additions & 0 deletions otsdaq/ARTDAQSupervisor/ARTDAQSupervisor.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ class ARTDAQSupervisor : public CoreSupervisorBase
virtual void transitionStopping(toolbox::Event::Reference event) override;
virtual void enteringError(toolbox::Event::Reference event) override;

void request(const std::string& requestType,
cgicc::Cgicc& cgiIn,
HttpXmlDocument& xmlOut,
const WebUsers::RequestUserInfo& userInfo) override;

virtual std::vector<SupervisorInfo::SubappInfo> getSubappInfo(void) override;
virtual std::string getStatusProgressDetail(void) override
{
Expand Down Expand Up @@ -80,6 +85,14 @@ class ARTDAQSupervisor : public CoreSupervisorBase
static std::list<std::string> tokenize_(std::string const& input);

private:
void forceSupervisorPropertyValues(void) override;
void initArtdaqSystemVariables();
void saveArtdaqSystemVariables();
void loadArtdaqSystemVariables();
std::string getServiceDataFilePath() const;

static const std::string ARTDAQ_SYSVAR_NAMESPACE;

void configuringThread(void);
void startingThread(void);

Expand Down
74 changes: 74 additions & 0 deletions otsdaq/CodeEditor/CodeEditor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <cctype> //for std::toupper
#include <map> //for std::map
#include <regex> //for std::regex
#include <sstream> //for std::stringstream
#include <thread> //for std::thread

using namespace ots;
Expand Down Expand Up @@ -69,6 +70,7 @@ try
//
// getDirectoryContent
// getFileContent
// getFhiclFileContent
// saveFileContent
// cleanBuild
// incrementalBuild
Expand All @@ -84,6 +86,10 @@ try
{
getFileContent(cgiIn, xmlOut);
}
else if(option == "getFhiclFileContent")
{
getFhiclFileContent(cgiIn, xmlOut);
}
else if(!readOnlyMode && option == "saveFileContent")
{
saveFileContent(cgiIn, xmlOut, username);
Expand Down Expand Up @@ -479,6 +485,74 @@ void CodeEditor::getFileContent(cgicc::Cgicc& cgiIn, HttpXmlDocument* xmlOut)

} // end getFileContent()

//==============================================================================
/// getFhiclFileContent
/// Locates a fcl file by its path relative to a $FHICL_FILE_PATH entry
/// (e.g. "mu2e-trig-config/core/trigSequences.fcl"), searching each
/// colon-separated directory in $FHICL_FILE_PATH in order, the same
/// convention any fcl-consuming tool uses to resolve #include and
/// @sequence:: search paths. This lets read-only viewers reach fcl files
/// that live outside the areas normally accessible to the Code Editor
/// ($USER_DATA, $OTSDAQ_WEB_PATH, $OTSDAQ_DATA, srcs/), such as files
/// installed by a UPS/spack product.
void CodeEditor::getFhiclFileContent(cgicc::Cgicc& cgiIn, HttpXmlDocument* xmlOut)
{
std::string relativePath = CgiDataUtilities::getData(cgiIn, "path");
relativePath = safePathString(StringMacros::decodeURIComponent(relativePath));
// leading slashes are not meaningful for a $FHICL_FILE_PATH-relative lookup
while(relativePath.size() && relativePath[0] == '/')
relativePath = relativePath.substr(1);
xmlOut->addTextElementToData("path", relativePath);

if(relativePath.find("..") != std::string::npos)
{
__SS__ << "Illegal '..' found in requested fcl path '" << relativePath << ".'"
<< __E__;
__SS_THROW__;
}
Comment on lines +500 to +512

std::string fhiclFilePath;
{
const char* envVal = getenv("FHICL_FILE_PATH");
if(envVal)
fhiclFilePath = envVal;
}

std::string contents;
bool found = false;
std::string lastError;
std::stringstream searchPaths(fhiclFilePath);
std::string dir;
while(std::getline(searchPaths, dir, ':'))
{
if(dir.empty())
continue;
try
{
CodeEditor::readFile(dir, relativePath, contents);
found = true;
break;
}
catch(const std::runtime_error& e)
{
lastError = e.what();
}
}

if(!found)
{
__SS__ << "Could not find '" << relativePath
<< "' in any directory of $FHICL_FILE_PATH.";
if(lastError.size())
ss << " Last error: " << lastError;
ss << __E__;
__SS_THROW__;
}

xmlOut->addTextElementToData("content", contents);

} // end getFhiclFileContent()

//==============================================================================
/// getFileGitURL
void CodeEditor::getFileGitURL(cgicc::Cgicc& cgiIn, HttpXmlDocument* xmlOut)
Expand Down
1 change: 1 addition & 0 deletions otsdaq/CodeEditor/CodeEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class CodeEditor
const std::string& path,
HttpXmlDocument* xmlOut);
void getFileContent(cgicc::Cgicc& cgiIn, HttpXmlDocument* xmlOut);
void getFhiclFileContent(cgicc::Cgicc& cgiIn, HttpXmlDocument* xmlOut);
void getFileGitURL(cgicc::Cgicc& cgiIn, HttpXmlDocument* xmlOut);
void saveFileContent(cgicc::Cgicc& cgiIn,
HttpXmlDocument* xmlOut,
Expand Down
5 changes: 5 additions & 0 deletions otsdaq/ConfigurationInterface/ConfigurationManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5775,6 +5775,11 @@ try
{
__COUTT__ << "Initializing prerequisites for artdaq!" << __E__;

// refresh persisted 'artdaq' system variables (set via web GUIs, e.g. the
// Trigger Menu Editor) so table plugins resolve current ${OTS.artdaq.*}
// values in this process at configure time
StringMacros::loadPersistentSystemVariables();

auto activeTables = getActiveVersions();
for(auto& tablePair : activeTables)
{
Expand Down
5 changes: 5 additions & 0 deletions otsdaq/CoreSupervisors/CorePropertySupervisorBase.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ CorePropertySupervisorBase::CorePropertySupervisorBase(xdaq::Application* applic
StringMacros::systemVariables_["System"]["totalMemoryMB"] = "unknown";
}
}

// load 'artdaq' namespace system variables persisted by the ARTDAQ Supervisor
// (e.g. set via the Trigger Menu Editor web GUI) so ${OTS.artdaq.*}
// references resolve in every Supervisor process
StringMacros::loadPersistentSystemVariables();
} // end init StringMacros::systemVariables_
__SUP_COUTV__(StringMacros::mapToString(StringMacros::systemVariables_));

Expand Down
5 changes: 3 additions & 2 deletions otsdaq/FiniteStateMachine/RunInfoVInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class RunInfoVInterface ///< : public Configurable
ERROR,
PAUSE,
RESUME,
START
START,
STOP_COMPLETE,
HALT_COMPLETE
};

RunInfoVInterface (const std::string& runInfoPluginClassName,
Expand Down Expand Up @@ -76,7 +78,6 @@ class RunInfoVInterface ///< : public Configurable
const std::string& /* comment */) { __SS__ << "updateRunInfo() Not implemented by the Run Info Plugin (" << mfSubject_ << ")!!"; __SS_THROW__; };



/// Get functions ----

const std::string& getActiveStateMachineName (void) const { return activeStateMachineName_; }
Expand Down
Loading