Skip to content

Commit

Permalink
optimize parsing modelDescription.xml only once (#1168)
Browse files Browse the repository at this point in the history
* optimize parsing modelDescription.xml only once

* expected output
  • Loading branch information
arun3688 committed Jun 13, 2022
1 parent e0eeaa5 commit 4c9975e
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 90 deletions.
1 change: 1 addition & 0 deletions src/OMSimulatorLib/Component.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ namespace oms
void getAllResources(std::vector<std::string>& resources) const { resources.push_back(path); }
const std::string& getPath() const { return path; }
const std::string& getTempDir() const { return tempDir; }
void setPath(const std::string& newPath) { this->path = newPath; }
void setTempDir(const std::string& tempDir) { this->tempDir = tempDir; }
oms_component_enu_t getType() const { return type; }
void fetchAllVars(bool enableOption) { fetchAllVars_ = enableOption; }
Expand Down
75 changes: 33 additions & 42 deletions src/OMSimulatorLib/ComponentFMUCS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
#include "SystemTLM.h"
#include "SystemWC.h"

#include <miniunz.h>
#include <fmilib.h>
#include <JM/jm_portability.h>
#include <RegEx.h>
Expand All @@ -61,7 +60,7 @@ oms::ComponentFMUCS::~ComponentFMUCS()
fmi_import_free_context(context);
}

oms::Component* oms::ComponentFMUCS::NewComponent(const oms::ComRef& cref, oms::System* parentSystem, const std::string& fmuPath, bool useTempDir)
oms::Component* oms::ComponentFMUCS::NewComponent(const oms::ComRef& cref, oms::System* parentSystem, const std::string& fmuPath)
{
if (!cref.isValidIdent())
{
Expand All @@ -75,52 +74,47 @@ oms::Component* oms::ComponentFMUCS::NewComponent(const oms::ComRef& cref, oms::
return NULL;
}

// parse the modeldescription.xml at top level to get the GUID to check whether instance already exist so we don't need to unpack the fmu
const char* modelDescription;
if (useTempDir)
{
filesystem::path tempDirPath = parentSystem->getModel().getTempDirectory() / filesystem::path(fmuPath);
modelDescription = ::miniunz_onefile_to_memory(tempDirPath.generic_string().c_str(), "modelDescription.xml");
}
else
modelDescription = ::miniunz_onefile_to_memory(fmuPath.c_str(), "modelDescription.xml");

Snapshot snapshot;
oms_status_enu_t status = snapshot.importResourceMemory("modelDescription.xml", modelDescription);
::miniunz_free(modelDescription);

if (oms_status_ok != status)
{
logError("Failed to import modelDescription.xml for fmu " + fmuPath);
return NULL;
}
filesystem::path temp_root(parentSystem->getModel().getTempDirectory());
filesystem::path temp_temp = temp_root / "temp";
filesystem::path relFMUPath = parentSystem->copyResources() ? (filesystem::path("resources") / (parentSystem->getUniqueID() + "_" + std::string(cref) + ".fmu")) : filesystem::path(fmuPath);
filesystem::path absFMUPath = temp_root / relFMUPath;

const pugi::xml_node node = snapshot.getResourceNode("modelDescription.xml");
if (!node)
{
logError("Failed to find root node in modelDescription.xml");
return NULL;
}
ComponentFMUCS* component = new ComponentFMUCS(cref, parentSystem, relFMUPath.generic_string());

//snapshot.debugPrintAll();
/* parse the modeldescription.xml at top level to get the GUID to check whether instance already exist
* so we don't need to unpack the fmu, and also parse start values before instantiating fmu's
*/
std::string guid_ = "";
filesystem::path modelDescriptionPath;
/*
* check for modeldescription path from file system or temp directory
* because when importingSnapshot the path will be resources/0001_tank1.fmu
*/
if (parentSystem->copyResources())
modelDescriptionPath = fmuPath;
else
modelDescriptionPath = parentSystem->getModel().getTempDirectory() / filesystem::path(fmuPath);

filesystem::path temp_root(parentSystem->getModel().getTempDirectory());
filesystem::path temp_temp = temp_root / "temp";
filesystem::path relFMUPath;
component->values.parseModelDescription(modelDescriptionPath, guid_);

std::string guid_ = node.attribute("guid").as_string();
/*
* check if instance of an fmu already exist by using guid of the fmu
* if instance exist use the existing instance path
* eg: tank1 => resources /0001_tank1.fmu
* tank2 => resources /0001_tank1.fmu
*/
auto it = parentSystem->fmuGuid.find(guid_);
if (it == parentSystem->fmuGuid.end())
{
relFMUPath = parentSystem->copyResources() ? (filesystem::path("resources") / (parentSystem->getUniqueID() + "_" + std::string(cref) + ".fmu")) : filesystem::path(fmuPath);
parentSystem->fmuGuid[guid_] = relFMUPath;
}
else
{
// instance exists and update the FMU path to already existing instance
relFMUPath = parentSystem->fmuGuid[guid_];
absFMUPath = temp_root / relFMUPath;
component->setPath(relFMUPath.generic_string());
}

filesystem::path absFMUPath = temp_root / relFMUPath;

ComponentFMUCS* component = new ComponentFMUCS(cref, parentSystem, relFMUPath.generic_string());
//std::cout <<"\nFmuInstances: " << cref.c_str() << "=" << guid_ << "=" << relFMUPath.generic_string();

component->callbacks.malloc = malloc;
component->callbacks.calloc = calloc;
Expand Down Expand Up @@ -287,9 +281,6 @@ oms::Component* oms::ComponentFMUCS::NewComponent(const oms::ComRef& cref, oms::
return NULL;
}

// parse modelDescription.xml to get start values before instantiating fmu's
component->values.parseModelDescription(tempDir);

// set units to connector
for (auto &connector : component->connectors)
{
Expand All @@ -316,7 +307,7 @@ oms::Component* oms::ComponentFMUCS::NewComponent(const pugi::xml_node& node, om
return NULL;
}

oms::ComponentFMUCS* component = dynamic_cast<oms::ComponentFMUCS*>(oms::ComponentFMUCS::NewComponent(cref, parentSystem, source, true));
oms::ComponentFMUCS* component = dynamic_cast<oms::ComponentFMUCS*>(oms::ComponentFMUCS::NewComponent(cref, parentSystem, source));
if (!component)
return NULL;

Expand Down
2 changes: 1 addition & 1 deletion src/OMSimulatorLib/ComponentFMUCS.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace oms
public:
~ComponentFMUCS();

static Component* NewComponent(const ComRef& cref, System* parentSystem, const std::string& fmuPath, bool useTempDir = false);
static Component* NewComponent(const ComRef& cref, System* parentSystem, const std::string& fmuPath);
static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot);
const FMUInfo* getFMUInfo() const {return &(this->fmuInfo);}

Expand Down
71 changes: 31 additions & 40 deletions src/OMSimulatorLib/ComponentFMUME.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
#include "SystemSC.h"
#include "SystemTLM.h"

#include <miniunz.h>
#include <fmilib.h>
#include <JM/jm_portability.h>
#include <RegEx.h>
Expand All @@ -61,7 +60,7 @@ oms::ComponentFMUME::~ComponentFMUME()
fmi_import_free_context(context);
}

oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms::System* parentSystem, const std::string& fmuPath, bool useTempDir)
oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms::System* parentSystem, const std::string& fmuPath)
{
if (!cref.isValidIdent())
{
Expand All @@ -75,50 +74,45 @@ oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms::
return NULL;
}

// parse the modeldescription.xml at top level to get the GUID to check whether instance already exist so we don't need to unpack the fmu
const char* modelDescription;
if (useTempDir)
{
filesystem::path tempDirPath = parentSystem->getModel().getTempDirectory() / filesystem::path(fmuPath);
modelDescription = ::miniunz_onefile_to_memory(tempDirPath.generic_string().c_str(), "modelDescription.xml");
}
else
modelDescription = ::miniunz_onefile_to_memory(fmuPath.c_str(), "modelDescription.xml");

Snapshot snapshot;
oms_status_enu_t status = snapshot.importResourceMemory("modelDescription.xml", modelDescription);
::miniunz_free(modelDescription);
filesystem::path temp_root(parentSystem->getModel().getTempDirectory());
filesystem::path temp_temp = temp_root / "temp";
filesystem::path relFMUPath = parentSystem->copyResources() ? (filesystem::path("resources") / (parentSystem->getUniqueID() + "_" + std::string(cref) + ".fmu")) : filesystem::path(fmuPath);
filesystem::path absFMUPath = temp_root / relFMUPath;

if (oms_status_ok != status)
{
logError("Failed to import modelDescription.xml for fmu " + fmuPath);
return NULL;
}
ComponentFMUME* component = new ComponentFMUME(cref, parentSystem, relFMUPath.generic_string());

const pugi::xml_node node = snapshot.getResourceNode("modelDescription.xml");
if (!node)
{
logError("Failed to find root node in modelDescription.xml");
return NULL;
}
/* parse the modeldescription.xml at top level to get the GUID to check whether instance already exist
* so we don't need to unpack the fmu, and also parse start values before instantiating fmu's
*/
std::string guid_ = "";
filesystem::path modelDescriptionPath;
/*
* check for modeldescription path from file system or temp directory
* because when importingSnapshot the path will be resources/0001_tank1.fmu
*/
if (parentSystem->copyResources())
modelDescriptionPath = fmuPath;
else
modelDescriptionPath = parentSystem->getModel().getTempDirectory() / filesystem::path(fmuPath);

filesystem::path temp_root(parentSystem->getModel().getTempDirectory());
filesystem::path temp_temp = temp_root / "temp";
filesystem::path relFMUPath;
component->values.parseModelDescription(modelDescriptionPath, guid_);

std::string guid_ = node.attribute("guid").as_string();
/*
* check if instance of an fmu already exist by using guid of the fmu
* if instance exist use the existing instance path
* eg: tank1 => resources /0001_tank1.fmu
* tank2 => resources /0001_tank1.fmu
*/
auto it = parentSystem->fmuGuid.find(guid_);
if (it == parentSystem->fmuGuid.end())
{
relFMUPath = parentSystem->copyResources() ? (filesystem::path("resources") / (parentSystem->getUniqueID() + "_" + std::string(cref) + ".fmu")) : filesystem::path(fmuPath);
parentSystem->fmuGuid[guid_] = relFMUPath;
}
else
{
// instance exists and update the FMU path to already existing instance
relFMUPath = parentSystem->fmuGuid[guid_];

filesystem::path absFMUPath = temp_root / relFMUPath;

ComponentFMUME* component = new ComponentFMUME(cref, parentSystem, relFMUPath.generic_string());
absFMUPath = temp_root / relFMUPath;
component->setPath(relFMUPath.generic_string());
}

component->callbacks.malloc = malloc;
component->callbacks.calloc = calloc;
Expand Down Expand Up @@ -287,9 +281,6 @@ oms::Component* oms::ComponentFMUME::NewComponent(const oms::ComRef& cref, oms::
return NULL;
}

// parse modelDescription.xml to get start values before instantiating fmu's
component->values.parseModelDescription(tempDir);

// set units to connector
for (auto &connector : component->connectors)
{
Expand Down
2 changes: 1 addition & 1 deletion src/OMSimulatorLib/ComponentFMUME.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace oms
public:
~ComponentFMUME();

static Component* NewComponent(const oms::ComRef& cref, System* parentSystem, const std::string& fmuPath, bool useTempDir = false);
static Component* NewComponent(const oms::ComRef& cref, System* parentSystem, const std::string& fmuPath);
static Component* NewComponent(const pugi::xml_node& node, System* parentSystem, const std::string& sspVersion, const Snapshot& snapshot);
const FMUInfo* getFMUInfo() const {return &(this->fmuInfo);}

Expand Down
18 changes: 14 additions & 4 deletions src/OMSimulatorLib/Values.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

#include <iostream>
#include <map>
#include <miniunz.h>
#include <pugixml.hpp>
#include <string>

Expand Down Expand Up @@ -1331,16 +1332,25 @@ void oms::Values::importUnitDefinitions(const pugi::xml_node& node)
}
}

oms_status_enu_t oms::Values::parseModelDescription(const filesystem::path& root)
oms_status_enu_t oms::Values::parseModelDescription(const filesystem::path& root, std::string& guid_)
{

const char* modelDescription = ::miniunz_onefile_to_memory(root.generic_string().c_str(), "modelDescription.xml");

Snapshot snapshot;
snapshot.importResourceFile("modelDescription.xml", root);
oms_status_enu_t status = snapshot.importResourceMemory("modelDescription.xml", modelDescription);
::miniunz_free(modelDescription);

if (oms_status_ok != status)
return logError("Failed to import modelDescription.xml from memory for fmu " + root.generic_string());

const pugi::xml_node node = snapshot.getResourceNode("modelDescription.xml");

if (!node)
return logError("Failed to load modelDescription.xml");
return logError("Failed to find root node in modelDescription.xml");

//std::string fmiVersion = node.attribute("fmiVersion").as_string();
guid_ = node.attribute("guid").as_string();
// std::string fmiVersion = node.attribute("fmiVersion").as_string();

for(pugi::xml_node_iterator it = node.begin(); it != node.end(); ++it)
{
Expand Down
2 changes: 1 addition & 1 deletion src/OMSimulatorLib/Values.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ namespace oms

oms_status_enu_t exportToSSMTemplate(pugi::xml_node& ssmNode, const ComRef& cref); ///< start values read from modelDescription.xml and creates a ssm template

oms_status_enu_t parseModelDescription(const filesystem::path& root); ///< path without the filename, i.e. modelDescription.xml
oms_status_enu_t parseModelDescription(const filesystem::path& root, std::string& guid_); ///< path without the filename, i.e. modelDescription.xml
oms_status_enu_t rename(const oms::ComRef& oldCref, const oms::ComRef& newCref);
oms_status_enu_t renameInResources(const oms::ComRef& oldCref, const oms::ComRef& newCref);

Expand Down
2 changes: 1 addition & 1 deletion testsuite/simulation/multipleInstance.lua
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ oms_delete("model")
-- <ssd:Component
-- name="ypipe"
-- type="application/x-fmu-sharedlibrary"
-- source="resources/0002_ypipe.fmu">
-- source="resources/0004_ypipe.fmu">
-- <ssd:Connectors>
-- <ssd:Connector
-- name="inputRate1"
Expand Down

0 comments on commit 4c9975e

Please sign in to comment.