Commit 9b5d2a0e authored by Micha Mueller's avatar Micha Mueller
Browse files

Use boost::asio strand for serial access to PDUUnit (similiar to IPMIHost)

2 Bugfixes:
-correct initialization of PDUSensors with new()
-cooldown value for XML-file refresh is now correctly converted from MS to NS
parent 331b92ee
......@@ -81,7 +81,7 @@ std::vector<Sensor*>& PDUConfigurator::readConfig(std::string cfgPath) {
BOOST_FOREACH(boost::property_tree::iptree::value_type &sensor, val.second) {
cout << "sensor \"" << sensor.second.data() << "\"" << endl;
if (!sensor.second.empty()) {
PDUSensor pduSensor(sensor.second.data());
PDUSensor* pduSensor = new PDUSensor(sensor.second.data());
//first check if default sensor is given
boost::optional<boost::property_tree::iptree&> defaultC = sensor.second.get_child_optional("default");
......@@ -89,18 +89,18 @@ std::vector<Sensor*>& PDUConfigurator::readConfig(std::string cfgPath) {
cout << " Using \"" << defaultC.get().data() << "\" as default." << endl;
sensorMap_t::iterator it = _templateSensors.find(defaultC.get().data());
if(it != _templateSensors.end()) {
pduSensor = it->second;
pduSensor.setName(sensor.second.data());
*pduSensor = it->second;
pduSensor->setName(sensor.second.data());
} else {
cout << " Template sensor \"" << defaultC.get().data() << "\" not found! Using standard values." << endl;
}
}
//read remaining values
if(readSensor(pduSensor, sensor.second)) {
if(readSensor(*pduSensor, sensor.second)) {
//set pointer to corresponding pdu
pduSensor.setPdu(&pduUnit);
_sensors.push_back(&pduSensor);
pduSensor->setPdu(&pduUnit);
_sensors.push_back(pduSensor);
} else {
cout << " Counter \"" << sensor.second.data() << "\" has bad values! Ignoring..." << endl;
}
......
......@@ -8,9 +8,6 @@
#include "PDUSensor.h"
#include "timestamp.h"
#include <string>
//#include <functional>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>
extern volatile int keepRunning;
......@@ -29,25 +26,13 @@ void PDUSensor::read() {
reading_t reading;
reading.timestamp = getTimestamp();
boost::property_tree::ptree tree = _pdu->getPTree();
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, tree.get_child("clustsafeResponse.energy")) {
if (v.first == "clustsafe") {
int csId = stoi(v.second.get_child("<xmlattr>.id").data());
if (csId == _clustsafeID) {
BOOST_FOREACH(boost::property_tree::ptree::value_type &o, v.second.get_child("outlets")) {
int outId = stoi(o.second.get_child("<xmlattr>.id").data());
if (outId == _outletID) {
reading.value = stoul(o.second.data());
_readingQueue->push(reading);
_latestValue.value = reading.value;
_latestValue.timestamp = reading.timestamp;
return;
}
}
}
}
}
reading.value = _pdu->findValue(_clustsafeID, _outletID);
_readingQueue->push(reading);
_latestValue.value = reading.value;
_latestValue.timestamp = reading.timestamp;
#ifdef DEBUG
std::cout << "[" << prettyPrintTimestamp(reading.timestamp) << "] " << _name << ": \"" << reading.value << "\"" << std::endl;
#endif
}
void PDUSensor::readAsync() {
......@@ -56,7 +41,7 @@ void PDUSensor::readAsync() {
if (_timer != NULL && keepRunning) {
uint64_t next = now + MS_TO_NS(_interval);
_timer->expires_at(timestamp2ptime(next));
_timer->async_wait(std::bind(&PDUSensor::readAsync, this));
_timer->async_wait(_pdu->getStrand()->wrap(std::bind(&PDUSensor::readAsync, this)));
}
}
......@@ -64,8 +49,12 @@ void PDUSensor::startPolling(boost::asio::io_service& io) {
if(!_readingQueue) {
_readingQueue = new boost::lockfree::spsc_queue<reading_t>(1024);
}
//TODO
_timer = new boost::asio::deadline_timer(io, boost::posix_time::seconds(0));
_timer->async_wait(std::bind(&PDUSensor::readAsync, this));
if (_pdu) {
_pdu->initalizeStrand(io);
_timer = new boost::asio::deadline_timer(io, boost::posix_time::seconds(0));
_timer->async_wait(_pdu->getStrand()->wrap(std::bind(&PDUSensor::readAsync, this)));
} else {
std::cout << "No PDUUnit set for Sensor " << _name << "! Can not start polling." << std::endl;
}
}
......@@ -7,30 +7,56 @@
#include "PDUUnit.h"
#include "timestamp.h"
#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
PDUUnit::PDUUnit() {
_cooldown = 1000;
_lastRefresh = 0;
_strand = NULL;
}
PDUUnit::~PDUUnit() {
// TODO Auto-generated destructor stub
}
boost::property_tree::ptree& PDUUnit::getPTree() {
uint64_t PDUUnit::findValue(unsigned clustsafeID, unsigned outletID) {
//TODO use appropriate lock
uint64_t now = getTimestamp();
if (now >= _lastRefresh + _cooldown) {
std::string file = refresh();
boost::property_tree::read_xml(file, _ptree);
if (now >= _lastRefresh + MS_TO_NS(_cooldown)) {
refresh();
#ifdef DEBUG
std::cout << "[" << prettyPrintTimestamp(now) << "] " << "Refreshed XML-file" << std::endl;
#endif
_lastRefresh = now;
}
return _ptree;
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, _ptree.get_child("clustsafeResponse.energy")) {
if (v.first == "clustsafe") {
int csId = stoi(v.second.get_child("<xmlattr>.id").data());
if (csId == clustsafeID) {
BOOST_FOREACH(boost::property_tree::ptree::value_type &o, v.second.get_child("outlets")) {
if (o.first == "outlet") {
int outId = stoi(o.second.get_child("<xmlattr>.id").data());
if (outId == outletID) {
return stoul(o.second.data());
}
}
}
}
}
}
return 0;
}
void PDUUnit::initalizeStrand(boost::asio::io_service& io) {
if (!_strand) {
_strand = new boost::asio::io_service::strand(io);
}
}
std::string PDUUnit::refresh() {
void PDUUnit::refresh() {
//TODO
return "/home/micha/LRZ/energy.xml";
boost::property_tree::read_xml("/home/micha/LRZ/energy.xml", _ptree);
return;
}
......@@ -8,6 +8,7 @@
#ifndef SRC_SENSORS_PDU_PDUUNIT_H_
#define SRC_SENSORS_PDU_PDUUNIT_H_
#include <boost/asio.hpp>
#include <boost/property_tree/ptree.hpp>
class PDUUnit {
......@@ -23,27 +24,33 @@ public:
return _cooldown;
}
void initalizeStrand(boost::asio::io_service& io);
boost::asio::io_service::strand* getStrand() const {
return _strand;
}
/**
* Return _ptree which holds the current data from the XML-sensor file.
* Checks if _ptree is still up to date.
* If not: calls refresh() and overwrites _ptree with a current version.
* Finds and returns the corresponding value in the energy.xml
* Checks if the _ptree is still up to date. If not updates it by a call to refresh().
*
* @return A boost property tree which represents the XML-sensor file
* @param clustsafeID ID of the clustsafe to find in the energy.xml
* @param outletID ID of the outlet to find within the clustsafe
* @return The value in the latest energy.xml, denoted by clustsafeID and outletID
*/
boost::property_tree::ptree& getPTree();
uint64_t findValue(unsigned clustsafeID, unsigned outletID);
private:
/**
* Gets a current version of the XML-file with sensor data.
*
* @return Filename referencing the refreshed XML-file
* Gets a current version of the XML-file energy.xml with sensor data and parses its content into _ptree
*/
std::string refresh();
void refresh();
uint64_t _lastRefresh;
unsigned int _cooldown;
boost::property_tree::ptree _ptree;
boost::asio::io_service::strand* _strand;
};
#endif /* SRC_SENSORS_PDU_PDUUNIT_H_ */
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