Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Broker file input #2700

Merged
merged 11 commits into from
Nov 26, 2024
11 changes: 6 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -488,15 +488,16 @@ target_include_directories(
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/containers>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/concurrency>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/utilities>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/utilities/gmlc/utilities>
)
# the utilities/gmlc is to account for the transfer of the header to a known location on install

target_include_directories(
helics_base SYSTEM INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty>
helics_base SYSTEM
INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/containers>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/concurrency>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/utilities>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty/utilities/gmlc/utilities>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty>
)

target_link_libraries(helics_base INTERFACE toml11::toml11)
Expand Down
3 changes: 2 additions & 1 deletion config/cmake/addBoost.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ if(NOT Boost_FOUND)
if(Boost_VERSION_MINOR GREATER_EQUAL ${BOOST_MINIMUM_VERSION})
add_library(Boost::headers INTERFACE IMPORTED)
set_target_properties(
Boost::headers PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIR}"
Boost::headers PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
"${Boost_INCLUDE_DIR}"
)
add_library(Boost::boost INTERFACE IMPORTED)
set_target_properties(Boost::boost PROPERTIES INTERFACE_LINK_LIBRARIES Boost::headers)
Expand Down
5 changes: 4 additions & 1 deletion src/helics/apps/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,14 @@ if(HELICS_BUILD_APP_LIBRARY)
target_include_directories(
helicscpp-apps
INTERFACE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/helics_cxx>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty>
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)

target_include_directories(
helicscpp-apps SYSTEM INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/ThirdParty>
)

set_target_properties(
helicscpp-apps PROPERTIES VERSION ${HELICS_VERSION} SOVERSION ${HELICS_VERSION_MAJOR}
)
Expand Down
181 changes: 179 additions & 2 deletions src/helics/core/BrokerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ SPDX-License-Identifier: BSD-3-Clause

#include "BrokerBase.hpp"

#include "../common/configFileHelpers.hpp"
#include "../common/logging.hpp"
#include "AsyncTimeCoordinator.hpp"
#include "ForwardingTimeCoordinator.hpp"
#include "GlobalTimeCoordinator.hpp"
#include "LogManager.hpp"
#include "ProfilerBuffer.hpp"
#include "core-exceptions.hpp"
#include "flagOperations.hpp"
#include "gmlc/libguarded/guarded.hpp"
#include "gmlc/utilities/stringOps.h"
Expand Down Expand Up @@ -81,7 +83,7 @@ BrokerBase::~BrokerBase()
joinAllThreads();
}
catch (...) {
// no exceptions in the destructor
; // no exceptions in the destructor
}
}
}
Expand Down Expand Up @@ -324,13 +326,184 @@ int BrokerBase::parseArgs(std::vector<std::string> args)

int BrokerBase::parseArgs(std::string_view initializationString)
{
auto type = fileops::getConfigType(initializationString);

switch (type) {
case fileops::ConfigType::JSON_FILE:
fileInUse = true;
loadInfoFromJson(std::string(initializationString));
configString = initializationString;
return 0;
case fileops::ConfigType::JSON_STRING:
try {
loadInfoFromJson(std::string(initializationString));
configString = initializationString;
return 0;
}
catch (const helics::InvalidParameter&) {
if (fileops::looksLikeConfigToml(initializationString)) {
try {
loadInfoFromToml(std::string(initializationString));
configString = initializationString;
return 0;
}
catch (const helics::InvalidParameter&) {
if (fileops::looksLikeCommandLine(initializationString)) {
break;
}
throw;
}
}
throw;
}
break;
case fileops::ConfigType::TOML_FILE:
fileInUse = true;
loadInfoFromToml(std::string(initializationString));
configString = initializationString;
return 0;
case fileops::ConfigType::TOML_STRING:
try {
loadInfoFromToml(std::string(initializationString));
configString = initializationString;
return 0;
}
catch (const helics::InvalidParameter&) {
if (fileops::looksLikeCommandLine(configString)) {
break;
}
throw;
}
break;
case fileops::ConfigType::CMD_LINE:
case fileops::ConfigType::NONE:
// with NONE there are default command line and environment possibilities
break;
}

auto app = generateBaseCLI();
auto sApp = generateCLI();
app->add_subcommand(sApp);
auto res = app->helics_parse(std::string(initializationString));
return static_cast<int>(res);
}

void BrokerBase::loadInfoFromJson(const std::string& jsonString, bool runArgParser)
{
nlohmann::json doc;
try {
doc = fileops::loadJson(jsonString);
}
catch (const std::invalid_argument& iarg) {
throw(helics::InvalidParameter(iarg.what()));
}
const bool hasHelicsSection = doc.contains("helics");
bool hasHelicsSubSection{false};
bool hasHelicsBrokerSubSection{false};
if (hasHelicsSection) {
hasHelicsSubSection = doc["helics"].contains("helics");
hasHelicsBrokerSubSection = doc["helics"].contains("broker");
}
const bool hasBrokerSection = doc.contains("broker");

if (runArgParser) {
auto app = generateBaseCLI();
auto sApp = generateCLI();
app->add_subcommand(sApp);
app->allow_extras();
try {
if (jsonString.find('{') != std::string::npos) {
std::istringstream jstring(jsonString);
app->parse_from_stream(jstring);
if (hasHelicsSection) {
app->get_config_formatter_base()->section("helics");
std::istringstream jstringHelics(jsonString);
app->parse_from_stream(jstringHelics);
if (hasHelicsSubSection) {
app->get_config_formatter_base()->section("helics.helics");
std::istringstream jstringHelicsSub(jsonString);
app->parse_from_stream(jstringHelicsSub);
}
if (hasHelicsBrokerSubSection) {
app->get_config_formatter_base()->section("helics.broker");
std::istringstream jstringHelicsSub(jsonString);
app->parse_from_stream(jstringHelicsSub);
}
}
if (hasBrokerSection) {
app->get_config_formatter_base()->section("broker");
std::istringstream jstringBroker(jsonString);
app->parse_from_stream(jstringBroker);
}
} else {
std::ifstream file(jsonString);
app->parse_from_stream(file);
if (hasHelicsSection) {
file.clear();
file.seekg(0);
app->get_config_formatter_base()->section("helics");
app->parse_from_stream(file);
if (hasHelicsSubSection) {
file.clear();
file.seekg(0);
app->get_config_formatter_base()->section("helics.helics");
app->parse_from_stream(file);
}
if (hasHelicsBrokerSubSection) {
file.clear();
file.seekg(0);
app->get_config_formatter_base()->section("helics.broker");
app->parse_from_stream(file);
}
}
if (hasBrokerSection) {
file.clear();
file.seekg(0);
app->get_config_formatter_base()->section("broker");
app->parse_from_stream(file);
}
}
}
catch (const CLI::Error& clierror) {
throw(InvalidIdentifier(clierror.what()));
}
}
}

void BrokerBase::loadInfoFromToml(const std::string& tomlString, bool runArgParser)
{
toml::value doc;
try {
doc = fileops::loadToml(tomlString);
}
catch (const std::invalid_argument& iarg) {
throw(helics::InvalidParameter(iarg.what()));
}

if (runArgParser) {
auto app = generateBaseCLI();
auto sApp = generateCLI();
app->add_subcommand(sApp);
app->allow_extras();
auto dptr = std::static_pointer_cast<HelicsConfigJSON>(app->get_config_formatter_base());
if (dptr) {
dptr->skipJson(true);
}
try {
if (tomlString.find('=') != std::string::npos) {
std::istringstream tstring(tomlString);
app->parse_from_stream(tstring);
} else {
std::ifstream file(tomlString);
app->parse_from_stream(file);
}
}
catch (const CLI::Error& e) {
throw(InvalidIdentifier(e.what()));
}
}
}

void BrokerBase::configureBase()
{
if (debugging) {
Expand Down Expand Up @@ -428,6 +601,10 @@ void BrokerBase::writeProfilingData()
prBuff->writeFile();
}
catch (const std::ios_base::failure&) {
sendToLogger(parent_broker_id,
LogLevels::ERROR_LEVEL,
identifier,
"Unable to write profiling buffer data");
}
}
}
Expand Down Expand Up @@ -669,7 +846,7 @@ static void
bbase->addActionMessage(CMD_TICK);
}
catch (std::exception& e) {
std::cerr << "exception caught from addActionMessage" << e.what() << std::endl;
std::cerr << "exception caught from addActionMessage" << e.what() << '\n';
}
} else {
ActionMessage tick(CMD_TICK);
Expand Down
14 changes: 14 additions & 0 deletions src/helics/core/BrokerBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ class BrokerBase {
decltype(std::chrono::steady_clock::now()) disconnectTime;
std::atomic<int> lastErrorCode{0}; //!< storage for last error code
std::string lastErrorString; //!< storage for last error string
std::string configString; //!< storage for a config file location
bool fileInUse{false};

private:
/// buffer for profiling messages
std::shared_ptr<ProfilerBuffer> prBuff;
Expand All @@ -170,6 +173,17 @@ class BrokerBase {
explicit BrokerBase(std::string_view broker_name, bool DisableQueue = false);

virtual ~BrokerBase();

/** load broker information object from a toml string either a file or toml string
@param toml a string containing the name of the toml file or toml contents
*/
void loadInfoFromToml(const std::string& toml, bool runArgParser = true);

/** load broker information from a JSON string either a file or JSON string
@param json a string containing the name of the JSON file or JSON contents
*/
void loadInfoFromJson(const std::string& json, bool runArgParser = true);

/** parse configuration information from command line arguments
@return 0 for OK, positive numbers for expected information calls and negative number for error
*/
Expand Down
34 changes: 34 additions & 0 deletions src/helics/core/BrokerFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-3-Clause
#include "CoreBroker.hpp"
#include "CoreTypes.hpp"
#include "core-exceptions.hpp"
#include "coreTypeOperations.hpp"
#include "gmlc/concurrency/DelayedDestructor.hpp"
#include "gmlc/concurrency/SearchableObjectHolder.hpp"
#include "gmlc/concurrency/TripWire.hpp"
Expand Down Expand Up @@ -109,6 +110,17 @@ std::shared_ptr<Broker> create(CoreType type, std::string_view configureString)
std::shared_ptr<Broker>
create(CoreType type, std::string_view brokerName, std::string_view configureString)
{
std::string newName;
CoreType newType;
if (type == CoreType::EXTRACT || brokerName.empty()) {
std::tie(newType, newName) = core::extractCoreType(std::string{configureString});
if (brokerName.empty() && !newName.empty()) {
brokerName = newName;
}
if (type == CoreType::EXTRACT) {
type = newType;
}
}
auto broker = makeBroker(type, brokerName);
if (!broker) {
throw(helics::RegistrationFailure("unable to create broker"));
Expand All @@ -129,6 +141,17 @@ std::shared_ptr<Broker> create(CoreType type, int argc, char* argv[])

std::shared_ptr<Broker> create(CoreType type, std::string_view brokerName, int argc, char* argv[])
{
std::string newName;
CoreType newType;
if (type == CoreType::EXTRACT || brokerName.empty()) {
std::tie(newType, newName) = core::extractCoreType(argc, argv);
if (brokerName.empty() && !newName.empty()) {
brokerName = newName;
}
if (type == CoreType::EXTRACT) {
type = newType;
}
}
auto broker = makeBroker(type, brokerName);
broker->configureFromArgs(argc, argv);
if (!registerBroker(broker, type)) {
Expand All @@ -147,6 +170,17 @@ std::shared_ptr<Broker> create(CoreType type, std::vector<std::string> args)
std::shared_ptr<Broker>
create(CoreType type, std::string_view brokerName, std::vector<std::string> args)
{
std::string newName;
CoreType newType;
if (type == CoreType::EXTRACT || brokerName.empty()) {
std::tie(newType, newName) = core::extractCoreType(args);
if (brokerName.empty() && !newName.empty()) {
brokerName = newName;
}
if (type == CoreType::EXTRACT) {
type = newType;
}
}
auto broker = makeBroker(type, brokerName);
broker->configureFromVector(std::move(args));
if (!registerBroker(broker, type)) {
Expand Down
3 changes: 2 additions & 1 deletion src/helics/core/BrokerFactory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace BrokerFactory {
class BrokerTypeBuilder final: public BrokerBuilder {
public:
static_assert(std::is_base_of<Broker, BrokerTYPE>::value,
"Type does not inherit from helics::Core");
"Type does not inherit from helics::Broker");

using broker_build_type = BrokerTYPE;
virtual std::shared_ptr<Broker> build(std::string_view name) override
Expand All @@ -55,6 +55,7 @@ namespace BrokerFactory {
defineBrokerBuilder(bbld, brokerTypeName, code);
return bbld;
}

/**
* Creates a Broker object of the specified type.
*
Expand Down
Loading
Loading