Commit 969a8d0f authored by corentinberge's avatar corentinberge Committed by GitHub

Merge branch 'master' into coverage

parents 4271a05a 1bcf9a54
......@@ -41,6 +41,7 @@ SET(PKG_CONFIG_EXTRA "plugindir=${PLUGINDIR}")
PKG_CONFIG_APPEND_LIBS(${PROJECT_NAME})
# Search for Boost.
SET(BOOST_COMPONENTS serialization system unit_test_framework thread)
SEARCH_FOR_BOOST()
SEARCH_FOR_PTHREAD()
......
......@@ -35,11 +35,11 @@ Inside the constructor of the entity:
\endcode
The first line sets the frequency at which the logger will be updated.<br>
The second line specifies at which frequency the message should be
The second line specifies at which frequency the STREAM messages should be
printed.<br>
The third line specifies the level of message to accept.<br>
The fourth line returns the level of verbosity.
In this case, all messages are accepted. <br>
In this case, all messages are accepted and the STREAM message are displayed on the output streams once on five. <br>
The full list of options are:
<ul>
......@@ -54,15 +54,19 @@ The full list of options are:
Here is some example on how to display or record some information.
\code
sendMsg("This is a message of level MSG_TYPE_DEBUG",MSG_TYPE_DEBUG);
sendMsg("This is a message of level MSG_TYPE_INFO",MSG_TYPE_INFO);
sendMsg("This is a message of level MSG_TYPE_WARNING",MSG_TYPE_WARNING);
sendMsg("This is a message of level MSG_TYPE_ERROR",MSG_TYPE_ERROR);
sendMsg("This is a message of level MSG_TYPE_DEBUG_STREAM",MSG_TYPE_DEBUG_STREAM);
sendMsg("This is a message of level MSG_TYPE_INFO_STREAM",MSG_TYPE_INFO_STREAM);
sendMsg("This is a message of level MSG_TYPE_WARNING_STREAM",MSG_TYPE_WARNING_STREAM);
sendMsg("This is a message of level MSG_TYPE_ERROR_STREAM",MSG_TYPE_ERROR_STREAM);
sendMsg("This is a message of level MSG_TYPE_DEBUG",MSG_TYPE_DEBUG, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_INFO",MSG_TYPE_INFO, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_WARNING",MSG_TYPE_WARNING, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_ERROR",MSG_TYPE_ERROR, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_DEBUG_STREAM",MSG_TYPE_DEBUG_STREAM, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_INFO_STREAM",MSG_TYPE_INFO_STREAM, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_WARNING_STREAM",MSG_TYPE_WARNING_STREAM, __FILE__,__LINE__);
sendMsg("This is a message of level MSG_TYPE_ERROR_STREAM",MSG_TYPE_ERROR_STREAM, __FILE__,__LINE__);
logger_.countdown();
\endcode
Specifying the file with __FILE__ and the line inside the file by __LINE__ are necessary for the
STREAM messages. Indeed they are indexed using the two values. As the default value are "" and 0
the counting will be confused.
*/
......@@ -112,7 +112,24 @@ namespace dynamicgraph
/// \brief Get the logger's verbosity level.
LoggerVerbosity getLoggerVerbosityLevel()
{ return logger_.getVerbosity(); };
{ return logger_.getVerbosity(); }
/// \brief Set the time sample.
bool setTimeSample(double t)
{ return logger_.setTimeSample(t); }
/// \brief Get the time sample.
double getTimeSample()
{ return logger_.getTimeSample();}
/// \brief Set the period of the stream period
bool setStreamPrintPeriod(double t)
{ return logger_.setStreamPrintPeriod(t); }
/// \brief Get the period of the stream period
double getStreamPrintPeriod()
{ return logger_.getStreamPrintPeriod();}
protected:
void addCommand(const std::string& name,command::Command* command);
......
......@@ -178,9 +178,16 @@ namespace dynamicgraph {
* is going to be called. */
bool setTimeSample(double t);
/** Get the sampling time at which the method countdown()
* is going to be called. */
double getTimeSample();
/** Set the time period for printing of streaming messages. */
bool setStreamPrintPeriod(double s);
/** Get the time period for printing of streaming messages. */
double getStreamPrintPeriod();
/** Set the verbosity level of the logger. */
void setVerbosity(LoggerVerbosity lv);
......
/* Copyright LAAS, CNRS
* Author: O. Stasse, 2019
* See LICENSE file in the root directory of this repository.
*/
#ifndef DYNAMIC_GRAPH_PROCESS_LIST_H_
# define DYNAMIC_GRAPH_PROCESS_LIST_H
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
# include <dynamic-graph/fwd.hh>
# include <dynamic-graph/dynamic-graph-api.h>
namespace dynamicgraph
{
namespace CPU
{
class DYNAMIC_GRAPH_DLLAPI ProcessData
{
};
class DYNAMIC_GRAPH_DLLAPI ProcessList
{
public:
ProcessList();
};
/// \class This class gather information on a specific CPU.
///
class DYNAMIC_GRAPH_DLLAPI CPUData
{
public:
CPUData();
int cpu_id_;
inline unsigned long long int
computePeriod(unsigned long long int &a,
unsigned long long int &b)
{
return (a>b) ? a-b :0;
}
/// \brief Various classes of time spend by the CPU
/// @{
/// Total time
unsigned long long int total_time_;
/// Time spend in user mode
unsigned long long int user_mode_time_;
/// Time spend in user mode with low priority (nice mode)
unsigned long long int nice_time_;
/// Time spend in system mode
unsigned long long int system_time_;
/// Time spend in system mode
unsigned long long int system_all_time_;
/// Time spend in doing nothing.
unsigned long long int idle_time_;
/// Time spend in doing nothing.
unsigned long long int idle_all_time_;
/// Time spend in waiting an input/output to complete.
unsigned long long int iowait_time_;
/// Time spend in servicing hardware interrupts.
unsigned long long int irq_time_;
/// Time spend in servicing software interrupts.
unsigned long long int softirq_time_;
/// Time spend in other operating systems in a virtualized environments
/// Never doing this for control !
unsigned long long int steal_time_;
/// Time spend running a virtual CPU for guest operating systems
/// under the control of the Linux kernel
unsigned long long int guest_time_;
/// Time spent running a niced guest
/// (virtual CPU for guest operating systems under the
/// control of the Linux kernel)
unsigned long long int guest_nice_time_;
/// @}
/// \brief Various classes of time spend by the CPU by period
/// @{
/// Total time
unsigned long long int total_period_;
/// Time spend in user mode
unsigned long long int user_mode_period_;
/// Time spend in user mode with low priority (nice mode)
unsigned long long int nice_period_;
/// Time spend in system mode
unsigned long long int system_period_;
/// Time spend in all system mode
unsigned long long int system_all_period_;
/// Time spend in doing nothing.
unsigned long long int idle_period_;
/// Time spend in doing nothing.
unsigned long long int idle_all_period_;
/// Time spend in waiting an input/output to complete.
unsigned long long int iowait_period_;
/// Time spend in servicing hardware interrupts.
unsigned long long int irq_period_;
/// Time spend in servicing software interrupts.
unsigned long long int softirq_period_;
/// Time spend in other operating systems in a virtualized environments
/// Never doing this for control !
unsigned long long int steal_period_;
/// Time spend running a virtual CPU for guest operating systems
/// under the control of the Linux kernel
unsigned long long int guest_period_;
/// @}
double percent_;
void ProcessLine(std::istringstream &aCPULine);
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & version;
ar & total_time_;
ar & user_mode_time_;
ar & nice_time_;
ar & system_time_;
ar & system_all_time_;
ar & idle_time_;
ar & idle_all_time_;
ar & iowait_time_;
ar & irq_time_;
ar & softirq_time_;
ar & steal_time_;
ar & guest_time_;
ar & guest_nice_time_;
ar & percent_;
}
};
/// \class This class gathers information on a computer.
/// This includes a list of CPU
class DYNAMIC_GRAPH_DLLAPI System
{
private:
bool init_;
public:
System();
/// Read /proc/state file to extract CPU count.
void init();
/// Update CPU data information from /proc/stat
void readProcStat();
/// Friend class for serialization.
friend class boost::serialization::access;
/// Number of CPU.
unsigned int cpuNb_;
void ProcessCPULine(unsigned int cpunb,
std::istringstream &aCPULine);
/// \brief Vector of CPU informations.
std::vector<CPUData> vCPUData_;
/// \brief Global CPU information.
CPUData gCPUData_;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & version;
ar & cpuNb_;
ar & gCPUData_;
ar & vCPUData_;
}
};
}
}
#endif /* DYNAMIC_GRAPH_PROCESS_LIST_H_ */
......@@ -132,8 +132,9 @@ namespace dynamicgraph
std::string next2="" ) const;
protected: // Interdiction of the rest of the heritage
using Signal<T,Time>::addDependency;
virtual void addDependency () {}
using Signal<T,Time>::removeDependency;
virtual void removeDependency () {}
virtual void clearDependencies () {}
......
......@@ -30,6 +30,8 @@ ADD_LIBRARY(${LIBRARY_NAME}
exception/exception-signal.cpp
exception/exception-traces.cpp
mt/process-list.cpp
signal/signal-array.cpp
signal/signal-caster.cpp
signal/signal-cast-helper.cpp
......
......@@ -63,7 +63,7 @@ namespace dynamicgraph
//TODO Modif ici
// if print is allowed by current verbosity level
if(isStreamMsg(type))
if( isStreamMsg(type))
{
int l = line;
// check whether counter already exists
......@@ -80,7 +80,10 @@ namespace dynamicgraph
if(it->second>0.0)
{
it->second -= m_timeSample;
return;
if (it->second<=0.0)
it->second = m_streamPrintPeriod;
else
return;
}
else // otherwise reset counter and print
it->second = m_streamPrintPeriod;
......@@ -103,4 +106,14 @@ namespace dynamicgraph
m_streamPrintPeriod = s;
return true;
}
double Logger::getTimeSample()
{
return m_timeSample;
}
double Logger::getStreamPrintPeriod()
{
return m_streamPrintPeriod;
}
} // namespace dynamicgraph
......@@ -74,35 +74,67 @@ namespace dynamicgraph
struct RealTimeLogger::thread
{
bool requestShutdown_;
int threadPolicy_;
int threadPriority_;
bool changedThreadParams;
boost::thread t_;
thread (RealTimeLogger* logger)
: requestShutdown_ (false)
, threadPolicy_(SCHED_OTHER)
, threadPriority_(0)
, changedThreadParams(true)
, t_ (&thread::spin, this, logger)
{}
void spin (RealTimeLogger* logger)
void setThreadPolicy(int policy)
{
threadPolicy_ = policy;
changedThreadParams = true;
}
void setPriority(int priority)
{
threadPriority_ = priority;
changedThreadParams = true;
}
int getThreadPolicy() { return threadPolicy_; }
int getThreadPriority() { return threadPriority_; }
void changeThreadParams()
{
// Change the thread's scheduler from real-time to normal and reduce its priority
int threadPolicy;
struct sched_param threadParam;
if (pthread_getschedparam (pthread_self(), &threadPolicy, &threadParam) == 0)
{
threadPolicy = SCHED_OTHER;
threadParam.sched_priority -= 5;
if (threadParam.sched_priority < sched_get_priority_min (threadPolicy))
threadParam.sched_priority = sched_get_priority_min (threadPolicy);
if (pthread_getschedparam (pthread_self(), &threadPolicy, &threadParam)
== 0)
{
threadPolicy = threadPolicy_;
threadParam.sched_priority = threadPriority_;
if (threadParam.sched_priority <
sched_get_priority_min (threadPolicy))
threadParam.sched_priority = sched_get_priority_min (threadPolicy);
pthread_setschedparam (pthread_self(), threadPolicy, &threadParam);
}
pthread_setschedparam (pthread_self(), threadPolicy, &threadParam);
changedThreadParams = false;
}
}
void spin (RealTimeLogger* logger)
{
// Change the thread's scheduler from real-time to normal
// and reduce its priority
while (!requestShutdown_ || !logger->empty())
{
// If the logger did not write anything, it means the buffer is empty.
// Do a pause
if (!logger->spinOnce())
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
}
{
// If the logger did not write anything, it means the buffer is empty.
// Do a pause
if (!logger->spinOnce())
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
if (changedThreadParams)
changeThreadParams();
}
}
};
......
/* Copyright LAAS, CNRS
* Author: O. Stasse, 2019
* See LICENSE file in the root directory of this repository.
*/
#include <fstream>
#include <sstream>
#include <string>
#include <dynamic-graph/process-list.hh>
using namespace dynamicgraph::CPU;
CPUData::CPUData():
user_mode_time_(0),
nice_time_(0),
system_time_(0),
idle_time_(0),
iowait_time_(0),
irq_time_(0),
softirq_time_(0),
steal_time_(0),
guest_time_(0),
guest_nice_time_(0),
percent_(0.0)
{
}
void CPUData::ProcessLine(std::istringstream &aCPULine)
{
unsigned long long int luser_mode_time=0,
lnice_time=0, lsystem_time=0, lidle_time=0,
liowait_time=0, lirq_time=0, lsoftirq_time=0,
lsteal_time=0,lguest_time=0, lguest_nice_time;
aCPULine >> luser_mode_time;
aCPULine >> lnice_time;
aCPULine >> lsystem_time;
aCPULine >> lidle_time;
aCPULine >> liowait_time;
aCPULine >> lirq_time;
aCPULine >> lsoftirq_time;
aCPULine >> lsteal_time;
aCPULine >> lguest_time;
aCPULine >> lguest_nice_time;
// Remove guest time already in user_time:
luser_mode_time -= lguest_time;
lnice_time -= lguest_nice_time;
// Compute cumulative time
unsigned long long int lidle_all_time=0,
lsystem_all_time=0, lguest_all_time=0, ltotal_time=0;
lidle_all_time = lidle_time + liowait_time;
lsystem_all_time = lsystem_time + lirq_time + lsoftirq_time;
lguest_all_time = lguest_time + lguest_nice_time;
ltotal_time = luser_mode_time + lnice_time + lsystem_all_time +
lidle_all_time + lsteal_time + lguest_all_time;
// Update periodic computation.
user_mode_period_ = computePeriod(luser_mode_time, user_mode_time_);
nice_period_ = computePeriod(lnice_time, nice_time_);
system_period_ = computePeriod(lsystem_time, system_time_);
system_all_period_ = computePeriod(lsystem_all_time,system_all_time_);
idle_period_ = computePeriod(lidle_time, idle_time_);
idle_all_period_ = computePeriod(lidle_all_time, idle_all_time_);
iowait_period_ = computePeriod(liowait_time, idle_time_);
irq_period_ = computePeriod(lirq_time, irq_time_);
softirq_period_ = computePeriod(lsoftirq_time, softirq_time_);
steal_period_ = computePeriod(lsteal_time, steal_time_);
guest_period_ = computePeriod(lguest_all_time, guest_time_);
total_period_ = computePeriod(ltotal_time, total_time_);
/// Update time.
user_mode_time_ = luser_mode_time;
nice_time_ = lnice_time;
system_time_ = lsystem_time;
system_all_time_ = lsystem_all_time;
idle_time_ = lidle_time;
idle_all_time_ = lidle_all_time;
iowait_time_ = liowait_time;
irq_time_ = lirq_time;
softirq_time_ = lsoftirq_time;
steal_time_ = lsteal_time;
guest_time_ = lguest_all_time;
total_time_ = ltotal_time;
if (total_period_!=0.0)
{
percent_ = (double)(user_mode_period_)/(double)(total_period_) * 100.0;
percent_ += (double)( nice_period_)/(double)(total_period_) * 100.0;
percent_ += (double)( system_period_)/(double)(total_period_) * 100.0;
percent_ += (double)( irq_period_)/(double)(total_period_) * 100.0;
percent_ += (double)( softirq_period_)/(double)(total_period_) * 100.0;
percent_ += (double)( steal_period_)/(double)(total_period_) * 100.0;
percent_ += (double)( iowait_period_)/(double)(total_period_) * 100.0;
}
std::cout << cpu_id_ << " " << percent_ << std::endl;
}
System::System()
{
vCPUData_.clear();
init();
}
void System::init()
{
init_ = false;
readProcStat();
init_ = true;
}
void System::ProcessCPULine(unsigned int cpunb,
std::istringstream &aCPULine)
{
vCPUData_[cpunb].ProcessLine(aCPULine);
}
void System::readProcStat()
{
std::ifstream aif;
cpuNb_ = 1;
aif.open("/proc/stat",std::ifstream::in);
std::string aline;
aline.clear();
while (std::getline(aif,aline))
{
// Read on line of the file
std::istringstream anISSLine(aline);
std::string line_hdr;
anISSLine >> line_hdr;
// Check if the line start with cpu
std::size_t pos = line_hdr.find("cpu");
std::string str_cpunbr = line_hdr.substr(pos+3);
// Check if this is the first line
if (pos==0 and str_cpunbr.empty())
{
gCPUData_.ProcessLine(anISSLine);
gCPUData_.cpu_id_=-1;
}
else
{
// If not then check if there is a CPU number
if (pos==0)
{
std::istringstream iss(str_cpunbr);
unsigned int lcpunb;
iss >> lcpunb;
// If we did not initialize
if (!init_)
{
// Count the number of CPU.
if (lcpunb>cpuNb_)
cpuNb_ = lcpunb;
}
else
// Otherwise process the line.
ProcessCPULine(lcpunb,anISSLine);
}
}
}
if (!init_)
{
/// The number of CPU has been detected by going through /proc/stat.
vCPUData_.resize(cpuNb_+1);
for(int i=0;i<(int)cpuNb_;i++)
vCPUData_[i].cpu_id_ = i;
}
aif.close();
}
......@@ -62,3 +62,6 @@ TARGET_LINK_LIBRARIES(debug-tracer tracer)
DYNAMIC_GRAPH_TEST(debug-logger)
DYNAMIC_GRAPH_TEST(debug-logger-winit)
DYNAMIC_GRAPH_TEST(signal-all)
DYNAMIC_GRAPH_TEST(command-test)
DYNAMIC_GRAPH_TEST(test-mt)
TARGET_LINK_LIBRARIES(test-mt tracer)
\ No newline at end of file
/* Copyright 2019, LAAS-CNRS
*
* Olivier Stasse
*
* See LICENSE file
*
*/
#include <sstream>
#include <iostream>
#include <dynamic-graph/entity.h>
#include <dynamic-graph/exception-factory.h>
#include "dynamic-graph/factory.h"
#include "dynamic-graph/pool.h"
#include "dynamic-graph/command-bind.h"
#define ENABLE_RT_LOG
#include <dynamic-graph/real-time-logger.h>
#include <dynamic-graph/logger.h>
#define BOOST_TEST_MODULE debug-logger
#include <boost/test/unit_test.hpp>
#include <boost/test/output_test_stream.hpp>
using boost::test_tools::output_test_stream;
using namespace dynamicgraph::command;
namespace dynamicgraph
{
class CustomEntity : public Entity
{
public:
static const std::string CLASS_NAME;
bool test_zero_arg_;
bool test_one_arg_;
bool test_two_args_;
bool test_three_args_;
bool test_four_args_;
virtual const std::string& getClassName () const
{
return CLASS_NAME;
}
CustomEntity (const std::string n)
: Entity (n)
{
test_zero_arg_ = false;
test_one_arg_ = false;
test_two_args_ = false;
test_three_args_ = false;
test_four_args_ = false;
addCommand("0_arg",
makeCommandVoid0(*this, &CustomEntity::zero_arg,
docCommandVoid0("zero arg")));
addCommand("1_arg",
makeCommandVoid1(*this, &CustomEntity::one_arg,
docCommandVoid1("one arg",
"int")));
addCommand("2_args",
makeCommandVoid2(*this, &CustomEntity::two_args,
docCommandVoid2("two args",
"int",
"int")));
addCommand("3_args",
makeCommandVoid3(*this, &CustomEntity::three_args,
docCommandVoid3("three args",
"int","int","int")));
addCommand("4_args",
makeCommandVoid4(*this, &CustomEntity::four_args,
docCommandVoid4("four args",
"int",
"int",
"int",
"int")));
}
~CustomEntity()
{
}
void zero_arg()
{
test_zero_arg_ = true;
}
void one_arg(const int & )
{
test_one_arg_ = true;
}
void two_args(const int & ,
const int & )
{
test_two_args_ = true;
}
void three_args(const int & ,
const int & ,
const int & )
{
test_three_args_ = true;
}
void four_args(const int & ,
const int & ,
const int & ,
const int & )
{
test_four_args_ = true;
}
};
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN (CustomEntity,"CustomEntity");