diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 18f837d..f9c1283 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -13,7 +13,7 @@ "defines": [], "cStandard": "c23", "intelliSenseMode": "linux-gcc-x64", - "compilerPath": "/usr/bin/g++", + "compilerPath": "/usr/lib64/ccache/g++", "compilerArgs": [ "-std=c++23", "-I/usr/include/", diff --git a/AMPLSolver.cpp b/AMPLSolver.cpp index 928d318..ab90ff8 100644 --- a/AMPLSolver.cpp +++ b/AMPLSolver.cpp @@ -156,6 +156,10 @@ void AMPLSolver::SetAMPLParameter( const std::string & ParameterName, void AMPLSolver::DefineProblem(const Solver::OptimisationProblem & TheProblem, const Address TheOracle) { + Theron::ConsoleOutput Output; + Output << "AMPL Solver: Optimisation problem received " << std::endl + << TheProblem.dump(2) << std::endl; + // First storing the AMPL problem file from its definition in the message // and read the file back to the AMPL interpreter. @@ -230,6 +234,11 @@ void AMPLSolver::DataFileUpdate( const DataFileMessage & TheDataFile, void AMPLSolver::SolveProblem( const ApplicationExecutionContext & TheContext, const Address TheRequester ) { + Theron::ConsoleOutput Output; + + Output << "AMPL Solver: Application Execution Context received. Problem Undefined = " << ProblemUndefined << std::endl + << TheContext.dump(2) << std::endl; + // There is nothing to do if the application model is missing. if( ProblemUndefined ) return; @@ -339,6 +348,8 @@ void AMPLSolver::SolveProblem( OptimisationGoal, ObjectiveValues, VariableValues, DeploymentFlagSet ), TheRequester ); + + Output << "Solver found a solution" << std::endl; } // ----------------------------------------------------------------------------- diff --git a/MetricUpdater.cpp b/MetricUpdater.cpp index 1d6ccf8..c42b66f 100644 --- a/MetricUpdater.cpp +++ b/MetricUpdater.cpp @@ -169,31 +169,25 @@ void MetricUpdater::UpdateMetricValue( void MetricUpdater::SLOViolationHandler( const SLOViolation & SeverityMessage, const Address TheSLOTopic ) { - // The application execution context is constructed first - // as it represents the name and the current values of the recorded - // metrics. - - Solver::MetricValueType TheApplicationExecutionContext; - - for( const auto & [ MetricName, MetricValue ] : MetricValues ) - if( !MetricValue.is_null() ) - TheApplicationExecutionContext.emplace( MetricName, MetricValue ); + Theron::ConsoleOutput Output; + Output << "Metric Updater: SLO violation received " << std::endl + << SeverityMessage.dump(2) << std::endl; // The application context can then be sent to the solution manager - // using the corresponding message, and the time stamp of the severity - // message provided that the size of the execution context equals the - // number of metric values. It will be different if any of the metric - // values has not been updated, and in this case the application execution - // context is invalid and cannot be used for optimisation and the - // SLO violation event will just be ignored. Finally, the flag indicating - // that the corresponding solution found for this application execution - // context should actually be enacted and deployed. + // using the application execution context message provided that none of + // metric values are null indicating that no value has been received (yet) + // Thus, only if all metrics have values will the message be sent. - if( TheApplicationExecutionContext.size() == MetricValues.size() ) + if( !MetricValues.empty() && + std::ranges::none_of( MetricValues, + [](const auto & MetricRecord){ return MetricRecord.second.is_null(); } )) Send( Solver::ApplicationExecutionContext( SeverityMessage.at( NebulOuS::TimePoint ).get< Solver::TimePointType >(), - TheApplicationExecutionContext, true + MetricValues, true ), TheSolverManager ); + else + Output << "... failed to forward the application execution context (size: " + << MetricValues.size() << ")" << std::endl; } // -------------------------------------------------------------------------- diff --git a/SolverComponent.cpp b/SolverComponent.cpp index 2d5d7bb..99b2eab 100644 --- a/SolverComponent.cpp +++ b/SolverComponent.cpp @@ -141,7 +141,7 @@ int main( int NumberOfCLIOptions, char ** CLIOptionStrings ) cxxopts::value()->default_value("NebulOuS::Solver") ) ("P,Port", "TCP port on AMQ Broker", cxxopts::value()->default_value("5672") ) - ("S,Solver", "Solver to use, devault Couenne", + ("S,Solver", "Solver to use, default Couenne", cxxopts::value()->default_value("couenne") ) ("U,User", "The user name used for the AMQ Broker connection", cxxopts::value()->default_value("admin") ) @@ -257,11 +257,13 @@ int main( int NumberOfCLIOptions, char ** CLIOptionStrings ) // The application identifier must also be provided in every message to // allow other receivers to filter on this. - virtual proton::message::property_map - MessageProperties( void ) const override + virtual proton::message::property_map MessageProperties( + const proton::message::property_map & CurrentProperties + = proton::message::property_map() ) const override { proton::message::property_map TheProperties( - Theron::AMQ::NetworkLayer::AMQProperties::MessageProperties() ); + Theron::AMQ::NetworkLayer::AMQProperties::MessageProperties( + CurrentProperties )); TheProperties.put( "application", ApplicationID ); @@ -288,7 +290,7 @@ int main( int NumberOfCLIOptions, char ** CLIOptionStrings ) // -------------------------------------------------------------------------- // // The AMQ communication is managed by the standard communication actors of - // the Theron++ Actor framewokr. Thus, it is just a matter of starting the + // the Theron++ Actor framework. Thus, it is just a matter of starting the // endpoint actors with the given command line parameters. // // The network endpoint takes the endpoint name as the first argument, then