Skip to content

Commit 75b5523

Browse files
authored
add support for timeval columns (#138)
1 parent b6331de commit 75b5523

14 files changed

Lines changed: 254 additions & 29 deletions

‎src/Makefile.am‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ livestatus_la_SOURCES = \
1818
ListColumn.cc ListColumnFilter.cc OffsetDoubleColumn.cc OffsetIntColumn.cc \
1919
OffsetStringColumn.cc OffsetTimeperiodColumn.cc OringFilter.cc OutputBuffer.cc \
2020
OffsetTimeColumn.cc TimeColumn.cc TimeColumnFilter.cc PerfdataAggregator.cc \
21+
OffsetTimeValColumn.cc TimeValColumn.cc TimeValColumnFilter.cc \
2122
Query.cc ServiceContactsColumn.cc ServicegroupsColumn.cc ServicelistColumn.cc \
2223
ServicelistColumnFilter.cc ServicelistStateColumn.cc store.cc Store.cc \
2324
StringColumn.cc StringColumnFilter.cc strutil.cc Table.cc TableColumns.cc \

‎src/OffsetTimeValColumn.cc‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright (c) 2026 Naemon team - license: GPL-2.0
2+
// This file is part of the naemon project: https://www.naemon.io
3+
// See LICENSE file in the project root for details.
4+
5+
#include "nagios.h"
6+
#include <stdint.h>
7+
#include "OffsetTimeValColumn.h"
8+
9+
struct timeval OffsetTimeValColumn::getValue(void *data, Query *)
10+
{
11+
if (!data)
12+
return {0, 0};
13+
14+
char *p = (char *)shiftPointer(data);
15+
if (p)
16+
return *(struct timeval *)(p + _offset);
17+
else
18+
return {0, 0};
19+
}

‎src/OffsetTimeValColumn.h‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2026 Naemon team - license: GPL-2.0
2+
// This file is part of the naemon project: https://www.naemon.io
3+
// See LICENSE file in the project root for details.
4+
5+
#ifndef OffsetTimeValColumn_h
6+
#define OffsetTimeValColumn_h
7+
8+
#include "config.h"
9+
10+
#include <stdlib.h>
11+
#include "TimeValColumn.h"
12+
13+
14+
/* This does almost the same as the time column,
15+
but applies a timezone offset stored in the Query. */
16+
17+
class OffsetTimeValColumn : public TimeValColumn
18+
{
19+
int _offset;
20+
public:
21+
OffsetTimeValColumn(string name, string description, int offset, int indirect_offset = -1)
22+
: TimeValColumn(name, description, indirect_offset), _offset(offset) {}
23+
struct timeval getValue(void *data, Query *);
24+
protected:
25+
int offset() { return _offset; }
26+
};
27+
28+
29+
#endif // OffsetTimeValColumn_h

‎src/Query.cc‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,12 @@ void Query::outputTime(time_t value)
11821182
outputInteger64((int64_t)value);
11831183
}
11841184

1185+
void Query::outputTimeVal(timeval value)
1186+
{
1187+
char buf[64];
1188+
int l = snprintf(buf, sizeof(buf), "%lu.%06lu", value.tv_sec + _timezone_offset, value.tv_usec);
1189+
_output->addBuffer(buf, l);
1190+
}
11851191

11861192
void Query::outputUnsignedLong(unsigned long value)
11871193
{

‎src/Query.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class Query
100100
void outputInteger(int32_t);
101101
void outputInteger64(int64_t);
102102
void outputTime(time_t);
103+
void outputTimeVal(timeval);
103104
void outputUnsignedLong(unsigned long);
104105
void outputCounter(counter_t);
105106
void outputDouble(double);

‎src/TableHosts.cc‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "OffsetStringColumn.h"
1313
#include "OffsetIntColumn.h"
1414
#include "OffsetTimeColumn.h"
15+
#include "OffsetTimeValColumn.h"
1516
#include "OffsetDoubleColumn.h"
1617
#include "OffsetTimeperiodColumn.h"
1718
#include "OffsetStringHostMacroColumn.h"
@@ -140,8 +141,8 @@ void TableHosts::addColumns(Table *table, string prefix, int indirect_offset)
140141
"Scheduled time for the next check (Unix timestamp)", (char *)(&hst.next_check) - ref, indirect_offset));
141142
table->addColumn(new OffsetTimeColumn(prefix + "last_hard_state_change",
142143
"Time of the last hard state change (Unix timestamp)", (char *)(&hst.last_hard_state_change) - ref, indirect_offset));
143-
table->addColumn(new OffsetTimeColumn(prefix + "last_update",
144-
"Time of the last update of this host (Unix timestamp)", (char *)(&hst.last_update) - ref, indirect_offset));
144+
table->addColumn(new OffsetTimeValColumn(prefix + "last_update",
145+
"Time of the last update of this host (Unix timestamp Microsecond Precision)", (char *)(&hst.last_update) - ref, indirect_offset));
145146
table->addColumn(new OffsetIntColumn(prefix + "has_been_checked",
146147
"Whether the host has already been checked (0/1)", (char *)(&hst.has_been_checked) - ref, indirect_offset));
147148
/* FIXME: hourly_value is an unsigned int... */

‎src/TableServices.cc‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "OffsetStringColumn.h"
1313
#include "OffsetIntColumn.h"
1414
#include "OffsetTimeColumn.h"
15+
#include "OffsetTimeValColumn.h"
1516
#include "OffsetDoubleColumn.h"
1617
#include "OffsetTimeperiodColumn.h"
1718
#include "OffsetStringServiceMacroColumn.h"
@@ -295,8 +296,8 @@ void TableServices::addColumns(Table *table, string prefix, int indirect_offset,
295296
"The time of the last state change - soft or hard (Unix timestamp)", (char *)&svc.last_state_change - ref, indirect_offset));
296297
table->addColumn(new OffsetTimeColumn(prefix + "last_hard_state_change",
297298
"The time of the last hard state change (Unix timestamp)", (char *)&svc.last_hard_state_change - ref, indirect_offset));
298-
table->addColumn(new OffsetTimeColumn(prefix + "last_update",
299-
"Time of the last update of this service (Unix timestamp)", (char *)(&svc.last_update) - ref, indirect_offset));
299+
table->addColumn(new OffsetTimeValColumn(prefix + "last_update",
300+
"Time of the last update of this service (Unix timestamp Microsecond Precision)", (char *)(&svc.last_update) - ref, indirect_offset));
300301
table->addColumn(new OffsetIntColumn(prefix + "scheduled_downtime_depth",
301302
"The number of scheduled downtimes the service is currently in", (char *)(&svc.scheduled_downtime_depth) - ref, indirect_offset));
302303
table->addColumn(new OffsetIntColumn(prefix + "is_flapping",

‎src/TimeColumnFilter.cc‎

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@
99
#include "logger.h"
1010
#include "opids.h"
1111

12-
TimeColumnFilter::TimeColumnFilter(TimeColumn *column, int opid, char *value)
12+
TimeColumnFilter::TimeColumnFilter(TimeColumn *column, int opid, char *value)
1313
: _column(column)
1414
, _opid(abs(opid))
1515
, _negate(opid < 0)
16-
, _ref_string(value)
16+
, _ref_value(convertRefValue(value))
1717
{
1818
}
1919

2020
// offset from Localtime: header
21-
time_t TimeColumnFilter::convertRefValue()
21+
time_t TimeColumnFilter::convertRefValue(const char *value)
2222
{
23-
time_t ref_remote = atoi(_ref_string.c_str());
23+
time_t ref_remote = atoi(value);
2424
if (_query) {
2525
time_t timezone_offset = _query->timezoneOffset();
2626
return ref_remote - timezone_offset;
@@ -33,14 +33,13 @@ bool TimeColumnFilter::accepts(void *data)
3333
{
3434
bool pass = true;
3535
time_t act_value = _column->getValue(data, _query);
36-
time_t ref_value = convertRefValue();
3736
switch (_opid) {
3837
case OP_EQUAL:
39-
pass = act_value == ref_value; break;
38+
pass = act_value == _ref_value; break;
4039
case OP_GREATER:
41-
pass = act_value > ref_value; break;
40+
pass = act_value > _ref_value; break;
4241
case OP_LESS:
43-
pass = act_value < ref_value; break;
42+
pass = act_value < _ref_value; break;
4443
default:
4544
logger(LG_INFO, "Sorry. Operator %s for time_t not implemented.", op_names_plus_8[_opid]);
4645
break;
@@ -57,49 +56,47 @@ void TimeColumnFilter::findTimeLimits(const char *columnname, time_t *lower, tim
5756
return; // already empty interval
5857
}
5958

60-
time_t ref_value = convertRefValue();
61-
6259
/* [lower, upper[ is some interval. This filter might restrict
6360
that interval to a smaller interval.
6461
*/
6562
int opref = _opid * (_negate != false ? -1 : 1);
6663
switch (opref) {
6764
case OP_EQUAL:
68-
if (ref_value >= *lower && ref_value < *upper) {
69-
*lower = ref_value;
70-
*upper = ref_value + 1;
65+
if (_ref_value >= *lower && _ref_value < *upper) {
66+
*lower = _ref_value;
67+
*upper = _ref_value + 1;
7168
}
7269
else
7370
*lower = *upper;
7471
return;
7572

7673
case -OP_EQUAL:
77-
if (ref_value == *lower)
74+
if (_ref_value == *lower)
7875
*lower = *lower + 1;
79-
else if (ref_value == *upper - 1)
76+
else if (_ref_value == *upper - 1)
8077
*upper = *upper - 1;
8178
return;
8279

8380
case OP_GREATER:
84-
if (ref_value >= *lower) {
85-
*lower = ref_value + 1;
81+
if (_ref_value >= *lower) {
82+
*lower = _ref_value + 1;
8683
}
8784

8885
return;
8986

9087
case OP_LESS:
91-
if (ref_value < *upper)
92-
*upper = ref_value;
88+
if (_ref_value < *upper)
89+
*upper = _ref_value;
9390
return;
9491

9592
case -OP_GREATER: // LESS OR EQUAL
96-
if (ref_value < *upper - 1)
97-
*upper = ref_value + 1;
93+
if (_ref_value < *upper - 1)
94+
*upper = _ref_value + 1;
9895
return;
9996

10097
case -OP_LESS: // GREATER OR EQUAL
101-
if (ref_value > *lower)
102-
*lower = ref_value;
98+
if (_ref_value > *lower)
99+
*lower = _ref_value;
103100
return;
104101
}
105102
}

‎src/TimeColumnFilter.h‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ class TimeColumnFilter : public Filter
1313
TimeColumn *_column;
1414
int _opid;
1515
bool _negate;
16-
string _ref_string;
16+
time_t _ref_value;
1717
public:
1818
TimeColumnFilter(TimeColumn *column, int opid, char *value);
19-
time_t convertRefValue();
19+
time_t convertRefValue(const char *value);
2020
bool accepts(void *data);
2121
void findTimeLimits(const char *columnname, time_t *lower, time_t *upper);
2222
};

‎src/TimeValColumn.cc‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2025 Naemon team - license: GPL-2.0
2+
// This file is part of the naemon project: https://www.naemon.io
3+
// See LICENSE file in the project root for details.
4+
5+
#include "TimeValColumn.h"
6+
#include "TimeValColumnFilter.h"
7+
#include "Query.h"
8+
9+
void TimeValColumn::output(void *data, Query *query)
10+
{
11+
query->outputTimeVal(getValue(data, query));
12+
}
13+
14+
Filter *TimeValColumn::createFilter(int operator_id, char *value)
15+
{
16+
return new TimeValColumnFilter(this, operator_id, value);
17+
}
18+
19+
20+
string TimeValColumn::valueAsString(void *data, Query *query)
21+
{
22+
char i[64];
23+
struct timeval value = (struct timeval)getValue(data, query);
24+
snprintf(i, sizeof(i), "%lu.%06lu", value.tv_sec, value.tv_usec);
25+
return i;
26+
}
27+
28+
int TimeValColumn::compare(void *dataa, void*datab, Query *query) {
29+
struct timeval a = getValue(dataa, query);
30+
struct timeval b = getValue(datab, query);
31+
if( a.tv_sec==b.tv_sec && a.tv_usec==b.tv_usec ) return 0;
32+
return (a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec)) ? 1 : -1;
33+
}

0 commit comments

Comments
 (0)