Commit ade91ef7 authored by Micha Mueller's avatar Micha Mueller
Browse files

Add a bit more comments

parent 053ab4b7
......@@ -120,13 +120,13 @@ counters { // Wrapper structure where the "real" counters are specified.
| PERF_TYPE_RAW | | user can define architecture-specific raw events here.
| " | *XXXX* | Config must be an hex value (without 0x prefix). See <sup>[2](#fn2)</sup>
| | | |
| PERF_TYPE_BREAKPOINT | --- | config not required, any values will be ignored. However config must be specified (even if empty)
| PERF_TYPE_BREAKPOINT | --- | config not required, any values will be ignored. However config must still be specified (even if empty)
#### Footnotes
Taken from the [perf_event_open man-page](http://man7.org/linux/man-pages/man2/perf_event_open.2.html):
<a name="fn1">**1**</a>: The perf_event_paranoid file can be set to restrict access to the performance counters.
<a name="fn1">**1**</a>: &ensp; The perf_event_paranoid file can be set to restrict access to the performance counters.
| Value | Restriction |
|:-----:|:----------- |
......@@ -137,7 +137,7 @@ Taken from the [perf_event_open man-page](http://man7.org/linux/man-pages/man2/p
The existence of the perf_event_paranoid file is the official method for determining if a kernel supports perf_event_open()
<a name="fn2">**2**</a>: If type is *PERF_TYPE_RAW*, then a custom "raw" config value is needed. Most CPUs support events that are not covered by the "generalized" events. These are implementation defined; see your CPU manual (for example the Intel Volume 3B documentation or the AMD BIOS and Kernel Developer Guide). The libpfm4 library can be used to translate from the name in the architectural manual to the raw hex value perf_event_open() expects in this field.
<a name="fn2">**2**</a>: &ensp; If type is *PERF_TYPE_RAW*, then a custom "raw" config value is needed. Most CPUs support events that are not covered by the "generalized" events. These are implementation defined; see your CPU manual (for example the Intel Volume 3B documentation or the AMD BIOS and Kernel Developer Guide). The libpfm4 library can be used to translate from the name in the architectural manual to the raw hex value perf_event_open() expects in this field.
## snmp
......
......@@ -117,8 +117,10 @@ bool Configuration::read() {
//build expected path to sysfs.conf
std::string sysfsConfigFile = _cfgFilePath;
sysfsConfigFile.append("sysfs.conf");
ifstream sysfsStream(sysfsConfigFile.c_str());
if (sysfsStream.good()) {
//sysfs.conf exists --> open sysfs.so and read config
cout << endl << "[INFO] sysfs.conf found" << endl;
sysfs.DL = dlopen("./libsysfs.so", RTLD_NOW);
......@@ -165,6 +167,7 @@ bool Configuration::read() {
//repeat the same procedure for perfevent
std::string perfeventConfigFile = _cfgFilePath;
perfeventConfigFile.append("perfevent.conf");
ifstream perfeventStream(perfeventConfigFile.c_str());
if (perfeventStream.good()) {
cout << endl << "[INFO] perfevent.conf found" << endl;
......@@ -258,7 +261,7 @@ bool Configuration::read() {
cout << "[INFO] ipmi.conf not found. Omitting..." << endl;
}
//TODO check for more config-files
//TODO check for more config-files (--> SNMP)
return true;
}
......
......@@ -26,8 +26,12 @@ typedef struct {
uint32_t threads;
} global_t;
/**
* Class responsible of reading the global configuration as well as loading and invoking required dynamic libraries.
*/
class Configuration {
//struct of values required for a dynamic library.
typedef struct {
void* DL;
Configurator* configurator;
......@@ -79,6 +83,7 @@ private:
sensorVector_t _sensors;
mqttSet_t _mqttSuffixes;
//define a struct for every possible dynamic library
dl_t sysfs;
dl_t perfevent;
dl_t ipmi;
......
......@@ -13,14 +13,23 @@
class Sensor;
/**
* Abstract base class, which defines the interface for the configurators in the shared dynamic libraries.
*/
class Configurator {
public:
Configurator() {}
virtual ~Configurator() {}
/**
* Read in the given configuration
* @param cfgPath Path to the config-file
* @return Reference to the vector of sensors which were created
*/
virtual std::vector<Sensor*>& readConfig(std::string cfgPath) = 0;
};
//typedef for more readable usage of create()- and destroy()-methods, required for dynamic libraries
typedef Configurator* create_t();
typedef void destroy_t(Configurator*);
......
......@@ -16,7 +16,8 @@ MQTTPusher::MQTTPusher(int brokerPort, const std::string& brokerHost,
const std::string& mqttPrefix, sensorVector_t& sensors) :
_brokerPort(brokerPort), _brokerHost(brokerHost),
_mqttPrefix(mqttPrefix),_sensors(sensors),_connected(false) {
//print some info
//first print some info
int mosqMajor, mosqMinor, mosqRevision;
mosquitto_lib_version(&mosqMajor, &mosqMinor, &mosqRevision);
std::cout << "mosquitto " << mosqMajor << "." << mosqMinor << "." << mosqRevision << std::endl;
......@@ -27,7 +28,9 @@ MQTTPusher::MQTTPusher(int brokerPort, const std::string& brokerHost,
}
hostname[255] = '\0';
std::cout << "Hostname: " << hostname << std::endl;
//enough information
//init mosquitto-struct
mosquitto_lib_init();
std::string clientID(_mqttPrefix);
_mosq = mosquitto_new(_mqttPrefix.c_str(), false, NULL);
......@@ -44,6 +47,8 @@ MQTTPusher::~MQTTPusher() {
}
void MQTTPusher::push() {
//connect to broker (if necessary)
while (keepRunning && !_connected) {
if (mosquitto_connect(_mosq, _brokerHost.c_str(), _brokerPort, 1000) != MOSQ_ERR_SUCCESS) {
std::cout << "Mosquitto: could not connect to MQTT broker "
......@@ -55,12 +60,15 @@ void MQTTPusher::push() {
}
}
//collect sensor-data
reading_t* reads = new reading_t[1024];
std::size_t totalCount = 0;
while (keepRunning || totalCount) {
totalCount = 0;
for(auto s : _sensors) {
if (s->getSizeOfReadingQueue() >= s->getMinValues()) {
//there was a (unintended) disconnect in the meantime --> reconnect
if (!_connected) {
if (mosquitto_reconnect(_mosq) != MOSQ_ERR_SUCCESS) {
std::cout << "mosquitto: could not reconnect to MQTT broker " << _brokerHost << ":" << _brokerPort << std::endl;
......@@ -71,6 +79,8 @@ void MQTTPusher::push() {
}
if (_connected) {
//get all sensor values out of its queue
std::size_t count = s->popReadingQueue(reads, 1024);
totalCount+= count;
#ifdef DEBUG
......@@ -79,7 +89,10 @@ void MQTTPusher::push() {
std::cout << " " << reads[i].timestamp << " " << reads[i].value << std::endl;
}
#endif
//try to send them to the broker
if (mosquitto_publish(_mosq, NULL, (_mqttPrefix+s->getMqtt()).c_str(), sizeof(reading_t)*count, reads, 0, false) != MOSQ_ERR_SUCCESS) {
//could not send them --> push the sensor values back into the queue
std::cerr << "mosquitto: could not send message! Trying again later" << std::endl;
mosquitto_disconnect(_mosq);
_connected = false;
......
......@@ -11,6 +11,9 @@
#include "Configuration.h"
#include <mosquitto.h>
/**
* Class responsible for collecting values from the sensors and pushing it to the database.
*/
class MQTTPusher {
public:
MQTTPusher(int brokerPort, const std::string& _brokerHost,
......
......@@ -2,11 +2,7 @@
* Sensor.h
*
* Created on: 12.01.2018
* Author: Micha Mueller
*
* Base class which defines the interface for concrete sensors.
* A concrete (derived) sensor must at least implement the read()-,
* readAsync()- and startPolling()-methods.
* Author: Micha Mueller
*/
#ifndef SENSOR_H_
......@@ -20,7 +16,11 @@ typedef struct {
uint64_t value;
uint64_t timestamp;
} reading_t;
/**
* Abstract base class which defines the interface for concrete sensors.
* A concrete (derived) sensor must at least implement the read()-,
* readAsync()- and startPolling()-methods.
*/
class Sensor {
public:
......
......@@ -72,12 +72,14 @@ int main(int argc, char** argv) {
}
keepRunning = 1;
//Handle Strg+C
signal(SIGINT, sigHandler);
boost::asio::io_service io;
boost::thread_group threads;
Configuration cfg(argv[argc-1]);
//Read in Configuration. Also creates all Sensors
if(!cfg.read()) {
return 1;
}
......@@ -109,6 +111,7 @@ int main(int argc, char** argv) {
}
}
//Init all sensors
for(auto s : sensors) {
#ifdef DEBUG
cout << "Starting sensor " << s->getName() << endl;
......@@ -120,13 +123,16 @@ int main(int argc, char** argv) {
dcdbdaemon();
}
//Create pool of threads which handle the sensors
for(size_t i = 0; i < globalSettings.threads; i++) {
threads.create_thread(bind(static_cast< size_t (boost::asio::io_service::*) () >(&boost::asio::io_service::run), &io));
}
//MQTTPusher gets his own thread
MQTTPusher mqttPusher(globalSettings.brokerPort, globalSettings.brokerHost, globalSettings.mqttPrefix, sensors);
boost::thread mqttThread(bind(&MQTTPusher::push, &mqttPusher));
//Run until Strg+C
mqttThread.join();
threads.join_all();
......
......@@ -35,7 +35,7 @@ namespace DCDB {
}
void IPMISensor::read() {
if (_host != NULL) {
// if (_host != NULL) {
reading_t reading;
reading.timestamp = getTimestamp();
try {
......@@ -51,7 +51,7 @@ namespace DCDB {
std::cout << prettyPrintTimestamp(reading.timestamp) << " " << _host->getHostName() << "::" << _name << " " << _host->getMqttPrefix() << _mqttSuffix << " (" << _readingQueue->read_available() << "/" << _readingQueue->write_available() << ") => " << reading.value << std::endl;
#endif
_readingQueue->push(reading);
}
// }
}
void IPMISensor::readAsync() {
......
......@@ -35,7 +35,6 @@ void PerfCounter::read() {
reading.timestamp = getTimestamp();
long long count;
if (_fd == -1) {return;}
::read(_fd, &count, sizeof(long long));
if (count >= _latestValue.value) {
......
Markdown is supported
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