Commit 280eb6c5 authored by Michael Ott's avatar Michael Ott
Browse files

Re-Use IPMI connections and SDR cache to speed up sensor readings

parent f02ae71a
......@@ -9,6 +9,9 @@
#include <iostream>
#include <string>
#include <unistd.h>
#if DEBUG
#include "timestamp.h"
#endif
#define LOGM(sev) LOG(sev) << "Mosquitto: "
......@@ -108,7 +111,7 @@ void MQTTPusher::push() {
#if DEBUG
for (std::size_t i=0; i<count; i++) {
LOG(debug) << " " << reads[i].timestamp << " " << reads[i].value;
LOG(debug) << " " << i << ": " << prettyPrintTimestamp(reads[i].timestamp) << " " << reads[i].value;
}
#endif
//try to send them to the broker
......
......@@ -39,6 +39,7 @@ IPMIHost::IPMIHost(const std::string& hostName, uint32_t retransmissionTimeout,
_strand = NULL;
_errorCount = 0;
_delayNextReadUntil = 0;
_lastRead = 0;
}
IPMIHost::~IPMIHost() {
......@@ -49,7 +50,7 @@ IPMIHost::~IPMIHost() {
int IPMIHost::connect() {
if (!(_ipmiCtx = ipmi_ctx_create())) {
throw std::runtime_error("freeipmi Error: " + std::string(strerror(errno)));
throw std::runtime_error("ipmi_ctx_create() Error: " + std::string(strerror(errno)));
return 1;
}
......@@ -62,7 +63,7 @@ int IPMIHost::connect() {
ipmi_ctx_close(_ipmiCtx);
ipmi_ctx_destroy(_ipmiCtx);
_ipmiCtx = NULL;
throw std::runtime_error("freeipmi Error: " + errorMsg);
throw std::runtime_error("ipmi_ctx_open_outofband() Error: " + errorMsg);
return 2;
}
......@@ -70,6 +71,11 @@ int IPMIHost::connect() {
}
int IPMIHost::disconnect() {
if (_sensorReadCtx) {
ipmi_sensor_read_ctx_destroy(_sensorReadCtx);
_sensorReadCtx = NULL;
}
if (_ipmiCtx) {
ipmi_ctx_close(_ipmiCtx);
ipmi_ctx_destroy(_ipmiCtx);
......@@ -79,7 +85,15 @@ int IPMIHost::disconnect() {
return 1;
}
void IPMIHost::createSdrCache() {
void IPMIHost::checkConnection() {
if (_ipmiCtx) {
uint64_t ts = getTimestamp();
if ((ts - _lastRead) > MS_TO_NS(_sessionTimeout)) {
LOG(debug) << "Last read was " << NS_TO_MS((ts - _lastRead)) << "ms ago, timeout is " << _sessionTimeout << "ms. Disconnecting.";
disconnect();
}
}
if (!_ipmiCtx) {
try {
connect();
......@@ -89,34 +103,39 @@ void IPMIHost::createSdrCache() {
return;
}
}
_sensorReadCtx = ipmi_sensor_read_ctx_create(_ipmiCtx);
}
void IPMIHost::createSdrCache() {
_sdrCtx = ipmi_sdr_ctx_create();
std::string errorMsg;
if (ipmi_sdr_cache_create(_sdrCtx, _ipmiCtx, _cache.c_str(), IPMI_SDR_CACHE_CREATE_FLAGS_DEFAULT, NULL, NULL) < 0) {
errorMsg = ipmi_sdr_ctx_errormsg(_sdrCtx);
} else if (ipmi_sdr_cache_open(_sdrCtx, _ipmiCtx, _cache.c_str()) < 0) {
if (ipmi_sdr_cache_open(_sdrCtx, _ipmiCtx, _cache.c_str()) < 0) {
if ((ipmi_sdr_ctx_errnum (_sdrCtx) == IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) || (ipmi_sdr_ctx_errnum (_sdrCtx) == IPMI_SDR_ERR_CACHE_INVALID) || (ipmi_sdr_ctx_errnum (_sdrCtx) == IPMI_SDR_ERR_CACHE_OUT_OF_DATE)) {
if ((ipmi_sdr_ctx_errnum (_sdrCtx) == IPMI_SDR_ERR_CACHE_INVALID) || (ipmi_sdr_ctx_errnum (_sdrCtx) == IPMI_SDR_ERR_CACHE_OUT_OF_DATE)) {
LOG(debug) << "Deleting SDR cache " << _cache;
ipmi_sdr_cache_delete (_sdrCtx, _cache.c_str());
}
ipmi_sdr_cache_open(_sdrCtx, _ipmiCtx, _cache.c_str());
}
}
if (ipmi_sdr_ctx_errnum (_sdrCtx) != IPMI_SDR_ERR_SUCCESS) {
errorMsg = ipmi_sdr_ctx_errormsg(_sdrCtx);
} else {
return;
}
destroySdrCache();
throw std::runtime_error("freeipmi Error: " + errorMsg);
throw std::runtime_error("ipmi_sdr_cache_open Error:" + errorMsg);
return;
}
void IPMIHost::destroySdrCache() {
if (_sdrCtx) {
ipmi_sdr_cache_close(_sdrCtx);
ipmi_sdr_cache_delete(_sdrCtx, _cache.c_str());
ipmi_sdr_ctx_destroy(_sdrCtx);
_sdrCtx = NULL;
}
if (_sensorReadCtx) {
ipmi_sensor_read_ctx_destroy(_sensorReadCtx);
_sensorReadCtx = NULL;
}
return;
}
......@@ -131,25 +150,23 @@ uint64_t IPMIHost::sendRawCmd(const std::vector<uint8_t>& rawCmd,
return 0;
}
if (_ipmiCtx == NULL) {
try {
connect();
} catch (const std::runtime_error& e) {
increaseErrorCount();
throw e;
return 0;
}
try {
checkConnection();
} catch (const std::runtime_error& e) {
increaseErrorCount();
throw e;
return 0;
}
if ((len = ipmi_cmd_raw(_ipmiCtx, rawCmd[0], rawCmd[1], &rawCmd[2],
rawCmd.size() - 2, buf, sizeof(buf))) < 0) {
increaseErrorCount();
throw std::runtime_error("freeipmi Error: " + std::string(ipmi_ctx_errormsg(_ipmiCtx)));
throw std::runtime_error("ipmi_cmd_raw" + std::string(ipmi_ctx_errormsg(_ipmiCtx)));
return 0;
}
disconnect();
_errorCount = 0;
_lastRead = getTimestamp();
#if 0
std::cout << "IPMIHost::sendRawCmd() received " << len << " bytes: " << std::setw(2) << std::setfill('0') << std::hex;
......@@ -173,27 +190,23 @@ uint64_t IPMIHost::sendRawCmd(const std::vector<uint8_t>& rawCmd,
return val;
}
double IPMIHost::readSensor_recordId(uint16_t recordId) {
if (!_ipmiCtx) {
try {
connect();
} catch (const std::runtime_error& e) {
increaseErrorCount();
throw e;
return 0;
}
}
if (!_sensorReadCtx || !_sdrCtx) {
try {
try {
checkConnection();
if (!_sensorReadCtx || !_sdrCtx) {
createSdrCache();
} catch (const std::runtime_error& e) {
increaseErrorCount();
throw e;
return 0;
}
} catch (const std::runtime_error& e) {
increaseErrorCount();
throw e;
return 0;
}
if (!_sensorReadCtx) {
_sensorReadCtx = ipmi_sensor_read_ctx_create(_ipmiCtx);
}
int recordLength = 0;
uint8_t record[IPMI_SDR_MAX_RECORD_LENGTH];
uint8_t rawReading = 0;
......@@ -202,24 +215,24 @@ double IPMIHost::readSensor_recordId(uint16_t recordId) {
if (ipmi_sdr_cache_search_record_id(_sdrCtx, recordId) < 0) {
increaseErrorCount();
throw std::runtime_error("freeipmi Error: " + std::string(ipmi_sdr_ctx_errormsg(_sdrCtx)));
throw std::runtime_error("ipmi_sdr_cache_search_record_id() Error: " + std::string(ipmi_sdr_ctx_errormsg(_sdrCtx)));
return 0;
}
if ((recordLength = ipmi_sdr_cache_record_read(_sdrCtx, record, IPMI_SDR_MAX_RECORD_LENGTH)) < 0) {
increaseErrorCount();
throw std::runtime_error("freeipmi Error: " + std::string(ipmi_sdr_ctx_errormsg(_sdrCtx)));
throw std::runtime_error("ipmi_sdr_cache_record_read Error: " + std::string(ipmi_sdr_ctx_errormsg(_sdrCtx)));
return 0;
}
if (ipmi_sensor_read(_sensorReadCtx, record, recordLength, 0, &rawReading, &reading, &eventBitmask) < 0) {
increaseErrorCount();
throw std::runtime_error("freeipmi Error: " + std::string(ipmi_sensor_read_ctx_errormsg(_sensorReadCtx)));
throw std::runtime_error("ipmi_sensor_read Error: " + std::string(ipmi_sensor_read_ctx_errormsg(_sensorReadCtx)));
return 0;
}
destroySdrCache();
disconnect();
_errorCount = 0;
_lastRead = getTimestamp();
return *reading;
}
......
......@@ -110,6 +110,7 @@ namespace DCDB {
/* Open/close connection to BMC (sets/destroys _ipmiCtx) */
int connect();
int disconnect();
void checkConnection() ;
/* Open and create/destroy SDR cache (sets/destroys _sdrCtx and _sensorReadCtx) */
void createSdrCache();
......@@ -133,6 +134,7 @@ namespace DCDB {
boost::log::sources::severity_logger<boost::log::trivial::severity_level> lg;
uint32_t _errorCount;
volatile uint64_t _delayNextReadUntil;
uint64_t _lastRead;
};
} /* namespace DCDB */
......
......@@ -36,7 +36,9 @@ namespace DCDB {
void IPMISensor::read() {
reading_t reading;
reading.timestamp = getTimestamp();
#if DEBUG
uint64_t ts = getTimestamp();
#endif
try {
if (_recordId != 0) { /* recordId was set */
reading.value = _host->readSensor_recordId(_recordId) * _factor;
......@@ -48,9 +50,11 @@ namespace DCDB {
LOG(error) << _host->getHostName() << "::" << _name << " could not read value: " << e.what();
return;
}
#ifdef DEBUG
LOG(debug) << _host->getHostName() << "::" << _name << ": \"" << reading.value << "\"";
#if DEBUG
LOG(debug) << _host->getHostName() << "::" << _name << ": " << reading.value << " (" << (getTimestamp()-ts)/1000000 << " ms)";
#endif
reading.timestamp = getTimestamp();
storeReading(reading);
}
......
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