Commit 13aef3cc authored by Alessio Netti's avatar Alessio Netti
Browse files

Analytics: Job Units in UnitGenerator

- UnitGenerator is now capable of generating job-associated units
- A job unit is hierarchical, and it has the sub-units related to the
nodes it was executed on as children
- Code is still untested
parent a4041689
...@@ -158,6 +158,27 @@ public: ...@@ -158,6 +158,27 @@ public:
return sensors; return sensors;
} }
/**
* @brief Resolves and formats a string encoding a tree level in function of a job id
*
* This method takes as input strings in the format specified for parseNodeLevelString(). It then
* takes as input also a job Id. The method will then return the one sensor encoded by s that is
* associated to the input job ID. This method is meant to be a simplified version of
* resolveNodeLevelString.
*
* @param s String to be parsed
* @param job Job ID to be used
* @return Resulting sensor name associated to the input job id
*/
string resolveJobString(const string& s, const string& job) {
string newName = s;
if(!boost::regex_search(s.c_str(), _match, _blockRx))
throw invalid_argument("JobUnitGenerator: sensor string is incorrectly formatted!");
else
boost::regex_replace(newName, _blockRx, job);
return newName;
}
/** /**
* @brief Computes and instantiates units associated to the input analyzer * @brief Computes and instantiates units associated to the input analyzer
* *
...@@ -241,7 +262,7 @@ public: ...@@ -241,7 +262,7 @@ public:
* @param inputMode Defines the method with which input sensors are instantiated for each unit * @param inputMode Defines the method with which input sensors are instantiated for each unit
* @param mqttPrefix MQTT prefix to use for output sensors if only the "root" unit is defined * @param mqttPrefix MQTT prefix to use for output sensors if only the "root" unit is defined
* @param relaxed If True, checks on the existence of input sensors are ignored * @param relaxed If True, checks on the existence of input sensors are ignored
* @return A vector of shared pointers to the generated unit objects * @return A shared pointer to the generated unit object
*/ */
shared_ptr<UnitTemplate<SBase>> generateUnit(const string& u, vector<shared_ptr<SBase>>& inputs, vector<shared_ptr<SBase>>& outputs, shared_ptr<UnitTemplate<SBase>> generateUnit(const string& u, vector<shared_ptr<SBase>>& inputs, vector<shared_ptr<SBase>>& outputs,
inputMode_t inputMode, string mqttPrefix="", bool relaxed=false) { inputMode_t inputMode, string mqttPrefix="", bool relaxed=false) {
...@@ -261,6 +282,67 @@ public: ...@@ -261,6 +282,67 @@ public:
return _generateUnit(u, inputs, outputs, inputMode, mqttPrefix, relaxed); return _generateUnit(u, inputs, outputs, inputMode, mqttPrefix, relaxed);
} }
/**
* @brief Computes and instantiates a job unit
*
* Job units slightly differ from conventional units. First, they are hierarchical: the top
* unit is related to the job itself, and contains all job-related outputs that are
* eventually propagated. This unit does not have inputs, as in, sensors. Then, there are as
* many children units as nodes on which the job was executed: for each of these, all of the
* inputs that were specified are present, together with node-related outputs.
*
* @param j Job identifier used to name the unit
* @param nodes Vector of node identifiers on which the job was executed
* @param inputs The vector of "prototype" sensor objects for inputs
* @param outputs The vector of "prototype" sensor objects for outputs
* @param inputMode Defines the method with which input sensors are instantiated for each unit
* @param mqttPrefix MQTT prefix to use for the output sensors at the job level
* @param relaxed If True, checks on the existence of input sensors are ignored
* @return A shared pointers to the generated job unit object
*/
shared_ptr<UnitTemplate<SBase>> generateJobUnit(const string& j, vector<std::string>& nodes, vector<shared_ptr<SBase>>& inputs,
vector<shared_ptr<SBase>>& outputs, inputMode_t inputMode, string mqttPrefix="", bool relaxed=false) {
// If no outputs are defined, no units can be instantiated
if((inputs.size()==0 && inputMode==SELECTIVE) || outputs.size() == 0)
throw invalid_argument("JobUnitGenerator: Invalid inputs or outputs!");
// Output sensors must share the same unit pattern
if(!isConsistent(outputs))
throw invalid_argument("JobUnitGenerator: Incoherent output levels!");
shared_ptr<UnitTemplate<SBase>> jobUnit = make_shared<UnitTemplate<SBase>>();
jobUnit->setName(j);
try {
for (const auto &nodeName : nodes) {
// The unit specified as input must belong to the domain of the outputs
if (!nodeBelongsToPattern(nodeName, outputs[0]->getName()))
throw domain_error("JobUnitGenerator: Node " + nodeName + " does not belong to this unit domain!");
jobUnit->addSubUnit(_generateUnit(nodeName, inputs, outputs, inputMode, mqttPrefix, relaxed));
}
} catch(const invalid_argument& e) {
jobUnit->clear();
throw invalid_argument("JobUnitGenerator: One or more node sub-units for job " + j + " could not be generated!");
}
// Mapping outputs
for(const auto& out : outputs) {
SBase uOut(*out);
uOut.setName(resolveJobString(uOut.getName(), j));
uOut.setMqtt(_navi->buildTopicForNode(j, uOut.getMqtt()));
// Duplicating the file sink adding the name of each unit to the path
string sPath = uOut.getSinkPath();
if(sPath != "") {
size_t idx = sPath.find_last_of("/\\");
if( idx != string::npos)
uOut.setSinkPath(sPath.substr(0, idx+1) + j + "_" + sPath.substr(idx+1, string::npos));
else
uOut.setSinkPath(j + "_" + sPath);
}
jobUnit->addOutput(uOut);
}
return jobUnit;
}
/** /**
* @brief Duplicates the input unit * @brief Duplicates the input unit
* *
......
...@@ -118,6 +118,22 @@ public: ...@@ -118,6 +118,22 @@ public:
return *this; return *this;
} }
/**
* @brief Class destructor
*/
virtual ~UnitTemplate() { clear(); }
/**
* @brief Clears this unit
*/
void clear() {
_baseInputs.clear();
_inputs.clear();
_baseOutputs.clear();
_outputs.clear();
_subUnits.clear();
}
/** /**
* @brief Sets the name of this unit * @brief Sets the name of this unit
* *
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment