Commit 61f7fefe authored by Alessio Netti's avatar Alessio Netti
Browse files

ProcFS : improved overflow management

- Switched internal buffers to ureading_t types to allow the SensorBase
class to perform all basic overflow and wrap-around checks
- Managing overflows explicitly in the SAR parser, as deltas need to be
calculated beforehand
parent 0c6be4a9
......@@ -137,9 +137,9 @@ std::vector<ProcfsSBPtr> *ProcfsParser::getSensors() {
*
* The parser must have been initialized earlier through the init() method.
*
* @return Pointer to a vector of reading_t structs if the parser is initialized and no errors are encountered, NULL otherwise
* @return Pointer to a vector of ureading_t structs if the parser is initialized and no errors are encountered, NULL otherwise
*/
std::vector<reading_t> *ProcfsParser::readSensors() {
std::vector<ureading_t> *ProcfsParser::readSensors() {
if( !_initialized || !_readMetrics())
return NULL;
return _readings;
......@@ -242,7 +242,7 @@ bool MeminfoParser::_readNames(std::map<std::string, ProcfsSBPtr> *sensorMap, st
*/
bool MeminfoParser::_readMetrics() {
if (_readings == NULL)
_readings = new std::vector<reading_t>(_numMetrics);
_readings = new std::vector<ureading_t>(_numMetrics);
//fseek(_metricsFile, 0, SEEK_SET);
if(_metricsFile) {
......@@ -273,7 +273,7 @@ bool MeminfoParser::_readMetrics() {
// Second token is the actual metric
lineToken = strtok_r(NULL, LINE_SEP, &savePtr);
if (lineToken == NULL) return false;
try { _valueBuffer.value = std::stoll(lineToken); }
try { _valueBuffer.value = std::stoull(lineToken); }
catch (const std::invalid_argument &ia) { return false; }
catch (const std::out_of_range &oor) { return false; }
......@@ -460,7 +460,7 @@ bool ProcstatParser::_readNames(std::map<std::string, ProcfsSBPtr> *sensorMap, s
*/
bool ProcstatParser::_readMetrics() {
if (_readings == NULL)
_readings = new std::vector<reading_t>(_numMetrics);
_readings = new std::vector<ureading_t>(_numMetrics);
//fseek(_metricsFile, 0, SEEK_SET);
if(_metricsFile) {
......@@ -492,7 +492,7 @@ bool ProcstatParser::_readMetrics() {
// Second part of the if: if the line contains node-level CPU metrics (starts with "cpu") and the
// column is flagged with 2 (sample only at node level) then the metric can be sampled
if(_skipColumn[colCtr] == 1 || (_skipColumn[colCtr] == 2 && _l->cpuID<0)) {
try { _readings->at(_l->dest + parsedCols).value += std::stoll(lineToken); }
try { _readings->at(_l->dest + parsedCols).value += std::stoull(lineToken); }
catch (const std::invalid_argument &ia) { return false; }
catch (const std::out_of_range &oor) { return false; }
ctr++;
......@@ -506,7 +506,7 @@ bool ProcstatParser::_readMetrics() {
// This means that for the intr line, only the total number of interrupts raised is captured
lineToken = strtok_r(NULL, LINE_SEP, &savePtr);
if (lineToken == NULL) return false;
try { _readings->at(_l->dest).value = std::stoll(lineToken); }
try { _readings->at(_l->dest).value = std::stoull(lineToken); }
catch (const std::invalid_argument &ia) { return false; }
catch (const std::out_of_range &oor) { return false; }
ctr++;
......@@ -552,7 +552,7 @@ void SARParser::close() {
*/
bool SARParser::_readMetrics() {
if ( _readings == NULL ) {
_readings = new std::vector<reading_t>(_numMetrics);
_readings = new std::vector<ureading_t>(_numMetrics);
_columnRawReadings = new unsigned long long[DEFAULTMETRICS * _lines.size()]();
int accumSize = _htAggr ? _htVal + 1 : _numCPUs + 1;
_accumulators = new unsigned long long[accumSize]();
......@@ -588,10 +588,14 @@ bool SARParser::_readMetrics() {
// We iterate over the line and capture all of the CPU core-related metrics
while((lineToken = strtok_r(NULL, LINE_SEP, &savePtr)) != NULL && colCtr < DEFAULTMETRICS) {
// Computing the difference between the latest reading and the corresponding previous one
try { _latestBuffer = std::stoll(lineToken); }
try { _latestBuffer = std::stoull(lineToken); }
catch (const std::invalid_argument &ia) { return false; }
catch (const std::out_of_range &oor) { return false; }
_latestValue = _latestBuffer - _columnRawReadings[(lineCtr-1)*DEFAULTMETRICS + colCtr];
// Overflow checking - this occurrence is extremely rare (if not impossible) on /proc/stat values
if(_latestBuffer >= _columnRawReadings[(lineCtr-1)*DEFAULTMETRICS + colCtr])
_latestValue = _latestBuffer - _columnRawReadings[(lineCtr-1)*DEFAULTMETRICS + colCtr];
else
return false;
_columnRawReadings[(lineCtr-1)*DEFAULTMETRICS + colCtr] = _latestBuffer;
_accumulators[accIdx] += _latestValue;
// Second part of the if: if the line contains node-level CPU metrics (starts with "cpu") and the
......@@ -608,7 +612,7 @@ bool SARParser::_readMetrics() {
// This means that for the intr line, only the total number of interrupts raised is captured
lineToken = strtok_r(NULL, LINE_SEP, &savePtr);
if (lineToken == NULL) return false;
try { _readings->at(_l->dest).value = std::stoll(lineToken); }
try { _readings->at(_l->dest).value = std::stoull(lineToken); }
catch (const std::invalid_argument &ia) { return false; }
catch (const std::out_of_range &oor) { return false; }
ctr++;
......
......@@ -77,7 +77,7 @@ public:
void setPath(std::string new_path) { _path = new_path; close(); }
std::vector<ProcfsSBPtr> *getSensors();
std::vector<reading_t> *readSensors();
std::vector<ureading_t> *readSensors();
protected:
// Private parsing methods that implement all necessary logic to parse metrics' names (and associated CPU cores, if any)
......@@ -89,7 +89,7 @@ protected:
// After initialization, _sensors is always non-NULL.
std::vector<ProcfsSBPtr> *_sensors;
// Vector of performed readings
std::vector<reading_t> *_readings;
std::vector<ureading_t> *_readings;
// Keeps track of which lines and columns in the parsed file must be skipped
std::vector<ProcLine> _lines;
// Pointer to the current line being parsed
......@@ -132,9 +132,9 @@ protected:
int _memTotalLine;
int _memFreeLine;
reading_t _memTotalValue;
reading_t _memFreeValue;
reading_t _valueBuffer;
ureading_t _memTotalValue;
ureading_t _memFreeValue;
ureading_t _valueBuffer;
const std::string _memUsedToken = "MemUsed";
};
......
......@@ -84,8 +84,8 @@ private:
// Set of cpu ids read during configuration
std::set<int> _cpuSet;
std::vector<reading_t> *_readingVector;
reading_t _readingBuffer;
std::vector<ureading_t> *_readingVector;
ureading_t _readingBuffer;
};
using ProcfsSGPtr = std::shared_ptr<ProcfsSensorGroup>;
......
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