initial commit

This commit is contained in:
Phillip Smith
2021-08-24 17:55:37 +10:00
commit 69e42aac8d
387 changed files with 69168 additions and 0 deletions

51
src/Aggregator.h Normal file
View File

@@ -0,0 +1,51 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef Aggregator_h
#define Aggregator_h
#include "config.h" // IWYU pragma: keep
#include <cmath>
#include <functional>
#include "Renderer.h"
#include "Row.h"
#include "contact_fwd.h"
class Query;
class Aggregation {
public:
virtual ~Aggregation() = default;
virtual void update(double value) = 0;
[[nodiscard]] virtual double value() const = 0;
};
class Aggregator {
public:
virtual ~Aggregator() = default;
virtual void consume(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) = 0;
virtual void output(RowRenderer &r) const = 0;
};
#endif // Aggregator_h

167
src/AndingFilter.cc Normal file
View File

@@ -0,0 +1,167 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "AndingFilter.h"
#include <algorithm>
#include <iterator>
#include <memory>
#include <ostream>
#include <type_traits>
#include <vector>
#include "Filter.h"
#include "OringFilter.h"
#include "Row.h"
// static
std::unique_ptr<Filter> AndingFilter::make(Kind kind, Filters subfilters) {
Filters filters;
for (const auto &filter : subfilters) {
if (filter->is_contradiction()) {
return OringFilter::make(kind, Filters());
}
auto conjuncts = filter->conjuncts();
filters.insert(filters.end(),
std::make_move_iterator(conjuncts.begin()),
std::make_move_iterator(conjuncts.end()));
}
return filters.size() == 1 ? std::move(filters[0])
: std::make_unique<AndingFilter>(
kind, std::move(filters), Secret());
}
bool AndingFilter::accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const {
for (const auto &filter : _subfilters) {
if (!filter->accepts(row, auth_user, timezone_offset)) {
return false;
}
}
return true;
}
std::unique_ptr<Filter> AndingFilter::partialFilter(
std::function<bool(const Column &)> predicate) const {
Filters filters;
std::transform(
_subfilters.begin(), _subfilters.end(), std::back_inserter(filters),
[&](const auto &filter) { return filter->partialFilter(predicate); });
return make(kind(), std::move(filters));
}
std::optional<std::string> AndingFilter::stringValueRestrictionFor(
const std::string &column_name) const {
for (const auto &filter : _subfilters) {
if (auto value = filter->stringValueRestrictionFor(column_name)) {
return {value};
}
}
return {};
}
std::optional<int32_t> AndingFilter::greatestLowerBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const {
std::optional<int32_t> result;
for (const auto &filter : _subfilters) {
if (auto glb =
filter->greatestLowerBoundFor(column_name, timezone_offset)) {
result = result ? std::max(*result, *glb) : glb;
}
}
return result;
}
std::optional<int32_t> AndingFilter::leastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const {
std::optional<int32_t> result;
for (const auto &filter : _subfilters) {
if (auto lub =
filter->leastUpperBoundFor(column_name, timezone_offset)) {
result = result ? std::min(*result, *lub) : lub;
}
}
return result;
}
std::optional<std::bitset<32>> AndingFilter::valueSetLeastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const {
std::optional<std::bitset<32>> result;
for (const auto &filter : _subfilters) {
if (auto foo = filter->valueSetLeastUpperBoundFor(column_name,
timezone_offset)) {
result = result ? (*result & *foo) : foo;
}
}
return result;
}
std::unique_ptr<Filter> AndingFilter::copy() const {
return make(kind(), conjuncts());
}
std::unique_ptr<Filter> AndingFilter::negate() const {
Filters filters;
std::transform(_subfilters.begin(), _subfilters.end(),
std::back_inserter(filters),
[](const auto &filter) { return filter->negate(); });
return OringFilter::make(kind(), std::move(filters));
}
bool AndingFilter::is_tautology() const { return _subfilters.empty(); }
bool AndingFilter::is_contradiction() const { return false; }
Filters AndingFilter::disjuncts() const {
Filters filters;
filters.push_back(copy());
return filters;
}
Filters AndingFilter::conjuncts() const {
Filters filters;
std::transform(_subfilters.begin(), _subfilters.end(),
std::back_inserter(filters),
[](const auto &filter) { return filter->copy(); });
return filters;
}
std::ostream &AndingFilter::print(std::ostream &os) const {
for (const auto &filter : _subfilters) {
os << *filter << "\\n";
}
switch (kind()) {
case Kind::row:
os << "And";
break;
case Kind::stats:
os << "StatsAnd";
break;
case Kind::wait_condition:
os << "WaitConditionAnd";
break;
}
return os << ": " << _subfilters.size();
}

81
src/AndingFilter.h Normal file
View File

@@ -0,0 +1,81 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef AndingFilter_h
#define AndingFilter_h
#include "config.h" // IWYU pragma: keep
#include <bitset>
#include <chrono>
#include <cstdint>
#include <functional>
#include <iosfwd>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "Filter.h"
#include "contact_fwd.h"
class Column;
class Row;
class AndingFilter : public Filter {
struct Secret {};
public:
static std::unique_ptr<Filter> make(Kind kind, Filters subfilters);
bool accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
std::unique_ptr<Filter> partialFilter(
std::function<bool(const Column &)> predicate) const override;
[[nodiscard]] std::optional<std::string> stringValueRestrictionFor(
const std::string &column_name) const override;
[[nodiscard]] std::optional<int32_t> greatestLowerBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::optional<int32_t> leastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::optional<std::bitset<32>> valueSetLeastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> copy() const override;
[[nodiscard]] std::unique_ptr<Filter> negate() const override;
[[nodiscard]] bool is_tautology() const override;
[[nodiscard]] bool is_contradiction() const override;
[[nodiscard]] Filters disjuncts() const override;
[[nodiscard]] Filters conjuncts() const override;
// NOTE: This is effectively private, but it can't be declared like this
// because of std::make_unique.
AndingFilter(Kind kind, Filters subfilters, Secret /*unused*/)
: Filter(kind), _subfilters(std::move(subfilters)) {}
private:
Filters _subfilters;
std::ostream &print(std::ostream &os) const override;
};
#endif // AndingFilter_h

View File

@@ -0,0 +1,48 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef AtomicInt32PointerColumn_h
#define AtomicInt32PointerColumn_h
#include "config.h" // IWYU pragma: keep
#include <atomic>
#include "IntColumn.h"
class AtomicInt32PointerColumn : public IntColumn {
public:
AtomicInt32PointerColumn(const std::string& name,
const std::string& description,
const std::atomic_int32_t* number)
: IntColumn(name, description, -1, -1, -1, 0), _number(number) {}
int32_t getValue(Row /* row */,
const contact* /* auth_user */) const override {
return _number->load();
}
private:
const std::atomic_int32_t* const _number;
};
#endif // AtomicInt32PointerColumn_h

View File

@@ -0,0 +1,103 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "AttributeListAsIntColumn.h"
#include <bitset>
#include <cctype>
#include <map>
#include <memory>
#include <ostream>
#include <utility>
#include "Filter.h"
#include "IntFilter.h"
#include "Logger.h"
#include "Row.h"
#include "strutil.h"
namespace {
// see MODATTR_FOO in nagios/common.h
std::map<std::string, unsigned long> known_attributes = {
{"notifications_enabled", 0}, {"active_checks_enabled", 1},
{"passive_checks_enabled", 2}, {"event_handler_enabled", 3},
{"flap_detection_enabled", 4}, {"failure_prediction_enabled", 5},
{"performance_data_enabled", 6}, {"obsessive_handler_enabled", 7},
{"event_handler_command", 8}, {"check_command", 9},
{"normal_check_interval", 10}, {"retry_check_interval", 11},
{"max_check_attempts", 12}, {"freshness_checks_enabled", 13},
{"check_timeperiod", 14}, {"custom_variable", 15},
{"notification_timeperiod", 16}};
using modified_atttibutes = std::bitset<32>;
std::string refValueFor(const std::string &value, Logger *logger) {
if (isdigit(value[0]) != 0) {
return value;
}
std::vector<char> value_vec(value.begin(), value.end());
value_vec.push_back('\0');
char *scan = &value_vec[0];
modified_atttibutes values;
for (const char *t; (t = next_token(&scan, ',')) != nullptr;) {
auto it = known_attributes.find(t);
if (it == known_attributes.end()) {
Informational(logger)
<< "Ignoring invalid value '" << t << "' for attribute list";
continue;
}
values[it->second] = true;
}
return std::to_string(values.to_ulong());
}
} // namespace
std::unique_ptr<Filter> AttributeListAsIntColumn::createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const {
return std::make_unique<IntFilter>(kind, *this, relOp,
refValueFor(value, logger()));
}
int32_t AttributeListAsIntColumn::getValue(
Row row, const contact * /*auth_user*/) const {
if (auto p = columnData<unsigned long>(row)) {
return static_cast<int32_t>(*p);
}
return 0;
}
std::vector<std::string> AttributeListAsIntColumn::getAttributes(
Row row) const {
std::vector<std::string> attributes;
if (auto p = columnData<unsigned long>(row)) {
modified_atttibutes values(*p);
for (const auto &entry : known_attributes) {
if (values[entry.second]) {
attributes.push_back(entry.first);
}
}
}
return attributes;
}

View File

@@ -0,0 +1,57 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef AttributeListAsIntColumn_h
#define AttributeListAsIntColumn_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "Filter.h"
#include "IntColumn.h"
#include "contact_fwd.h"
#include "opids.h"
class Row;
class AttributeListAsIntColumn : public IntColumn {
public:
AttributeListAsIntColumn(const std::string &name,
const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: IntColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
int32_t getValue(Row row, const contact *auth_user) const override;
[[nodiscard]] std::vector<std::string> getAttributes(Row row) const;
};
#endif // AttributeListAsIntColumn_h

View File

@@ -0,0 +1,41 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "AttributeListColumn.h"
#include <memory>
#include <vector>
#include "Filter.h" // IWYU pragma: keep
#include "Row.h"
std::unique_ptr<Filter> AttributeListColumn::createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const {
return _int_view_column.createFilter(kind, relOp, value);
}
std::vector<std::string> AttributeListColumn::getValue(
Row row, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
return _int_view_column.getAttributes(row);
}

62
src/AttributeListColumn.h Normal file
View File

@@ -0,0 +1,62 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef AttributeListColumn_h
#define AttributeListColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include <vector>
#include "AttributeListAsIntColumn.h"
#include "Filter.h"
#include "ListColumn.h"
#include "contact_fwd.h"
#include "opids.h"
class Row;
class AttributeListColumn : public ListColumn {
public:
AttributeListColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _int_view_column(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
private:
AttributeListAsIntColumn _int_view_column;
};
#endif // AttributeListColumn_h

99
src/BitMask.h Normal file
View File

@@ -0,0 +1,99 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2017 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef BitMask_h
#define BitMask_h
#include "config.h" // IWYU pragma: keep
#include <type_traits>
namespace mk {
// Return the enumerator's value as a compile-time constant, see Scott Meyer's
// "Effective Modern C++", item 10.
template <typename Enum>
constexpr auto toUType(Enum e) noexcept {
return static_cast<std::underlying_type_t<Enum>>(e);
}
// A marker trait which enables the bit mask operators
template <typename Enum>
struct is_bit_mask {
static const bool value = false;
};
// A helper macro to make the use sites of the marker trait less verbose
#define IS_BIT_MASK(ENUM) \
namespace mk { \
template <> \
struct is_bit_mask<ENUM> { \
static const bool value = true; \
}; \
}
// A helper template to make template definitions a bit shorter
template <typename T>
constexpr bool is_bit_mask_v = is_bit_mask<T>::value;
} // namespace mk
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline constexpr Enum operator&(Enum x, Enum y) {
return x &= y;
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline constexpr Enum operator|(Enum x, Enum y) {
return x |= y;
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline constexpr Enum operator^(Enum x, Enum y) {
return x ^= y;
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline constexpr Enum operator~(Enum x) {
return Enum(~mk::toUType(x));
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline Enum &operator|=(Enum &x, Enum y) {
return x = Enum(mk::toUType(x) | mk::toUType(y));
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline const Enum &operator&=(Enum &x, Enum y) {
return x = Enum(mk::toUType(x) & mk::toUType(y));
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline Enum &operator^=(Enum &x, Enum y) {
return x = Enum(mk::toUType(x) ^ mk::toUType(y));
}
template <typename Enum, typename = std::enable_if_t<mk::is_bit_mask_v<Enum>>>
inline bool is_empty_bit_mask(Enum x) {
return x == Enum(0);
}
#endif // BitMask_h

50
src/BlobColumn.cc Normal file
View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "BlobColumn.h"
#include <stdexcept>
#include "Renderer.h"
#include "Row.h"
void BlobColumn::output(Row row, RowRenderer& r, const contact* /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
if (std::unique_ptr<std::vector<char>> blob = getValue(row)) {
r.output(*blob);
} else {
r.output(Null());
}
}
std::unique_ptr<Filter> BlobColumn::createFilter(
Filter::Kind /*unused*/, RelationalOperator /*unused*/,
const std::string& /*unused*/) const {
throw std::runtime_error("filtering on blob column '" + name() +
"' not supported");
}
std::unique_ptr<Aggregator> BlobColumn::createAggregator(
AggregationFactory /*factory*/) const {
throw std::runtime_error("aggregating on blob column '" + name() +
"' not supported");
}

65
src/BlobColumn.h Normal file
View File

@@ -0,0 +1,65 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef BlobColumn_h
#define BlobColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include <vector>
#include "Column.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class Aggregator;
class Row;
class RowRenderer;
class BlobColumn : public Column {
public:
BlobColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset, int extra_extra_offset,
int offset)
: Column(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
[[nodiscard]] ColumnType type() const override { return ColumnType::blob; }
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
[[nodiscard]] std::unique_ptr<Aggregator> createAggregator(
AggregationFactory factory) const override;
[[nodiscard]] virtual std::unique_ptr<std::vector<char>> getValue(
Row row) const = 0;
};
#endif // BlobColumn_h

142
src/ChronoUtils.h Normal file
View File

@@ -0,0 +1,142 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ChronoUtils_h
#define ChronoUtils_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <ratio>
#include <string>
#include <utility>
using minutes_d = std::chrono::duration<double, std::ratio<60>>;
inline double elapsed_ms_since(std::chrono::steady_clock::time_point then) {
return std::chrono::duration_cast<
std::chrono::duration<double, std::milli>>(
std::chrono::steady_clock::now() - then)
.count();
}
inline tm to_tm(std::chrono::system_clock::time_point tp) {
time_t t = std::chrono::system_clock::to_time_t(tp);
struct tm ret;
// NOTE: A brilliant example of how to make a simple API function a total
// chaos follows...
#if defined(__STDC_LIB_EXT1__)
// C11 function, only guaranteed to be available when a
// #define __STDC_WANT_LIB_EXT1_ 1
// is done before including <time.h>. Signature:
// struct tm *localtime_s(const time_t *restrict timer,
// struct tm *restrict result)
localtime_s(&t, &ret);
#elif defined(__WIN32)
// Win32 variant, it keeps us entertained with swapped parameters and a
// different return value, yay! Signature:
// errno_t localtime_s(struct tm* _tm, const time_t *time)
// We have to de-confuse cppcheck:
// cppcheck-suppress uninitvar
localtime_s(&ret, &t);
#else
// POSIX.1-2008 variant, available under MinGW64 only under obscure
// circumstances, so better avoid it there. Signature:
// struct tm *localtime_r(const time_t *restrict timer,
// struct tm *restrict result);
localtime_r(&t, &ret);
#endif
// Reason: see Win32 section above
// cppcheck-suppress uninitvar
return ret;
}
inline std::chrono::system_clock::time_point from_tm(tm tp) {
return std::chrono::system_clock::from_time_t(mktime(&tp));
}
template <typename Rep, typename Period>
inline timeval to_timeval(std::chrono::duration<Rep, Period> dur) {
timeval tv;
// NOTE: The static_casts below are needed to avoid warning on e.g. some
// 32bit platforms, because the underlying types might be larger than the
// timeval fields. We can't use the correct POSIX types time_t and
// suseconds_t because of the broken MinGW cross compiler, so we revert to
// decltype.
tv.tv_sec = static_cast<decltype(tv.tv_sec)>(
std::chrono::duration_cast<std::chrono::seconds>(dur).count());
tv.tv_usec = static_cast<decltype(tv.tv_usec)>(
std::chrono::duration_cast<std::chrono::microseconds>(
dur % std::chrono::seconds(1))
.count());
return tv;
}
inline std::chrono::system_clock::time_point from_timeval(const timeval &tv) {
return std::chrono::system_clock::time_point(
std::chrono::seconds(tv.tv_sec) +
std::chrono::microseconds(tv.tv_usec));
}
inline std::chrono::system_clock::time_point parse_time_t(
const std::string &str) {
return std::chrono::system_clock::from_time_t(atoi(str.c_str()));
}
template <typename Dur>
typename Dur::rep time_point_part(std::chrono::system_clock::time_point &tp) {
return std::chrono::duration_cast<Dur>(tp.time_since_epoch() % Dur(1000))
.count();
}
class FormattedTimePoint {
public:
explicit FormattedTimePoint(std::chrono::system_clock::time_point tp,
std::string format = default_format)
: _tp(tp), _format(std::move(format)) {}
explicit FormattedTimePoint(time_t t, std::string format = default_format)
: _tp(std::chrono::system_clock::from_time_t(t))
, _format(std::move(format)) {}
friend std::ostream &operator<<(std::ostream &os,
const FormattedTimePoint &f) {
tm local = to_tm(f._tp);
return os << std::put_time(&local, f._format.c_str());
}
private:
std::chrono::system_clock::time_point _tp;
std::string _format;
// NOTE: In a perfect world we would simply use "%F %T" below, but the "%F"
// format is a C99 addition, and the "%T" format is part of The Single Unix
// Specification. Both formats should be available in any C++11-compliant
// compiler, but the MinGW cross compiler doesn't get this right. So let's
// use their ancient expansions...
static constexpr auto default_format = "%Y-%m-%d %H:%M:%S";
};
#endif // ChronoUtils_h

64
src/ClientQueue.cc Normal file
View File

@@ -0,0 +1,64 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ClientQueue.h"
#include <unistd.h>
#include <algorithm>
ClientQueue::ClientQueue() : _should_terminate(false) {}
ClientQueue::~ClientQueue() {
std::for_each(_queue.begin(), _queue.end(), close);
}
void ClientQueue::addConnection(int fd) {
{
std::lock_guard<std::mutex> lg(_mutex);
_queue.push_back(fd);
}
_cond.notify_one();
}
int ClientQueue::popConnection() {
std::unique_lock<std::mutex> ul(_mutex);
while (_queue.empty() && !_should_terminate) {
_cond.wait(ul);
}
if (_queue.empty()) {
return -1;
}
int fd = _queue.front();
_queue.pop_front();
return fd;
}
// Note: What we *really* want here is the functionality of
// notify_all_at_thread_exit.
void ClientQueue::terminate() {
{
std::lock_guard<std::mutex> lg(_mutex);
_should_terminate = true;
}
_cond.notify_all();
}

50
src/ClientQueue.h Normal file
View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ClientQueue_h
#define ClientQueue_h
#include "config.h" // IWYU pragma: keep
#include <condition_variable>
#include <deque>
#include <mutex>
class ClientQueue {
public:
ClientQueue();
~ClientQueue();
void addConnection(int fd);
int popConnection();
void terminate();
private:
// The mutext protects _queue and _should_terminate, and it works together
// with the condition variable.
std::mutex _mutex;
std::deque<int> _queue;
bool _should_terminate;
std::condition_variable _cond;
};
#endif // ClientQueue_h

57
src/Column.cc Normal file
View File

@@ -0,0 +1,57 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "Column.h"
#include <utility>
#include "Logger.h"
Column::Column(std::string name, std::string description, int indirect_offset,
int extra_offset, int extra_extra_offset, int offset)
: _logger(Logger::getLogger("cmk.livestatus"))
, _name(std::move(name))
, _description(std::move(description))
, _indirect_offset(indirect_offset)
, _extra_offset(extra_offset)
, _extra_extra_offset(extra_extra_offset)
, _offset(offset) {}
namespace {
const void *add(const void *data, int offset) {
return (data == nullptr || offset < 0) ? data
: offset_cast<void>(data, offset);
}
const void *shift(const void *data, int offset) {
return (data == nullptr || offset < 0)
? data
: *offset_cast<const void *>(data, offset);
}
} // namespace
const void *Column::shiftPointer(Row row) const {
return add(shift(shift(shift(row.rawData<const void>(), _indirect_offset),
_extra_offset),
_extra_extra_offset),
_offset);
}

95
src/Column.h Normal file
View File

@@ -0,0 +1,95 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef Column_h
#define Column_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <cstddef>
#include <functional>
#include <memory>
#include <string>
#include "Filter.h"
#include "Row.h"
#include "contact_fwd.h"
#include "opids.h"
class Aggregation;
class Aggregator;
class Logger;
class RowRenderer;
template <typename T>
const T *offset_cast(const void *ptr, size_t offset) {
// cppcheck is too dumb to see that this is just pointer arithmetic... :-/
// cppcheck-suppress invalidPointerCast
return reinterpret_cast<const T *>(reinterpret_cast<const char *>(ptr) +
offset);
}
enum class ColumnType { int_, double_, string, list, time, dict, blob, null };
using AggregationFactory = std::function<std::unique_ptr<Aggregation>()>;
class Column {
public:
Column(std::string name, std::string description, int indirect_offset,
int extra_offset, int extra_extra_offset, int offset);
virtual ~Column() = default;
[[nodiscard]] std::string name() const { return _name; }
[[nodiscard]] std::string description() const { return _description; }
template <typename T>
[[nodiscard]] const T *columnData(Row row) const {
return static_cast<const T *>(shiftPointer(row));
}
[[nodiscard]] virtual ColumnType type() const = 0;
virtual void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const = 0;
[[nodiscard]] virtual std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const = 0;
[[nodiscard]] virtual std::unique_ptr<Aggregator> createAggregator(
AggregationFactory factory) const = 0;
[[nodiscard]] Logger *logger() const { return _logger; }
private:
Logger *const _logger;
std::string _name;
std::string _description;
int _indirect_offset;
int _extra_offset;
int _extra_extra_offset;
int _offset;
[[nodiscard]] const void *shiftPointer(Row row) const;
};
#endif // Column_h

51
src/ColumnFilter.cc Normal file
View File

@@ -0,0 +1,51 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ColumnFilter.h"
#include "AndingFilter.h"
std::unique_ptr<Filter> ColumnFilter::partialFilter(
std::function<bool(const Column &)> predicate) const {
return predicate(_column) ? copy() : AndingFilter::make(kind(), Filters());
}
bool ColumnFilter::is_tautology() const { return false; }
bool ColumnFilter::is_contradiction() const { return false; }
Filters ColumnFilter::disjuncts() const {
Filters filters;
filters.push_back(copy());
return filters;
}
Filters ColumnFilter::conjuncts() const {
Filters filters;
filters.push_back(copy());
return filters;
}
std::ostream &ColumnFilter::print(std::ostream &os) const {
return os << "Filter: " << columnName() << " " << oper() << " " << value();
}

64
src/ColumnFilter.h Normal file
View File

@@ -0,0 +1,64 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ColumnFilter_h
#define ColumnFilter_h
#include "config.h" // IWYU pragma: keep
#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include "Column.h"
#include "Filter.h"
#include "opids.h"
class ColumnFilter : public Filter {
public:
ColumnFilter(Kind kind, const Column &column, RelationalOperator relOp,
std::string value)
: Filter(kind)
, _column(column)
, _relOp(relOp)
, _value(std::move(value)) {}
[[nodiscard]] std::string columnName() const { return _column.name(); }
[[nodiscard]] RelationalOperator oper() const { return _relOp; }
[[nodiscard]] std::string value() const { return _value; }
std::unique_ptr<Filter> partialFilter(
std::function<bool(const Column &)> predicate) const override;
[[nodiscard]] bool is_tautology() const override;
[[nodiscard]] bool is_contradiction() const override;
[[nodiscard]] Filters disjuncts() const override;
[[nodiscard]] Filters conjuncts() const override;
private:
const Column &_column;
const RelationalOperator _relOp;
const std::string _value;
std::ostream &print(std::ostream &os) const override;
};
#endif // ColumnFilter_h

35
src/ColumnsColumn.cc Normal file
View File

@@ -0,0 +1,35 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ColumnsColumn.h"
#include "Row.h"
#include "TableColumns.h"
class Column;
std::string ColumnsColumn::getValue(Row row) const {
if (auto p = columnData<Column>(row)) {
return _table_columns.getValue(p, _colcol);
}
return "";
}

52
src/ColumnsColumn.h Normal file
View File

@@ -0,0 +1,52 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ColumnsColumn_h
#define ColumnsColumn_h
#include "config.h" // IWYU pragma: keep
#include <string>
#include "StringColumn.h"
class Row;
class TableColumns;
class ColumnsColumn : public StringColumn {
public:
enum class Type { table, name, description, type };
ColumnsColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset, int extra_extra_offset,
int offset, Type colcol, const TableColumns &tablecols)
: StringColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _colcol(colcol)
, _table_columns(tablecols) {}
[[nodiscard]] std::string getValue(Row row) const override;
private:
const Type _colcol;
const TableColumns &_table_columns;
};
#endif // ColumnsColumn_h

76
src/CommentColumn.cc Normal file
View File

@@ -0,0 +1,76 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CommentColumn.h"
#include <algorithm>
#include <chrono>
#include <cstdint>
#include <iterator>
#include "MonitoringCore.h"
#include "Renderer.h"
#include "Row.h"
#include "nagios.h"
void CommentColumn::output(Row row, RowRenderer &r,
const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
ListRenderer l(r);
for (const auto &comment : comments_for_row(row)) {
if (_with_info) {
SublistRenderer s(l);
s.output(comment._id);
s.output(comment._author);
s.output(comment._comment);
if (_with_extra_info) {
s.output(comment._entry_type);
s.output(comment._entry_time);
}
} else {
l.output(comment._id);
}
}
}
std::vector<std::string> CommentColumn::getValue(
Row row, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
std::vector<std::string> ids;
auto comments = comments_for_row(row);
std::transform(
comments.begin(), comments.end(), std::back_inserter(ids),
[](const auto &comment) { return std::to_string(comment._id); });
return ids;
}
std::vector<CommentData> CommentColumn::comments_for_row(Row row) const {
if (auto data = columnData<void>(row)) {
return _is_service
? _mc->comments_for_service(
reinterpret_cast<const MonitoringCore::Service *>(
data))
: _mc->comments_for_host(
reinterpret_cast<const MonitoringCore::Host *>(data));
}
return {};
}

68
src/CommentColumn.h Normal file
View File

@@ -0,0 +1,68 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CommentColumn_h
#define CommentColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
struct CommentData;
class MonitoringCore;
class RowRenderer;
class Row;
class CommentColumn : public ListColumn {
public:
CommentColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset, int extra_extra_offset,
int offset, MonitoringCore *mc, bool is_service,
bool with_info, bool with_extra_info)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _mc(mc)
, _is_service(is_service)
, _with_info(with_info)
, _with_extra_info(with_extra_info) {}
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
private:
MonitoringCore *_mc;
bool _is_service;
bool _with_info;
bool _with_extra_info;
[[nodiscard]] std::vector<CommentData> comments_for_row(Row row) const;
};
#endif // CommentColumn_h

View File

@@ -0,0 +1,54 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ContactGroupsColumn.h"
#include "Row.h"
#ifdef CMC
#include "ContactList.h"
#include "Object.h"
#include "cmc.h"
#else
#include "nagios.h"
#endif
std::vector<std::string> ContactGroupsColumn::getValue(
Row row, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
std::vector<std::string> names;
#ifdef CMC
if (auto object = columnData<Object>(row)) {
for (const auto &name : object->_contact_list->groupNames()) {
names.push_back(name);
}
}
#else
if (auto p = columnData<contactgroupsmember *>(row)) {
for (auto cgm = *p; cgm != nullptr; cgm = cgm->next) {
names.emplace_back(cgm->group_ptr->group_name);
}
}
#endif
return names;
}

49
src/ContactGroupsColumn.h Normal file
View File

@@ -0,0 +1,49 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ContactGroupsColumn_h
#define ContactGroupsColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
class Row;
class ContactGroupsColumn : public ListColumn {
public:
ContactGroupsColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
};
#endif // ContactGroupsColumn_h

View File

@@ -0,0 +1,51 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ContactGroupsMemberColumn.h"
#include "Row.h"
#ifdef CMC
#include "ContactGroup.h"
#else
#include "nagios.h"
#endif
std::vector<std::string> ContactGroupsMemberColumn::getValue(
Row row, const contact* /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
#ifdef CMC
if (auto cg = columnData<ContactGroup>(row)) {
return cg->contactNames();
}
return {};
#else
std::vector<std::string> names;
if (auto cg = columnData<contactgroup>(row)) {
for (auto cm = cg->members; cm != nullptr; cm = cm->next) {
names.emplace_back(cm->contact_ptr->name);
}
}
return names;
#endif
}

View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ContactGroupsMemberColumn_h
#define ContactGroupsMemberColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
class Row;
class ContactGroupsMemberColumn : public ListColumn {
public:
ContactGroupsMemberColumn(const std::string& name,
const std::string& description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
std::vector<std::string> getValue(
Row row, const contact* auth_user,
std::chrono::seconds timezone_offset) const override;
};
#endif // ContactGroupsMemberColumn_h

37
src/CountAggregator.cc Normal file
View File

@@ -0,0 +1,37 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CountAggregator.h"
#include "Filter.h"
#include "Renderer.h"
#include "Row.h"
void CountAggregator::consume(Row row, const contact* auth_user,
std::chrono::seconds timezone_offset) {
if (_filter->accepts(row, auth_user, timezone_offset)) {
_count++;
}
}
void CountAggregator::output(RowRenderer& r) const { r.output(_count); }

50
src/CountAggregator.h Normal file
View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CountAggregator_h
#define CountAggregator_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <cstdint>
#include "Aggregator.h"
#include "contact_fwd.h"
class Filter;
class Row;
class RowRenderer;
class CountAggregator : public Aggregator {
public:
explicit CountAggregator(const Filter *filter)
: _filter(filter), _count(0) {}
void consume(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) override;
void output(RowRenderer &r) const override;
private:
const Filter *const _filter;
std::uint32_t _count;
};
#endif // CountAggregator_h

View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CustomTimeperiodColumn.h"
#include "Row.h"
#include "TimeperiodsCache.h"
extern TimeperiodsCache *g_timeperiods_cache;
// Get the name of a timeperiod from a custom variable and lookup the current
// state of that period
int32_t CustomTimeperiodColumn::getValue(
Row row, const contact * /* auth_user */) const {
for (customvariablesmember *cvm = getCVM(row); cvm != nullptr;
cvm = cvm->next) {
if (cvm->variable_name == _varname) {
return static_cast<int32_t>(
g_timeperiods_cache->inTimeperiod(cvm->variable_value));
}
}
return 1; // assume 24X7
}
customvariablesmember *CustomTimeperiodColumn::getCVM(Row row) const {
if (auto p = columnData<customvariablesmember *>(row)) {
return *p;
}
return nullptr;
}

View File

@@ -0,0 +1,53 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CustomTimeperiodColumn_h
#define CustomTimeperiodColumn_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <string>
#include <utility>
#include "IntColumn.h"
#include "nagios.h"
class Row;
class CustomTimeperiodColumn : public IntColumn {
public:
CustomTimeperiodColumn(const std::string &name,
const std::string &description, int indirect_offset,
int extra_offset, int extra_extra_offset, int offset,
std::string varname)
: IntColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _varname(std::move(varname)) {}
int32_t getValue(Row row, const contact *auth_user) const override;
private:
std::string _varname;
[[nodiscard]] customvariablesmember *getCVM(Row row) const;
};
#endif // CustomTimeperiodColumn_h

View File

@@ -0,0 +1,77 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CustomVarsDictColumn.h"
#include <stdexcept>
#include <utility>
#include "CustomVarsDictFilter.h"
#include "Filter.h"
#include "Renderer.h"
#include "Row.h"
class Aggregator;
#ifdef CMC
#include "Object.h"
#include "cmc.h"
#else
#include "nagios.h"
#endif
void CustomVarsDictColumn::output(
Row row, RowRenderer &r, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
DictRenderer d(r);
for (const auto &it : getValue(row)) {
d.output(it.first, it.second);
}
}
std::unique_ptr<Filter> CustomVarsDictColumn::createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const {
return std::make_unique<CustomVarsDictFilter>(kind, *this, relOp, value);
}
std::unique_ptr<Aggregator> CustomVarsDictColumn::createAggregator(
AggregationFactory /*factory*/) const {
throw std::runtime_error("aggregating on dictionary column '" + name() +
"' not supported");
}
std::unordered_map<std::string, std::string> CustomVarsDictColumn::getValue(
Row row) const {
std::unordered_map<std::string, std::string> dict;
#ifdef CMC
if (auto *object = columnData<Object>(row)) {
return object->customAttributes();
}
#else
if (auto p = columnData<customvariablesmember *>(row)) {
for (auto cvm = *p; cvm != nullptr; cvm = cvm->next) {
dict.emplace(cvm->variable_name, cvm->variable_value);
}
}
#endif
return dict;
}

View File

@@ -0,0 +1,66 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CustomVarsDictColumn_h
#define CustomVarsDictColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include "Column.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class Aggregator;
class Row;
class RowRenderer;
class CustomVarsDictColumn : public Column {
public:
CustomVarsDictColumn(std::string name, std::string description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: Column(std::move(name), std::move(description), indirect_offset,
extra_offset, extra_extra_offset, offset) {}
[[nodiscard]] ColumnType type() const override { return ColumnType::dict; };
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
[[nodiscard]] std::unique_ptr<Aggregator> createAggregator(
AggregationFactory factory) const override;
[[nodiscard]] std::unordered_map<std::string, std::string> getValue(
Row row) const;
};
#endif // CustomVarsDictColumn_h

View File

@@ -0,0 +1,87 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CustomVarsDictFilter.h"
#include <tuple>
#include <unordered_map>
#include <utility>
#include "CustomVarsDictColumn.h"
#include "Filter.h"
#include "RegExp.h"
#include "Row.h"
#include "StringUtils.h"
CustomVarsDictFilter::CustomVarsDictFilter(Kind kind,
const CustomVarsDictColumn &column,
RelationalOperator relOp,
const std::string &value)
: ColumnFilter(kind, column, relOp, value), _column(column) {
// Filter for custom_variables:
// Filter: custom_variables = PATH /hirni.mk
// The variable name is part of the value and separated with spaces
std::tie(_ref_varname, _ref_string) = mk::nextField(value);
_ref_string = mk::lstrip(_ref_string);
_regExp = makeRegExpFor(oper(), _ref_string);
}
bool CustomVarsDictFilter::accepts(
Row row, const contact * /* auth_user */,
std::chrono::seconds /* timezone_offset */) const {
auto cvm = _column.getValue(row);
auto it = cvm.find(_ref_varname);
auto act_string = it == cvm.end() ? "" : it->second;
switch (oper()) {
case RelationalOperator::equal:
case RelationalOperator::equal_icase:
return _regExp->match(act_string);
case RelationalOperator::not_equal:
case RelationalOperator::not_equal_icase:
return !_regExp->match(act_string);
case RelationalOperator::matches:
case RelationalOperator::matches_icase:
return _regExp->search(act_string);
case RelationalOperator::doesnt_match:
case RelationalOperator::doesnt_match_icase:
return !_regExp->search(act_string);
// FIXME: The cases below are nonsense for UTF-8...
case RelationalOperator::less:
return act_string < _ref_string;
case RelationalOperator::greater_or_equal:
return act_string >= _ref_string;
case RelationalOperator::greater:
return act_string > _ref_string;
case RelationalOperator::less_or_equal:
return act_string <= _ref_string;
}
return false; // unreachable
}
std::unique_ptr<Filter> CustomVarsDictFilter::copy() const {
return std::make_unique<CustomVarsDictFilter>(*this);
}
std::unique_ptr<Filter> CustomVarsDictFilter::negate() const {
return std::make_unique<CustomVarsDictFilter>(
kind(), _column, negateRelationalOperator(oper()), value());
}

View File

@@ -0,0 +1,56 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CustomVarsDictFilter_h
#define CustomVarsDictFilter_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include "ColumnFilter.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class CustomVarsDictColumn;
class RegExp;
class Row;
class CustomVarsDictFilter : public ColumnFilter {
public:
CustomVarsDictFilter(Kind kind, const CustomVarsDictColumn &column,
RelationalOperator relOp, const std::string &value);
bool accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> copy() const override;
[[nodiscard]] std::unique_ptr<Filter> negate() const override;
private:
const CustomVarsDictColumn &_column;
std::shared_ptr<RegExp> _regExp;
std::string _ref_string;
std::string _ref_varname;
};
#endif // CustomVarsDictFilter_h

View File

@@ -0,0 +1,43 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CustomVarsExplicitColumn.h"
#include "Row.h"
std::string CustomVarsExplicitColumn::getValue(Row row) const {
for (customvariablesmember *cvm = getCVM(row); cvm != nullptr;
cvm = cvm->next) {
if (cvm->variable_name == _varname) {
return cvm->variable_value;
}
}
return "";
}
customvariablesmember *CustomVarsExplicitColumn::getCVM(Row row) const {
if (auto p = columnData<customvariablesmember *>(row)) {
return *p;
}
return nullptr;
}

View File

@@ -0,0 +1,52 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CustomVarsExplicitColumn_h
#define CustomVarsExplicitColumn_h
#include "config.h" // IWYU pragma: keep
#include <string>
#include "StringColumn.h"
#include "nagios.h"
class Row;
class CustomVarsExplicitColumn : public StringColumn {
public:
CustomVarsExplicitColumn(const std::string &name,
const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset,
const char *varname)
: StringColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _varname(varname) {}
[[nodiscard]] std::string getValue(Row row) const override;
private:
std::string _varname;
[[nodiscard]] customvariablesmember *getCVM(Row row) const;
};
#endif // CustomVarsExplicitColumn_h

View File

@@ -0,0 +1,56 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CustomVarsNamesColumn.h"
#include "Row.h"
#ifdef CMC
#include <algorithm>
#include <iterator>
#include <unordered_map>
#include "Object.h"
#include "cmc.h"
#else
#include "nagios.h"
#endif
std::vector<std::string> CustomVarsNamesColumn::getValue(
Row row, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
std::vector<std::string> names;
#ifdef CMC
if (auto *object = columnData<Object>(row)) {
auto attrs = object->customAttributes();
std::transform(attrs.begin(), attrs.end(), std::back_inserter(names),
[](const auto &entry) { return entry.first; });
}
#else
if (auto p = columnData<customvariablesmember *>(row)) {
for (auto cvm = *p; cvm != nullptr; cvm = cvm->next) {
names.emplace_back(cvm->variable_name);
}
}
#endif
return names;
}

View File

@@ -0,0 +1,49 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CustomVarsNamesColumn_h
#define CustomVarsNamesColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
class Row;
class CustomVarsNamesColumn : public ListColumn {
public:
CustomVarsNamesColumn(const std::string &name,
const std::string &description, int indirect_offset,
int extra_offset, int extra_extra_offset, int offset)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
};
#endif // CustomVarsNamesColumn_h

View File

@@ -0,0 +1,56 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "CustomVarsValuesColumn.h"
#include "Row.h"
#ifdef CMC
#include <algorithm>
#include <iterator>
#include <unordered_map>
#include "Object.h"
#include "cmc.h"
#else
#include "nagios.h"
#endif
std::vector<std::string> CustomVarsValuesColumn::getValue(
Row row, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
std::vector<std::string> values;
#ifdef CMC
if (auto *object = columnData<Object>(row)) {
auto attrs = object->customAttributes();
std::transform(attrs.begin(), attrs.end(), std::back_inserter(values),
[](const auto &entry) { return entry.second; });
}
#else
if (auto p = columnData<customvariablesmember *>(row)) {
for (auto cvm = *p; cvm != nullptr; cvm = cvm->next) {
values.emplace_back(cvm->variable_value);
}
}
#endif
return values;
}

View File

@@ -0,0 +1,49 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef CustomVarsValuesColumn_h
#define CustomVarsValuesColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
class Row;
class CustomVarsValuesColumn : public ListColumn {
public:
CustomVarsValuesColumn(const std::string &name,
const std::string &description, int indirect_offset,
int extra_offset, int extra_extra_offset, int offset)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
};
#endif // CustomVarsValuesColumn_h

56
src/DoubleAggregator.h Normal file
View File

@@ -0,0 +1,56 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DoubleAggregator_h
#define DoubleAggregator_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include "Aggregator.h"
#include "DoubleColumn.h"
#include "contact_fwd.h"
class Row;
class RowRenderer;
class DoubleAggregator : public Aggregator {
public:
DoubleAggregator(const AggregationFactory &factory,
const DoubleColumn *column)
: _aggregation(factory()), _column(column) {}
void consume(Row row, const contact * /*contact*/,
std::chrono::seconds /*timezone_offset*/) override {
_aggregation->update(_column->getValue(row));
}
void output(RowRenderer &r) const override {
r.output(_aggregation->value());
}
private:
std::unique_ptr<Aggregation> _aggregation;
const DoubleColumn *const _column;
};
#endif // DoubleAggregator_h

48
src/DoubleColumn.cc Normal file
View File

@@ -0,0 +1,48 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DoubleColumn.h"
#include "Aggregator.h"
#include "DoubleAggregator.h"
#include "DoubleFilter.h"
#include "Filter.h"
#include "Renderer.h"
#include "Row.h"
void DoubleColumn::output(Row row, RowRenderer &r,
const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
r.output(getValue(row));
}
std::unique_ptr<Filter> DoubleColumn::createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const {
return std::make_unique<DoubleFilter>(kind, *this, relOp, value);
}
std::unique_ptr<Aggregator> DoubleColumn::createAggregator(
AggregationFactory factory) const {
return std::make_unique<DoubleAggregator>(factory, this);
}

60
src/DoubleColumn.h Normal file
View File

@@ -0,0 +1,60 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DoubleColumn_h
#define DoubleColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include "Column.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class Aggregator;
class Row;
class RowRenderer;
class DoubleColumn : public Column {
public:
DoubleColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset, int extra_extra_offset,
int offset)
: Column(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
[[nodiscard]] virtual double getValue(Row row) const = 0;
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] ColumnType type() const override {
return ColumnType::double_;
}
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
[[nodiscard]] std::unique_ptr<Aggregator> createAggregator(
AggregationFactory factory) const override;
};
#endif // DoubleColumn_h

76
src/DoubleFilter.cc Normal file
View File

@@ -0,0 +1,76 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DoubleFilter.h"
#include <cstdlib>
#include <ostream>
#include "DoubleColumn.h"
#include "Filter.h"
#include "Logger.h"
#include "Row.h"
DoubleFilter::DoubleFilter(Kind kind, const DoubleColumn &column,
RelationalOperator relOp, const std::string &value)
: ColumnFilter(kind, column, relOp, value)
, _column(column)
, _ref_value(atof(value.c_str())) {}
bool DoubleFilter::accepts(Row row, const contact * /* auth_user */,
std::chrono::seconds /* timezone_offset */) const {
double act_value = _column.getValue(row);
switch (oper()) {
case RelationalOperator::equal:
return act_value == _ref_value;
case RelationalOperator::not_equal:
return act_value != _ref_value;
case RelationalOperator::less:
return act_value < _ref_value;
case RelationalOperator::greater_or_equal:
return act_value >= _ref_value;
case RelationalOperator::greater:
return act_value > _ref_value;
case RelationalOperator::less_or_equal:
return act_value <= _ref_value;
case RelationalOperator::matches:
case RelationalOperator::doesnt_match:
case RelationalOperator::equal_icase:
case RelationalOperator::not_equal_icase:
case RelationalOperator::matches_icase:
case RelationalOperator::doesnt_match_icase:
Informational(_column.logger())
<< "Sorry. Operator " << oper()
<< " for float columns not implemented.";
return false;
}
return false; // unreachable
}
std::unique_ptr<Filter> DoubleFilter::copy() const {
return std::make_unique<DoubleFilter>(*this);
}
std::unique_ptr<Filter> DoubleFilter::negate() const {
return std::make_unique<DoubleFilter>(
kind(), _column, negateRelationalOperator(oper()), value());
}

53
src/DoubleFilter.h Normal file
View File

@@ -0,0 +1,53 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DoubleFilter_h
#define DoubleFilter_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include "ColumnFilter.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class DoubleColumn;
class Row;
class DoubleFilter : public ColumnFilter {
public:
DoubleFilter(Kind kind, const DoubleColumn &column,
RelationalOperator relOp, const std::string &value);
bool accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> copy() const override;
[[nodiscard]] std::unique_ptr<Filter> negate() const override;
private:
const DoubleColumn &_column;
const double _ref_value;
};
#endif // DoubleFilter_h

45
src/DoublePointerColumn.h Normal file
View File

@@ -0,0 +1,45 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DoublePointerColumn_h
#define DoublePointerColumn_h
#include "config.h" // IWYU pragma: keep
#include "DoubleColumn.h"
class DoublePointerColumn : public DoubleColumn {
public:
DoublePointerColumn(const std::string &name, const std::string &description,
const double *number)
: DoubleColumn(name, description, -1, -1, -1, 0), _number(number) {}
[[nodiscard]] double getValue(Row /*unused*/) const override {
return *_number;
}
private:
const double *const _number;
};
#endif // DoublePointerColumn_h

70
src/DowntimeColumn.cc Normal file
View File

@@ -0,0 +1,70 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DowntimeColumn.h"
#include "MonitoringCore.h"
#include "Renderer.h"
#include "Row.h"
#ifndef CMC
#include "nagios.h"
#endif
void DowntimeColumn::output(Row row, RowRenderer &r,
const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
ListRenderer l(r);
for (const auto &downtime : downtimes_for_row(row)) {
if (_with_info) {
SublistRenderer s(l);
s.output(downtime._id);
s.output(downtime._author);
s.output(downtime._comment);
} else {
l.output(downtime._id);
}
}
}
std::vector<std::string> DowntimeColumn::getValue(
Row row, const contact * /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
std::vector<std::string> ids;
for (const auto &downtime : downtimes_for_row(row)) {
ids.push_back(std::to_string(downtime._id));
}
return ids;
}
std::vector<DowntimeData> DowntimeColumn::downtimes_for_row(Row row) const {
if (auto data = columnData<void>(row)) {
return _is_service
? _mc->downtimes_for_service(
reinterpret_cast<const MonitoringCore::Service *>(
data))
: _mc->downtimes_for_host(
reinterpret_cast<const MonitoringCore::Host *>(data));
}
return {};
}

66
src/DowntimeColumn.h Normal file
View File

@@ -0,0 +1,66 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DowntimeColumn_h
#define DowntimeColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
struct DowntimeData;
class MonitoringCore;
class Row;
class RowRenderer;
class DowntimeColumn : public ListColumn {
public:
DowntimeColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset, MonitoringCore *mc,
bool is_service, bool with_info)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _mc(mc)
, _is_service(is_service)
, _with_info(with_info) {}
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
private:
MonitoringCore *_mc;
bool _is_service;
bool _with_info;
[[nodiscard]] std::vector<DowntimeData> downtimes_for_row(Row row) const;
};
#endif // DowntimeColumn_h

57
src/DowntimeOrComment.cc Normal file
View File

@@ -0,0 +1,57 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DowntimeOrComment.h"
DowntimeOrComment::DowntimeOrComment(nebstruct_downtime_struct *dt,
unsigned long id)
: _type(dt->downtime_type)
, _is_service(dt->service_description != nullptr)
, _host(find_host(dt->host_name))
, _service(_is_service
? find_service(dt->host_name, dt->service_description)
: nullptr)
, _entry_time(dt->entry_time)
, _author_name(dt->author_name)
, _comment(dt->comment_data)
, _id(id) {}
DowntimeOrComment::~DowntimeOrComment() = default;
Downtime::Downtime(nebstruct_downtime_struct *dt)
: DowntimeOrComment(dt, dt->downtime_id)
, _start_time(dt->start_time)
, _end_time(dt->end_time)
, _fixed(dt->fixed)
, _duration(static_cast<int>(dt->duration))
, _triggered_by(static_cast<int>(dt->triggered_by)) {}
Comment::Comment(nebstruct_comment_struct *co)
: DowntimeOrComment(reinterpret_cast<nebstruct_downtime_struct *>(co),
co->comment_id)
, _expire_time(co->expire_time)
, _persistent(co->persistent)
, _source(co->source)
, _entry_type(co->entry_type)
, _expires(co->expires) {}

119
src/DowntimeOrComment.h Normal file
View File

@@ -0,0 +1,119 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DowntimeOrComment_h
#define DowntimeOrComment_h
#include "config.h" // IWYU pragma: keep
#include <ctime>
#include <string>
#include "nagios.h"
/* The structs for downtime and comment are so similar, that
we handle them with the same logic */
/*
typedef struct nebstruct_downtime_struct{
int type;
int flags;
int attr;
struct timeval timestamp;
int downtime_type;
char *host_name;
char *service_description;
time_t entry_time;
char *author_name;
char *comment_data;
time_t start_time;
time_t end_time;
int fixed;
unsigned long duration;
unsigned long triggered_by;
unsigned long downtime_id;
void *object_ptr; // not implemented yet
}nebstruct_downtime_data;
typedef struct nebstruct_comment_struct{
int type;
int flags;
int attr;
struct timeval timestamp;
int comment_type;
char *host_name;
char *service_description;
time_t entry_time;
char *author_name;
char *comment_data;
int persistent;
int source;
int entry_type;
int expires;
time_t expire_time;
unsigned long comment_id;
void *object_ptr; // not implemented yet
}nebstruct_comment_data;
*/
class DowntimeOrComment {
public:
int _type;
bool _is_service;
host *_host;
service *_service;
time_t _entry_time;
std::string _author_name;
std::string _comment;
unsigned long _id;
DowntimeOrComment(nebstruct_downtime_struct *dt, unsigned long id);
virtual ~DowntimeOrComment();
};
class Downtime : public DowntimeOrComment {
public:
time_t _start_time;
time_t _end_time;
int _fixed;
// TODO(sp): Wrong types, caused by TableDowntimes accessing it via
// OffsetIntColumn, should be unsigned long
int _duration;
int _triggered_by;
explicit Downtime(nebstruct_downtime_struct *dt);
};
class Comment : public DowntimeOrComment {
public:
time_t _expire_time;
int _persistent;
int _source;
int _entry_type;
int _expires;
explicit Comment(nebstruct_comment_struct *co);
};
#endif // DowntimeOrComment_h

View File

@@ -0,0 +1,67 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DowntimesOrComments.h"
#include <iosfwd>
#include "DowntimeOrComment.h"
#include "Logger.h"
DowntimesOrComments::DowntimesOrComments()
: _logger(Logger::getLogger("cmk.livestatus")) {}
void DowntimesOrComments::registerDowntime(nebstruct_downtime_data *data) {
unsigned long id = data->downtime_id;
switch (data->type) {
case NEBTYPE_DOWNTIME_ADD:
case NEBTYPE_DOWNTIME_LOAD:
_entries[id] = std::make_unique<Downtime>(data);
break;
case NEBTYPE_DOWNTIME_DELETE:
if (_entries.erase(id) == 0) {
Informational(_logger)
<< "Cannot delete non-existing downtime " << id;
}
break;
default:
break;
}
}
void DowntimesOrComments::registerComment(nebstruct_comment_data *data) {
unsigned long id = data->comment_id;
switch (data->type) {
case NEBTYPE_COMMENT_ADD:
case NEBTYPE_COMMENT_LOAD:
_entries[id] = std::make_unique<Comment>(data);
break;
case NEBTYPE_COMMENT_DELETE:
if (_entries.erase(id) == 0) {
Informational(_logger)
<< "Cannot delete non-existing comment " << id;
}
break;
default:
break;
}
}

48
src/DowntimesOrComments.h Normal file
View File

@@ -0,0 +1,48 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DowntimesOrComments_h
#define DowntimesOrComments_h
#include "config.h" // IWYU pragma: keep
#include <map>
#include <memory>
#include "nagios.h"
class DowntimeOrComment;
class Logger;
class DowntimesOrComments {
public:
DowntimesOrComments();
void registerDowntime(nebstruct_downtime_data *data);
void registerComment(nebstruct_comment_data *data);
[[nodiscard]] auto begin() const { return _entries.cbegin(); }
[[nodiscard]] auto end() const { return _entries.cend(); }
private:
std::map<unsigned long, std::unique_ptr<DowntimeOrComment>> _entries;
Logger *const _logger;
};
#endif // DowntimesOrComments_h

40
src/DynamicColumn.cc Normal file
View File

@@ -0,0 +1,40 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DynamicColumn.h"
#include <utility>
DynamicColumn::DynamicColumn(std::string name, std::string description,
Logger *logger, int indirect_offset,
int extra_offset, int extra_extra_offset)
: _name(std::move(name))
, _description(std::move(description))
, _logger(logger)
, _indirect_offset(indirect_offset)
, _extra_offset(extra_offset)
, _extra_extra_offset(extra_extra_offset) {}
DynamicColumn::~DynamicColumn() = default;
std::string DynamicColumn::name() const { return _name; }

53
src/DynamicColumn.h Normal file
View File

@@ -0,0 +1,53 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DynamicColumn_h
#define DynamicColumn_h
#include "config.h" // IWYU pragma: keep
#include <memory>
#include <string>
class Column;
class Logger;
class DynamicColumn {
public:
DynamicColumn(std::string name, std::string description, Logger *logger,
int indirect_offset, int extra_offset,
int extra_extra_offset);
virtual ~DynamicColumn();
[[nodiscard]] std::string name() const;
virtual std::unique_ptr<Column> createColumn(
const std::string &name, const std::string &arguments) = 0;
protected:
const std::string _name;
const std::string _description; // Note: Currently unused!
Logger *const _logger;
const int _indirect_offset;
const int _extra_offset;
const int _extra_extra_offset;
};
#endif // DynamicColumn_h

View File

@@ -0,0 +1,95 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DynamicEventConsoleReplicationColumn.h"
#include <iosfwd>
#include <memory>
#include <stdexcept>
#include <utility>
#include <vector>
#include "BlobColumn.h"
#include "Column.h"
#include "EventConsoleConnection.h"
#include "Logger.h"
#include "MonitoringCore.h"
#include "Row.h"
namespace {
class ECTableConnection : public EventConsoleConnection {
public:
ECTableConnection(MonitoringCore *mc, std::string command)
: EventConsoleConnection(mc->loggerLivestatus(),
mc->mkeventdSocketPath())
, _command(std::move(command)) {}
[[nodiscard]] std::string getResult() const { return _result; }
private:
void sendRequest(std::ostream &os) override { os << _command; }
void receiveReply(std::istream &is) override { std::getline(is, _result); }
const std::string _command;
std::string _result;
};
class ReplicationColumn : public BlobColumn {
public:
ReplicationColumn(const std::string &name, const std::string &description,
std::string blob, int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: BlobColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _blob(std::move(blob)) {}
[[nodiscard]] std::unique_ptr<std::vector<char>> getValue(
Row /* unused */) const override {
return std::make_unique<std::vector<char>>(_blob.begin(), _blob.end());
};
private:
const std::string _blob;
};
} // namespace
DynamicEventConsoleReplicationColumn::DynamicEventConsoleReplicationColumn(
const std::string &name, const std::string &description, MonitoringCore *mc,
int indirect_offset, int extra_offset, int extra_extra_offset)
: DynamicColumn(name, description, mc->loggerLivestatus(), indirect_offset,
extra_offset, extra_extra_offset)
, _mc(mc) {}
std::unique_ptr<Column> DynamicEventConsoleReplicationColumn::createColumn(
const std::string &name, const std::string &arguments) {
std::string result;
if (_mc->mkeventdEnabled()) {
try {
ECTableConnection ec(_mc, "REPLICATE " + arguments);
ec.run();
result = ec.getResult();
} catch (const std::runtime_error &err) {
Alert(_mc->loggerLivestatus()) << err.what();
}
}
return std::make_unique<ReplicationColumn>(name, "replication value",
result, -1, -1, -1, 0);
}

View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DynamicEventConsoleReplicationColumn_h
#define DynamicEventConsoleReplicationColumn_h
#include "config.h" // IWYU pragma: keep
#include <memory>
#include <string>
#include "DynamicColumn.h"
class Column;
class MonitoringCore;
class DynamicEventConsoleReplicationColumn : public DynamicColumn {
public:
DynamicEventConsoleReplicationColumn(const std::string &name,
const std::string &description,
MonitoringCore *mc,
int indirect_offset, int extra_offset,
int extra_extra_offset);
std::unique_ptr<Column> createColumn(const std::string &name,
const std::string &arguments) override;
private:
MonitoringCore *_mc;
};
#endif // DynamicEventConsoleReplicationColumn_h

View File

@@ -0,0 +1,69 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "DynamicLogwatchFileColumn.h"
#include <stdexcept>
#include "Column.h"
#include "HostFileColumn.h"
#include "MonitoringCore.h"
namespace {
// Replace \\ with \ and \s with space
std::string unescape_filename(std::string filename) {
std::string filename_native;
bool quote_active = false;
for (auto c : filename) {
if (quote_active) {
if (c == 's') {
filename_native += ' ';
} else {
filename_native += c;
}
quote_active = false;
} else if (c == '\\') {
quote_active = true;
} else {
filename_native += c;
}
}
return filename_native;
}
} // namespace
std::unique_ptr<Column> DynamicLogwatchFileColumn::createColumn(
const std::string &name, const std::string &arguments) {
// arguments contains a file name
if (arguments.empty()) {
throw std::runtime_error("invalid arguments for column '" + _name +
"': missing file name");
}
if (arguments.find('/') != std::string::npos) {
throw std::runtime_error("invalid arguments for column '" + _name +
"': file name '" + arguments +
"' contains slash");
}
return std::make_unique<HostFileColumn>(
name, "Contents of logwatch file", _indirect_offset, _extra_offset, -1,
0, _mc->mkLogwatchPath(), "/" + unescape_filename(arguments));
}

View File

@@ -0,0 +1,53 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef DynamicLogwatchFileColumn_h
#define DynamicLogwatchFileColumn_h
#include "config.h" // IWYU pragma: keep
#include <memory>
#include <string>
#include "DynamicColumn.h"
class Column;
class Logger;
class MonitoringCore;
class DynamicLogwatchFileColumn : public DynamicColumn {
public:
DynamicLogwatchFileColumn(const std::string &name,
const std::string &description, Logger *logger,
MonitoringCore *mc, int indirect_offset,
int extra_offset, int extra_extra_offset)
: DynamicColumn(name, description, logger, indirect_offset,
extra_offset, extra_extra_offset)
, _mc(mc) {}
~DynamicLogwatchFileColumn() override = default;
std::unique_ptr<Column> createColumn(const std::string &name,
const std::string &arguments) override;
private:
MonitoringCore *_mc;
};
#endif // DynamicLogwatchFileColumn_h

View File

@@ -0,0 +1,89 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "EventConsoleConnection.h"
#include <boost/asio/basic_socket_streambuf.hpp>
#include <boost/asio/socket_base.hpp>
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
#include <chrono>
#include <ostream>
#include <thread>
#include <utility>
#include "Logger.h"
EventConsoleConnection::EventConsoleConnection(Logger *logger, std::string path)
: _logger(logger), _path(std::move(path)) {}
EventConsoleConnection::~EventConsoleConnection() {
Debug(_logger) << prefix("closing connection");
}
void EventConsoleConnection::run() {
boost::asio::local::stream_protocol::endpoint ep(_path);
// Attention, tricky timing-dependent stuff ahead: When we connect very
// rapidly, a no_buffer_space (= ENOBUFS) error can happen. This is probably
// caused by some internal Boost Kung Fu, remapping EGAIN to ENOBUFS, and
// looks like a bug in Boost, but that's a bit unclear. So instead of
// relying on Boost to retry under these circumstances, we do it ourselves.
boost::asio::local::stream_protocol::iostream stream;
while (true) {
stream.connect(ep);
if (stream.error() !=
boost::system::error_code(boost::system::errc::no_buffer_space,
boost::system::system_category())) {
break;
}
Debug(_logger) << "retrying to connect";
stream.clear();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
check(stream, "connect");
Debug(_logger) << prefix("successfully connected");
stream << std::nounitbuf;
sendRequest(stream);
stream.flush();
stream.rdbuf()->shutdown(boost::asio::socket_base::shutdown_send);
check(stream, "send request");
receiveReply(stream);
check(stream, "receive reply");
}
std::string EventConsoleConnection::prefix(const std::string &message) const {
return "[mkeventd at " + _path + "] " + message;
}
void EventConsoleConnection::check(
boost::asio::local::stream_protocol::iostream &stream,
const std::string &what) const {
if (!stream && !stream.eof()) {
// NOTE: Boost's system_error has a mutable string member for lazy
// construction of what(), this screws up cert-err60-cpp. :-P
throw boost::system::system_error(stream.error(),
prefix("cannot " + what)); // NOLINT
}
}

View File

@@ -0,0 +1,52 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef EventConsoleConnection_h
#define EventConsoleConnection_h
#include "config.h" // IWYU pragma: keep
#include <boost/asio/local/stream_protocol.hpp>
#include <iosfwd>
#include <string>
class Logger;
class EventConsoleConnection {
public:
EventConsoleConnection(Logger *logger, std::string path);
~EventConsoleConnection();
void run();
private:
virtual void sendRequest(std::ostream &os) = 0;
virtual void receiveReply(std::istream &is) = 0;
[[nodiscard]] std::string prefix(const std::string &message) const;
void check(boost::asio::local::stream_protocol::iostream &stream,
const std::string &what) const;
Logger *const _logger;
const std::string _path;
};
#endif // EventConsoleConnection_h

34
src/FileSystem.h Normal file
View File

@@ -0,0 +1,34 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef FileSystem_h
#define FileSystem_h
// IWYU pragma: begin_exports
#include <experimental/filesystem>
// IWYU pragma: end_exports
namespace fs = std::experimental::filesystem;
#endif // FileSystem_h

50
src/Filter.cc Normal file
View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "Filter.h"
Filter::~Filter() = default;
std::optional<std::string> Filter::stringValueRestrictionFor(
const std::string& /* column_name */) const {
return {};
}
std::optional<int32_t> Filter::greatestLowerBoundFor(
const std::string& /* column_name */,
std::chrono::seconds /* timezone_offset */) const {
return {};
}
std::optional<int32_t> Filter::leastUpperBoundFor(
const std::string& /* column_name */,
std::chrono::seconds /* timezone_offset */) const {
return {};
}
std::optional<std::bitset<32>> Filter::valueSetLeastUpperBoundFor(
const std::string& /* column_name */,
std::chrono::seconds /* timezone_offset */) const {
return {};
}

102
src/Filter.h Normal file
View File

@@ -0,0 +1,102 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef Filter_h
#define Filter_h
#include "config.h" // IWYU pragma: keep
#include <bitset>
#include <chrono>
#include <cstdint>
#include <functional>
#include <iosfwd>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "contact_fwd.h"
class Column;
class Filter;
class Row;
using Filters = std::vector<std::unique_ptr<Filter>>;
/// A propositional formula over column value relations, kept in negation normal
/// form.
class Filter {
public:
enum Kind { row, stats, wait_condition };
explicit Filter(Kind kind) : _kind(kind) {}
virtual ~Filter();
[[nodiscard]] Kind kind() const { return _kind; }
virtual bool accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const = 0;
virtual std::unique_ptr<Filter> partialFilter(
std::function<bool(const Column &)> predicate) const = 0;
// TODO(sp) We might be able to unify all the methods below if we make the
// underlying lattice structure explicit, i.e. provide a set type and
// corresponding meet/join operations. Perhaps we can even get rid of the
// std::optional by making the lattice bounded, i.e. by providing bottom/top
// values.
[[nodiscard]] virtual std::optional<std::string> stringValueRestrictionFor(
const std::string &column_name) const;
[[nodiscard]] virtual std::optional<int32_t> greatestLowerBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const;
[[nodiscard]] virtual std::optional<int32_t> leastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const;
[[nodiscard]] virtual std::optional<std::bitset<32>>
valueSetLeastUpperBoundFor(const std::string &column_name,
std::chrono::seconds timezone_offset) const;
[[nodiscard]] virtual std::unique_ptr<Filter> copy() const = 0;
[[nodiscard]] virtual std::unique_ptr<Filter> negate() const = 0;
/// Checks for a *syntactic* tautology.
[[nodiscard]] virtual bool is_tautology() const = 0;
/// Checks for a *syntactic* contradiction.
[[nodiscard]] virtual bool is_contradiction() const = 0;
/// Combining the returned filters with *or* yields a filter equivalent to
/// the current one.
[[nodiscard]] virtual Filters disjuncts() const = 0;
/// Combining the returned filters with *and* yields a filter equivalent to
/// the current one.
[[nodiscard]] virtual Filters conjuncts() const = 0;
friend std::ostream &operator<<(std::ostream &os, const Filter &filter) {
return filter.print(os);
}
private:
const Kind _kind;
virtual std::ostream &print(std::ostream &os) const = 0;
};
#endif // Filter_h

46
src/FixedIntColumn.h Normal file
View File

@@ -0,0 +1,46 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef FixedIntColumn_h
#define FixedIntColumn_h
#include "config.h" // IWYU pragma: keep
#include "IntColumn.h"
class FixedIntColumn : public IntColumn {
public:
FixedIntColumn(const std::string& name, const std::string& description,
int value)
: IntColumn(name, description, -1, -1, -1, 0), _value(value) {}
int32_t getValue(Row /* row */,
const contact* /* auth_user */) const override {
return _value;
}
private:
const int32_t _value;
};
#endif // FixedIntColumn_h

60
src/HostContactsColumn.cc Normal file
View File

@@ -0,0 +1,60 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostContactsColumn.h"
#include "Row.h"
#ifdef CMC
#include "ContactList.h"
#include "Object.h"
#include "cmc.h"
#else
#include <unordered_set>
#include "nagios.h"
#endif
std::vector<std::string> HostContactsColumn::getValue(
Row row, const contact* /*auth_user*/,
std::chrono::seconds /*timezone_offset*/) const {
#ifdef CMC
if (auto object = columnData<Object>(row)) {
return object->_contact_list->contactNames();
}
return {};
#else
std::unordered_set<std::string> names;
if (auto hst = columnData<host>(row)) {
for (auto cm = hst->contacts; cm != nullptr; cm = cm->next) {
names.insert(cm->contact_ptr->name);
}
for (auto cgm = hst->contact_groups; cgm != nullptr; cgm = cgm->next) {
for (auto cm = cgm->group_ptr->members; cm != nullptr;
cm = cm->next) {
names.insert(cm->contact_ptr->name);
}
}
}
return std::vector<std::string>(names.begin(), names.end());
#endif
}

49
src/HostContactsColumn.h Normal file
View File

@@ -0,0 +1,49 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostContactsColumn_h
#define HostContactsColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
class Row;
class HostContactsColumn : public ListColumn {
public:
HostContactsColumn(const std::string& name, const std::string& description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
std::vector<std::string> getValue(
Row row, const contact* auth_user,
std::chrono::seconds timezone_offset) const override;
};
#endif // HostContactsColumn_h

117
src/HostFileColumn.cc Normal file
View File

@@ -0,0 +1,117 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostFileColumn.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <ostream>
#include <utility>
#include "Logger.h"
#include "Row.h"
#ifdef CMC
#include "Host.h"
#else
#include "nagios.h"
#endif
HostFileColumn::HostFileColumn(const std::string& name,
const std::string& description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset,
std::string base_dir, std::string suffix)
: BlobColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _base_dir(std::move(base_dir))
, _suffix(std::move(suffix)) {}
std::unique_ptr<std::vector<char>> HostFileColumn::getValue(Row row) const {
if (_base_dir.empty()) {
return nullptr; // Path is not configured
}
#ifdef CMC
auto hst = columnData<Host>(row);
if (hst == nullptr) {
return nullptr;
}
std::string host_name = hst->name();
#else
auto hst = columnData<host>(row);
if (hst == nullptr) {
return nullptr;
}
std::string host_name = hst->name;
#endif
std::string path = _base_dir + "/" + host_name + _suffix;
int fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
// It is OK when inventory/logwatch files do not exist.
if (errno != ENOENT) {
generic_error ge("cannot open " + path);
Warning(logger()) << ge;
}
return nullptr;
}
struct stat st;
if (fstat(fd, &st) == -1) {
generic_error ge("cannot stat " + path);
Warning(logger()) << ge;
return nullptr;
}
if (!S_ISREG(st.st_mode)) {
Warning(logger()) << path << " is not a regular file";
return nullptr;
}
size_t bytes_to_read = st.st_size;
auto result = std::make_unique<std::vector<char>>(bytes_to_read);
char* buffer = &(*result)[0];
while (bytes_to_read > 0) {
ssize_t bytes_read = read(fd, buffer, bytes_to_read);
if (bytes_read == -1) {
if (errno != EINTR) {
generic_error ge("could not read " + path);
Warning(logger()) << ge;
close(fd);
return nullptr;
}
} else if (bytes_read == 0) {
Warning(logger()) << "premature EOF reading " << path;
close(fd);
return nullptr;
} else {
bytes_to_read -= bytes_read;
buffer += bytes_read;
}
}
close(fd);
return result;
}

50
src/HostFileColumn.h Normal file
View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostFileColumn_h
#define HostFileColumn_h
#include "config.h" // IWYU pragma: keep
#include <memory>
#include <string>
#include <vector>
#include "BlobColumn.h"
class Row;
class HostFileColumn : public BlobColumn {
public:
HostFileColumn(const std::string& name, const std::string& description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset, std::string base_dir,
std::string suffix);
[[nodiscard]] std::unique_ptr<std::vector<char>> getValue(
Row row) const override;
private:
std::string _base_dir;
std::string _suffix;
};
#endif // HostFileColumn_h

60
src/HostGroupsColumn.cc Normal file
View File

@@ -0,0 +1,60 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostGroupsColumn.h"
#include "Row.h"
#ifdef CMC
#include "Object.h"
#include "ObjectGroup.h"
#include "cmc.h"
#else
#include "auth.h"
#include "nagios.h"
#endif
std::vector<std::string> HostGroupsColumn::getValue(
Row row, const contact *auth_user,
std::chrono::seconds /*timezone_offset*/) const {
std::vector<std::string> group_names;
#ifdef CMC
if (auto object = columnData<Object>(row)) {
for (const auto &og : object->_groups) {
if (og->isContactAuthorized(_mc, auth_user)) {
group_names.push_back(og->name());
}
}
}
#else
if (auto p = columnData<objectlist *>(row)) {
for (objectlist *list = *p; list != nullptr; list = list->next) {
auto hg = static_cast<hostgroup *>(list->object_ptr);
if (is_authorized_for_host_group(_mc, hg, auth_user)) {
group_names.emplace_back(hg->group_name);
}
}
}
#endif
return group_names;
}

54
src/HostGroupsColumn.h Normal file
View File

@@ -0,0 +1,54 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostGroupsColumn_h
#define HostGroupsColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
class MonitoringCore;
class Row;
class HostGroupsColumn : public ListColumn {
public:
HostGroupsColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset, MonitoringCore *mc)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _mc(mc) {}
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
private:
MonitoringCore *const _mc;
};
#endif // HostGroupsColumn_h

96
src/HostListColumn.cc Normal file
View File

@@ -0,0 +1,96 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostListColumn.h"
#include <algorithm>
#include <iterator>
#include "Renderer.h"
#include "Row.h"
#ifdef CMC
#include <unordered_set>
#include "Host.h"
#include "LogEntry.h"
#include "State.h"
#include "cmc.h"
#else
#include "auth.h"
#include "nagios.h"
#endif
void HostListColumn::output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds /*timezone_offset*/) const {
ListRenderer l(r);
for (const auto &member : getMembers(row, auth_user)) {
if (_show_state) {
SublistRenderer s(l);
s.output(member.host_name);
s.output(static_cast<int>(member.current_state));
s.output(static_cast<int>(member.has_been_checked));
} else {
l.output(member.host_name);
}
}
}
std::vector<std::string> HostListColumn::getValue(
Row row, const contact *auth_user,
std::chrono::seconds /*timezone_offset*/) const {
auto members = getMembers(row, auth_user);
std::vector<std::string> host_names;
std::transform(members.begin(), members.end(),
std::back_inserter(host_names),
[](const auto &member) { return member.host_name; });
return host_names;
};
std::vector<HostListColumn::Member> HostListColumn::getMembers(
Row row, const contact *auth_user) const {
std::vector<Member> members;
#ifdef CMC
if (auto p = columnData<std::unordered_set<Host *>>(row)) {
for (const auto &hst : *p) {
if (auth_user == nullptr || hst->hasContact(_mc, auth_user)) {
members.emplace_back(
hst->name(),
static_cast<HostState>(hst->state()->_current_state),
hst->state()->_has_been_checked);
}
}
}
#else
if (auto p = columnData<hostsmember *>(row)) {
for (const hostsmember *mem = *p; mem != nullptr; mem = mem->next) {
host *hst = mem->host_ptr;
if (auth_user == nullptr ||
is_authorized_for(_mc, auth_user, hst, nullptr)) {
members.emplace_back(hst->name,
static_cast<HostState>(hst->current_state),
hst->has_been_checked != 0);
}
}
}
#endif
return members;
}

76
src/HostListColumn.h Normal file
View File

@@ -0,0 +1,76 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostListColumn_h
#define HostListColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <string>
#include <utility>
#include <vector>
#include "ListColumn.h"
#include "contact_fwd.h"
enum class HostState;
class MonitoringCore;
class Row;
class RowRenderer;
class HostListColumn : public ListColumn {
public:
HostListColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset, MonitoringCore *mc,
bool show_state)
: ListColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _mc(mc)
, _show_state(show_state) {}
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds /*timezone_offset*/) const override;
std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
private:
MonitoringCore *_mc;
const bool _show_state;
struct Member {
Member(std::string hn, HostState cs, bool hbc)
: host_name(std::move(hn))
, current_state(cs)
, has_been_checked(hbc) {}
std::string host_name;
HostState current_state;
bool has_been_checked;
};
std::vector<Member> getMembers(Row row, const contact *auth_user) const;
};
#endif // HostListColumn_h

129
src/HostListStateColumn.cc Normal file
View File

@@ -0,0 +1,129 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostListStateColumn.h"
#include "LogEntry.h"
#include "Row.h"
#ifdef CMC
#include <unordered_set>
#include "Host.h"
#include "State.h"
#else
#include "auth.h"
#endif
int32_t HostListStateColumn::getValue(Row row, const contact *auth_user) const {
int32_t result = 0;
#ifdef CMC
if (auto p = columnData<std::unordered_set<Host *>>(row)) {
for (auto hst : *p) {
if (auth_user == nullptr || hst->hasContact(_mc, auth_user)) {
update(hst, auth_user, result);
}
}
}
#else
if (auto p = columnData<hostsmember *>(row)) {
for (hostsmember *mem = *p; mem != nullptr; mem = mem->next) {
host *hst = mem->host_ptr;
if (auth_user == nullptr ||
is_authorized_for(_mc, auth_user, hst, nullptr)) {
update(hst, auth_user, result);
}
}
}
#endif
return result;
}
void HostListStateColumn::update(host *hst, const contact *auth_user,
int32_t &result) const {
#ifdef CMC
ServiceListStateColumn::service_list services = &hst->_services;
bool has_been_checked = hst->state()->_has_been_checked;
auto current_state = static_cast<int>(hst->state()->_current_state);
#else
ServiceListStateColumn::service_list services = hst->services;
bool has_been_checked = hst->has_been_checked != 0;
int current_state = hst->current_state;
#endif
switch (_logictype) {
case Type::num_svc_pending:
case Type::num_svc_ok:
case Type::num_svc_warn:
case Type::num_svc_crit:
case Type::num_svc_unknown:
case Type::num_svc:
result += ServiceListStateColumn::getValueFromServices(
_mc, static_cast<ServiceListStateColumn::Type>(_logictype),
services, auth_user);
break;
case Type::worst_svc_state: {
int state = ServiceListStateColumn::getValueFromServices(
_mc, static_cast<ServiceListStateColumn::Type>(_logictype),
services, auth_user);
if (worse(static_cast<ServiceState>(state),
static_cast<ServiceState>(result))) {
result = state;
}
break;
}
case Type::num_hst_up:
case Type::num_hst_down:
case Type::num_hst_unreach:
if (has_been_checked &&
current_state == static_cast<int>(_logictype) -
static_cast<int>(Type::num_hst_up)) {
result++;
}
break;
case Type::num_hst_pending:
if (!has_been_checked) {
result++;
}
break;
case Type::num_hst:
result++;
break;
case Type::worst_hst_state:
if (worse(static_cast<HostState>(current_state),
static_cast<HostState>(result))) {
result = current_state;
}
break;
case Type::num_svc_hard_ok:
case Type::num_svc_hard_warn:
case Type::num_svc_hard_crit:
case Type::num_svc_hard_unknown:
case Type::worst_svc_hard_state:
// TODO(sp) Why are these not handled?
break;
}
}

92
src/HostListStateColumn.h Normal file
View File

@@ -0,0 +1,92 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostListStateColumn_h
#define HostListStateColumn_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <string>
#include "IntColumn.h"
#include "ServiceListStateColumn.h"
class MonitoringCore;
class Row;
#ifdef CMC
#include "cmc.h"
#else
#include "nagios.h"
#endif
class HostListStateColumn : public IntColumn {
public:
// TODO(sp) Remove the magic arithmetic
enum class Type {
num_svc = static_cast<int>(ServiceListStateColumn::Type::num),
num_svc_pending =
static_cast<int>(ServiceListStateColumn::Type::num_pending),
num_svc_ok = static_cast<int>(ServiceListStateColumn::Type::num_ok),
num_svc_warn = static_cast<int>(ServiceListStateColumn::Type::num_warn),
num_svc_crit = static_cast<int>(ServiceListStateColumn::Type::num_crit),
num_svc_unknown =
static_cast<int>(ServiceListStateColumn::Type::num_unknown),
worst_svc_state =
static_cast<int>(ServiceListStateColumn::Type::worst_state),
num_svc_hard_ok =
static_cast<int>(ServiceListStateColumn::Type::num_hard_ok),
num_svc_hard_warn =
static_cast<int>(ServiceListStateColumn::Type::num_hard_warn),
num_svc_hard_crit =
static_cast<int>(ServiceListStateColumn::Type::num_hard_crit),
num_svc_hard_unknown =
static_cast<int>(ServiceListStateColumn::Type::num_hard_unknown),
worst_svc_hard_state =
static_cast<int>(ServiceListStateColumn::Type::worst_hard_state),
num_hst_up = 10,
num_hst_down = 11,
num_hst_unreach = 12,
num_hst_pending = 13,
num_hst = -11,
worst_hst_state = -12,
};
HostListStateColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset,
int extra_extra_offset, int offset, MonitoringCore *mc,
Type logictype)
: IntColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _mc(mc)
, _logictype(logictype) {}
int32_t getValue(Row row, const contact *auth_user) const override;
private:
MonitoringCore *_mc;
const Type _logictype;
void update(host *hst, const contact *auth_user, int32_t &result) const;
};
#endif // HostListStateColumn_h

94
src/HostServiceState.cc Normal file
View File

@@ -0,0 +1,94 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostServiceState.h"
HostServiceState::HostServiceState()
: _is_host(false)
, _time(0)
, _lineno(0)
, _from(0)
, _until(0)
, _duration(0)
, _duration_part(0)
, _duration_state_UNMONITORED(0)
, _duration_part_UNMONITORED(0)
, _duration_state_OK(0)
, _duration_part_OK(0)
, _duration_state_WARNING(0)
, _duration_part_WARNING(0)
, _duration_state_CRITICAL(0)
, _duration_part_CRITICAL(0)
, _duration_state_UNKNOWN(0)
, _duration_part_UNKNOWN(0)
, _host_down(0)
, _state(0)
, _in_notification_period(0)
, _in_service_period(0)
, _in_downtime(0)
, _in_host_downtime(0)
, _is_flapping(0)
, _may_no_longer_exist(false)
, _has_vanished(false)
, _last_known_time(0)
, _host(nullptr)
, _service(nullptr) {}
#ifdef CMC
void HostServiceState::computePerStateDurations() {
_duration_state_UNMONITORED = 0;
_duration_part_UNMONITORED = 0;
_duration_state_OK = 0;
_duration_part_OK = 0;
_duration_state_WARNING = 0;
_duration_part_WARNING = 0;
_duration_state_CRITICAL = 0;
_duration_part_CRITICAL = 0;
_duration_state_UNKNOWN = 0;
_duration_part_UNKNOWN = 0;
switch (_state) {
case -1:
_duration_state_UNMONITORED = _duration;
_duration_part_UNMONITORED = _duration_part;
break;
case 0:
_duration_state_OK = _duration;
_duration_part_OK = _duration_part;
break;
case 1:
_duration_state_WARNING = _duration;
_duration_part_WARNING = _duration_part;
break;
case 2:
_duration_state_CRITICAL = _duration;
_duration_part_CRITICAL = _duration_part;
break;
case 3:
_duration_state_UNKNOWN = _duration;
_duration_part_UNKNOWN = _duration_part;
break;
}
}
#endif

107
src/HostServiceState.h Normal file
View File

@@ -0,0 +1,107 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostServiceState_h
#define HostServiceState_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <ctime>
#include <string>
#include <vector>
class HostServiceState;
// for host/service, ugly...
#ifdef CMC
#include "cmc.h"
#else
#include "nagios.h"
#endif
using HostServices = std::vector<HostServiceState *>;
using HostServiceKey = void *;
class HostServiceState {
public:
bool _is_host;
time_t _time;
int32_t _lineno;
time_t _from;
time_t _until;
time_t _duration;
double _duration_part;
time_t _duration_state_UNMONITORED;
double _duration_part_UNMONITORED;
time_t _duration_state_OK;
double _duration_part_OK;
time_t _duration_state_WARNING;
double _duration_part_WARNING;
time_t _duration_state_CRITICAL;
double _duration_part_CRITICAL;
time_t _duration_state_UNKNOWN;
double _duration_part_UNKNOWN;
// State information
int _host_down; // used if service
int _state; // -1/0/1/2/3
int _in_notification_period;
int _in_service_period;
int _in_downtime;
int _in_host_downtime;
int _is_flapping;
// Service information
HostServices _services;
// Absent state handling
bool _may_no_longer_exist;
bool _has_vanished;
time_t _last_known_time;
std::string _debug_info;
std::string _log_output;
// maybe "": -> no period known, we assume "always"
std::string _notification_period;
// maybe "": -> no period known, we assume "always"
std::string _service_period;
host *_host;
service *_service;
std::string _host_name; // Fallback if host no longer exists
std::string _service_description; // Fallback if service no longer exists
HostServiceState();
#ifdef CMC
void computePerStateDurations();
#endif
};
#endif // HostServiceState_h

View File

@@ -0,0 +1,133 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostSpecialDoubleColumn.h"
#include "Row.h"
#ifdef CMC
#include <chrono>
#include "Object.h"
#include "State.h"
#include "Timeperiod.h"
#else
#include <ctime>
#include "nagios.h"
#endif
double HostSpecialDoubleColumn::getValue(Row row) const {
#ifdef CMC
if (auto object = columnData<Object>(row)) {
switch (_type) {
case Type::staleness:
return staleness(object);
}
}
#else
if (auto hst = columnData<host>(row)) {
switch (_type) {
case Type::staleness: {
extern int interval_length;
return static_cast<double>(time(nullptr) - hst->last_check) /
((hst->check_interval == 0 ? 1 : hst->check_interval) *
interval_length);
}
}
}
#endif
return 0;
}
#ifdef CMC
// static
double HostSpecialDoubleColumn::staleness(const Object *object) {
auto state = object->state();
std::chrono::system_clock::duration check_result_age;
const Timeperiod *check_period = object->_check_period;
std::chrono::system_clock::time_point last_period_change =
check_period->lastStateChange();
std::chrono::system_clock::time_point last_check = state->_last_check;
// Compute the age of the check result. When the check is currently in its
// check period then...
auto m_now = std::chrono::system_clock::now();
if (check_period->isActive()) {
// Has a check happened since the beginning of the current phase? Then
// simply compare last check with current time. This should be the 99%
// case.
if (last_check >= last_period_change) {
check_result_age = m_now - last_check;
} else {
// otherwise the active phase has just begun. Take the time since
// the beginning of the phase.
check_result_age = m_now - last_period_change;
// Add time at the end of the pre-last transition
std::chrono::system_clock::time_point prelast_period_change =
check_period->previousLastStateChange();
if (prelast_period_change !=
std::chrono::system_clock::time_point()) {
if (last_check < prelast_period_change) {
check_result_age += prelast_period_change - last_check;
}
// else: a check happend out of the check period. Ignore this
}
// else: no information about past. Ignore this
}
} else {
// Check is currently out of its check period? Then use the beginning of
// the inactive phase as reference for computing the check age. This
// effectively freezes the staleness value when a goes goes into its
// inactive phase.
if (last_period_change != std::chrono::system_clock::time_point()) {
check_result_age = last_period_change - last_check;
} else {
// e.g. for timeperiod "never"
check_result_age = std::chrono::seconds(0);
}
}
// Is the checks' result based on cached agent data? Then use the age of
// that data as check result age
std::chrono::duration<double> interval;
if (state->_cached_at != std::chrono::system_clock::time_point()) {
// Cache interval and check interval can add up in the worst case.
interval = state->_cache_interval + object->_check_interval;
std::chrono::system_clock::duration cached_age =
m_now - state->_cached_at;
if (cached_age > check_result_age) {
check_result_age = cached_age;
}
} else {
interval = object->_check_interval;
}
// Check_MK configures the interval for its passive checks correctly. Just
// make sure that we do not fail if it is set to 0 by some error.
return std::chrono::duration_cast<std::chrono::seconds>(check_result_age)
.count() /
(interval == std::chrono::seconds(0) ? 1 : interval.count());
}
#endif

View File

@@ -0,0 +1,59 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostSpecialDoubleColumn_h
#define HostSpecialDoubleColumn_h
#include "config.h" // IWYU pragma: keep
#include <string>
#include "DoubleColumn.h"
class Row;
#ifdef CMC
class Object;
#endif
class HostSpecialDoubleColumn : public DoubleColumn {
public:
enum class Type { staleness };
HostSpecialDoubleColumn(const std::string& name,
const std::string& description, int indirect,
int extra_offset, int extra_extra_offset,
int offset, Type hsdc_type)
: DoubleColumn(name, description, indirect, extra_offset,
extra_extra_offset, offset)
, _type(hsdc_type) {}
[[nodiscard]] double getValue(Row row) const override;
#ifdef CMC
static double staleness(const Object* object);
#endif
private:
const Type _type;
};
#endif // HostSpecialDoubleColumn_h

View File

@@ -0,0 +1,92 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "HostSpecialIntColumn.h"
#include "MonitoringCore.h"
#include "Row.h"
#include "mk_inventory.h"
#ifdef CMC
#include "Core.h"
#include "Host.h"
#include "Object.h"
#include "RRDBackend.h"
#include "RRDInfoCache.h"
#include "State.h"
#include "cmc.h"
#else
#include "nagios.h"
#include "pnp4nagios.h"
#endif
int32_t HostSpecialIntColumn::getValue(Row row,
const contact* /* auth_user */) const {
#ifdef CMC
if (auto object = columnData<Object>(row)) {
switch (_type) {
case Type::real_hard_state: {
if (object->isCurrentStateOK()) {
return 0;
}
auto state = object->state();
return state->_state_type == StateType::hard
? state->_current_state
: state->_last_hard_state;
}
case Type::pnp_graph_present:
return _mc->impl<Core>()
->_rrd_backend.infoFor(object)
._names.empty()
? 0
: 1;
case Type::mk_inventory_last:
return static_cast<int32_t>(mk_inventory_last(
_mc->mkInventoryPath() + "/" + object->host()->name()));
}
}
#else
if (auto hst = columnData<host>(row)) {
switch (_type) {
case Type::real_hard_state:
if (hst->current_state == 0) {
return 0;
}
if (hst->state_type == HARD_STATE) {
return hst->current_state;
}
return hst->last_hard_state;
case Type::pnp_graph_present:
return pnpgraph_present(_mc, hst->name,
dummy_service_description());
case Type::mk_inventory_last: {
return static_cast<int32_t>(mk_inventory_last(
_mc->mkInventoryPath() + "/" + hst->name));
}
}
}
#endif
return 0;
}

View File

@@ -0,0 +1,56 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef HostSpecialIntColumn_h
#define HostSpecialIntColumn_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <string>
#include "IntColumn.h"
#include "contact_fwd.h"
class MonitoringCore;
class Row;
class HostSpecialIntColumn : public IntColumn {
public:
enum class Type { real_hard_state, pnp_graph_present, mk_inventory_last };
HostSpecialIntColumn(const std::string &name,
const std::string &description, int indirect_offset,
int extra_offset, int extra_extra_offset, int offset,
MonitoringCore *mc, Type hsic_type)
: IntColumn(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset)
, _mc(mc)
, _type(hsic_type) {}
int32_t getValue(Row row, const contact *auth_user) const override;
private:
MonitoringCore *_mc;
const Type _type;
};
#endif // HostSpecialIntColumn_h

252
src/InputBuffer.cc Normal file
View File

@@ -0,0 +1,252 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "InputBuffer.h"
#include <unistd.h>
#include <cctype>
#include <cstring>
#include <ostream>
#include <type_traits>
#include "Logger.h"
#include "Poller.h"
namespace {
const size_t initial_buffer_size = 4096;
// TODO(sp): Make this configurable?
const size_t maximum_buffer_size = 500 * 1024 * 1024;
bool timeout_reached(const std::chrono::system_clock::time_point &start,
const std::chrono::milliseconds &timeout) {
return (timeout != std::chrono::milliseconds(0)) &&
(std::chrono::system_clock::now() - start >= timeout);
}
} // namespace
std::ostream &operator<<(std::ostream &os, const InputBuffer::Result &r) {
switch (r) {
case InputBuffer::Result::request_read:
return os << "request read";
case InputBuffer::Result::data_read:
return os << "data read";
case InputBuffer::Result::unexpected_eof:
return os << "unexpected EOF";
case InputBuffer::Result::should_terminate:
return os << "should terminate";
case InputBuffer::Result::line_too_long:
return os << "line too long";
case InputBuffer::Result::eof:
return os << "EOF";
case InputBuffer::Result::empty_request:
return os << "empty request";
case InputBuffer::Result::timeout:
return os << "timeout";
}
return os; // never reached
}
InputBuffer::InputBuffer(int fd, const bool &termination_flag, Logger *logger,
std::chrono::milliseconds query_timeout,
std::chrono::milliseconds idle_timeout)
: _fd(fd)
, _termination_flag(termination_flag)
, _query_timeout(query_timeout)
, _idle_timeout(idle_timeout)
, _readahead_buffer(initial_buffer_size)
, _logger(logger) {
_read_index = 0; // points to data not yet processed
_write_index = 0; // points to end of data in buffer
}
// read in data enough for one complete request (and maybe more).
InputBuffer::Result InputBuffer::readRequest() {
// Remember when we started waiting for a request. This is needed for the
// idle_timeout. A connection may not be idle longer than that value.
auto start_of_idle = std::chrono::system_clock::now();
// Remember if we have read some part of the query. During
// a query the timeout is another (short) than between
// queries.
bool query_started = false;
// _read_index points to the place in the buffer, where the
// next valid data begins. This data ends at _write_index.
// That data might have been read while reading the previous
// request.
// r is used to find the end of the line
size_t r = _read_index;
while (true) {
// Try to find end of the current line in buffer
while (r < _write_index && _readahead_buffer[r] != '\n') {
r++; // now r is at end of data or at '\n'
}
// If we cannot find the end of line in the data
// already read, then we need to read new data from
// the client.
if (r == _write_index) {
// Is there still space left in the buffer => read in
// further data into the buffer.
if (_write_index < _readahead_buffer.capacity()) {
Result rd =
readData(); // tries to read in further data into buffer
if (rd == Result::timeout) {
if (query_started) {
Informational(_logger)
<< "Timeout of " << _query_timeout.count()
<< " ms exceeded while reading query";
return Result::timeout;
}
// Check if we exceeded the maximum time between two queries
if (timeout_reached(start_of_idle, _idle_timeout)) {
Informational(_logger)
<< "Idle timeout of " << _idle_timeout.count()
<< " ms exceeded. Going to close connection.";
return Result::timeout;
}
}
// Are we at end of file? That is only an error, if we've
// read an incomplete line. If the last thing we read was
// a linefeed, then we consider the current request to
// be valid, if it is not empty.
else if (
rd == Result::eof &&
r == _read_index /* currently at beginning of a line */) {
if (_request_lines.empty()) {
return Result::eof; // empty request -> no request
}
// socket has been closed but request is complete
return Result::request_read;
// the current state is now:
// _read_index == r == _write_index => buffer is empty
// that way, if the main program tries to read the
// next request, it will get an IB_UNEXPECTED_EOF
}
// if we are *not* at an end of line while reading
// a request, we got an invalid request.
else if (rd == Result::eof) {
return Result::unexpected_eof;
// Other status codes
} else if (rd == Result::should_terminate) {
return rd;
}
}
// OK. So no space is left in the buffer. But maybe at the
// *beginning* of the buffer is space left again. This is
// very probable if _write_index == _readahead_buffer.capacity().
// Most
// of the buffer's content is already processed. So we simply
// shift the yet unprocessed data to the very left of the buffer.
else if (_read_index > 0) {
size_t shift_by =
_read_index; // distance to beginning of buffer
size_t size =
_write_index - _read_index; // amount of data to shift
memmove(&_readahead_buffer[0], &_readahead_buffer[_read_index],
size);
_read_index = 0; // unread data is now at the beginning
_write_index -= shift_by; // write pointer shifted to the left
r -= shift_by; // current scan position also shift left
// continue -> still no data in buffer, but it will
// be read, as now is space
}
// buffer is full, but still no end of line found
else {
size_t new_capacity = _readahead_buffer.capacity() * 2;
if (new_capacity > maximum_buffer_size) {
Informational(_logger)
<< "Error: maximum length of request line exceeded";
return Result::line_too_long;
}
_readahead_buffer.resize(new_capacity);
}
} else // end of line found
{
if (_read_index == r) { // empty line found => end of request
_read_index = r + 1;
// Was ist, wenn noch keine korrekte Zeile gelesen wurde?
if (_request_lines.empty()) {
return Result::empty_request;
}
return Result::request_read;
} // non-empty line: belongs to current request
size_t length = r - _read_index;
for (size_t end = r; end > _read_index &&
(isspace(_readahead_buffer[--end]) != 0);) {
length--;
}
if (length > 0) {
_request_lines.emplace_back(&_readahead_buffer[_read_index],
length);
} else {
Informational(_logger)
<< "Warning ignoring line containing only whitespace";
}
query_started = true;
_read_index = r + 1;
r = _read_index;
}
}
}
// read at least *some* data. Return IB_TIMEOUT if that lasts more than
// _query_timeout msecs.
InputBuffer::Result InputBuffer::readData() {
auto start = std::chrono::system_clock::now();
while (!_termination_flag) {
if (timeout_reached(start, _query_timeout)) {
return Result::timeout;
}
Poller poller;
poller.addFileDescriptor(_fd, PollEvents::in);
int retval = poller.poll(std::chrono::milliseconds(200));
if (retval > 0 && poller.isFileDescriptorSet(_fd, PollEvents::in)) {
ssize_t r = read(_fd, &_readahead_buffer[_write_index],
_readahead_buffer.capacity() - _write_index);
if (r < 0) {
return Result::eof;
}
if (r == 0) {
return Result::eof;
}
_write_index += r;
return Result::data_read;
}
}
return Result::should_terminate;
}
bool InputBuffer::empty() const { return _request_lines.empty(); }
std::string InputBuffer::nextLine() {
std::string s = _request_lines.front();
_request_lines.pop_front();
return s;
}

73
src/InputBuffer.h Normal file
View File

@@ -0,0 +1,73 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef InputBuffer_h
#define InputBuffer_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <cstddef>
#include <iosfwd>
#include <list>
#include <string>
#include <vector>
class Logger;
class InputBuffer {
public:
enum class Result {
request_read,
data_read,
unexpected_eof,
should_terminate,
line_too_long,
eof,
empty_request,
timeout
};
friend std::ostream &operator<<(std::ostream &os, const Result &r);
InputBuffer(int fd, const bool &termination_flag, Logger *logger,
std::chrono::milliseconds query_timeout,
std::chrono::milliseconds idle_timeout);
Result readRequest();
[[nodiscard]] bool empty() const;
std::string nextLine();
private:
int _fd;
const bool &_termination_flag;
std::chrono::milliseconds _query_timeout;
std::chrono::milliseconds _idle_timeout;
std::vector<char> _readahead_buffer;
size_t _read_index;
size_t _write_index;
std::list<std::string> _request_lines;
Logger *const _logger;
Result readData();
};
#endif // InputBuffer_h

55
src/IntAggregator.h Normal file
View File

@@ -0,0 +1,55 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef IntAggregator_h
#define IntAggregator_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include "Aggregator.h"
#include "IntColumn.h"
#include "contact_fwd.h"
class Row;
class RowRenderer;
class IntAggregator : public Aggregator {
public:
IntAggregator(const AggregationFactory &factory, const IntColumn *column)
: _aggregation(factory()), _column(column) {}
void consume(Row row, const contact *auth_user,
std::chrono::seconds /* timezone_offset*/) override {
_aggregation->update(_column->getValue(row, auth_user));
}
void output(RowRenderer &r) const override {
r.output(_aggregation->value());
}
private:
std::unique_ptr<Aggregation> _aggregation;
const IntColumn *const _column;
};
#endif // IntAggregator_h

47
src/IntColumn.cc Normal file
View File

@@ -0,0 +1,47 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "IntColumn.h"
#include "Aggregator.h"
#include "Filter.h"
#include "IntAggregator.h"
#include "IntFilter.h"
#include "Renderer.h"
#include "Row.h"
void IntColumn::output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds /*timezone_offset*/) const {
r.output(getValue(row, auth_user));
}
std::unique_ptr<Filter> IntColumn::createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const {
return std::make_unique<IntFilter>(kind, *this, relOp, value);
}
std::unique_ptr<Aggregator> IntColumn::createAggregator(
AggregationFactory factory) const {
return std::make_unique<IntAggregator>(factory, this);
}

64
src/IntColumn.h Normal file
View File

@@ -0,0 +1,64 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef IntColumn_h
#define IntColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <cstdint>
#include <memory>
#include <string>
#include "Column.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class Aggregator;
class Row;
class RowRenderer;
class IntColumn : public Column {
public:
IntColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset, int extra_extra_offset,
int offset)
: Column(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
[[nodiscard]] ColumnType type() const override { return ColumnType::int_; }
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
[[nodiscard]] std::unique_ptr<Aggregator> createAggregator(
AggregationFactory factory) const override;
virtual int32_t getValue(Row row, const contact *auth_user) const = 0;
};
#endif // IntColumn_h

149
src/IntFilter.cc Normal file
View File

@@ -0,0 +1,149 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "IntFilter.h"
#include <cstdlib>
#include "Filter.h"
#include "IntColumn.h"
#include "Row.h"
IntFilter::IntFilter(Kind kind, const IntColumn &column,
RelationalOperator relOp, const std::string &value)
: ColumnFilter(kind, column, relOp, value)
, _column(column)
, _ref_value(atoi(value.c_str())) {}
namespace {
bool eval(int32_t x, RelationalOperator op, int32_t y) {
switch (op) {
case RelationalOperator::equal:
return x == y;
case RelationalOperator::not_equal:
return x != y;
case RelationalOperator::matches: // superset
return (x & y) == y;
case RelationalOperator::doesnt_match: // not superset
return (x & y) != y;
case RelationalOperator::equal_icase: // subset
return (x & y) == x;
case RelationalOperator::not_equal_icase: // not subset
return (x & y) != x;
case RelationalOperator::matches_icase: // contains any
return (x & y) != 0;
case RelationalOperator::doesnt_match_icase: // contains none of
return (x & y) == 0;
case RelationalOperator::less:
return x < y;
case RelationalOperator::greater_or_equal:
return x >= y;
case RelationalOperator::greater:
return x > y;
case RelationalOperator::less_or_equal:
return x <= y;
}
return false;
}
} // namespace
bool IntFilter::accepts(Row row, const contact *auth_user,
std::chrono::seconds /*timezone_offset*/) const {
return eval(_column.getValue(row, auth_user), oper(), _ref_value);
}
std::optional<int32_t> IntFilter::greatestLowerBoundFor(
const std::string &column_name,
std::chrono::seconds /* timezone_offset */) const {
if (column_name != columnName()) {
return {}; // wrong column
}
switch (oper()) {
case RelationalOperator::equal:
case RelationalOperator::greater_or_equal:
return {_ref_value};
case RelationalOperator::greater:
return {_ref_value + 1};
case RelationalOperator::not_equal:
case RelationalOperator::matches: // superset
case RelationalOperator::doesnt_match: // not superset
case RelationalOperator::equal_icase: // subset
case RelationalOperator::not_equal_icase: // not subset
case RelationalOperator::matches_icase: // contains any
case RelationalOperator::doesnt_match_icase: // contains none of
case RelationalOperator::less:
case RelationalOperator::less_or_equal:
// NOTE: If we use the equivalent 'return {}' here and the other
// std::nullopt occurences below, we run into g++/libstdc++ bug
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86465. :-/
return std::nullopt;
}
return std::nullopt; // unreachable
}
std::optional<int32_t> IntFilter::leastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds /* timezone_offset */) const {
if (column_name != columnName()) {
return {}; // wrong column
}
switch (oper()) {
case RelationalOperator::equal:
case RelationalOperator::less_or_equal:
return {_ref_value};
case RelationalOperator::less:
return {_ref_value - 1};
case RelationalOperator::not_equal:
case RelationalOperator::matches: // superset
case RelationalOperator::doesnt_match: // not superset
case RelationalOperator::equal_icase: // subset
case RelationalOperator::not_equal_icase: // not subset
case RelationalOperator::matches_icase: // contains any
case RelationalOperator::doesnt_match_icase: // contains none of
case RelationalOperator::greater_or_equal:
case RelationalOperator::greater:
return std::nullopt;
}
return std::nullopt; // unreachable
}
std::optional<std::bitset<32>> IntFilter::valueSetLeastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds /* timezone_offset */) const {
if (column_name != columnName()) {
return {}; // wrong column
}
std::bitset<32> result;
for (int32_t bit = 0; bit < 32; ++bit) {
result[bit] = eval(bit, oper(), _ref_value);
}
return {result};
}
std::unique_ptr<Filter> IntFilter::copy() const {
return std::make_unique<IntFilter>(*this);
}
std::unique_ptr<Filter> IntFilter::negate() const {
return std::make_unique<IntFilter>(
kind(), _column, negateRelationalOperator(oper()), value());
}

70
src/IntFilter.h Normal file
View File

@@ -0,0 +1,70 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef IntFilter_h
#define IntFilter_h
#include "config.h" // IWYU pragma: keep
#include <bitset>
#include <chrono>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include "ColumnFilter.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class IntColumn;
class Row;
class IntFilter : public ColumnFilter {
public:
IntFilter(Kind kind, const IntColumn &column, RelationalOperator relOp,
const std::string &value);
bool accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::optional<int32_t> greatestLowerBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::optional<int32_t> leastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::optional<std::bitset<32>> valueSetLeastUpperBoundFor(
const std::string &column_name,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> copy() const override;
[[nodiscard]] std::unique_ptr<Filter> negate() const override;
private:
const IntColumn &_column;
const int32_t _ref_value;
};
#endif // IntFilter_h

46
src/IntPointerColumn.h Normal file
View File

@@ -0,0 +1,46 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef IntPointerColumn_h
#define IntPointerColumn_h
#include "config.h" // IWYU pragma: keep
#include "IntColumn.h"
class IntPointerColumn : public IntColumn {
public:
IntPointerColumn(const std::string& name, const std::string& description,
const int* number)
: IntColumn(name, description, -1, -1, -1, 0), _number(number) {}
int32_t getValue(Row /* row */,
const contact* /* auth_user */) const override {
return *_number;
}
private:
const int* const _number;
};
#endif // IntPointerColumn_h

50
src/ListColumn.cc Normal file
View File

@@ -0,0 +1,50 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ListColumn.h"
#include <stdexcept>
#include "Filter.h"
#include "ListFilter.h"
#include "Renderer.h"
#include "Row.h"
void ListColumn::output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const {
ListRenderer l(r);
for (const auto &val : getValue(row, auth_user, timezone_offset)) {
l.output(val);
}
}
std::unique_ptr<Filter> ListColumn::createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const {
return std::make_unique<ListFilter>(kind, *this, relOp, value);
}
std::unique_ptr<Aggregator> ListColumn::createAggregator(
AggregationFactory /*factory*/) const {
throw std::runtime_error("aggregating on list column '" + name() +
"' not supported");
}

68
src/ListColumn.h Normal file
View File

@@ -0,0 +1,68 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ListColumn_h
#define ListColumn_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <memory>
#include <string>
#include <vector>
#include "Column.h"
#include "Filter.h"
#include "contact_fwd.h"
#include "opids.h"
class Aggregator;
class Row;
class RowRenderer;
class ListColumn : public Column {
public:
ListColumn(const std::string &name, const std::string &description,
int indirect_offset, int extra_offset, int extra_extra_offset,
int offset)
: Column(name, description, indirect_offset, extra_offset,
extra_extra_offset, offset) {}
[[nodiscard]] ColumnType type() const override { return ColumnType::list; }
void output(Row row, RowRenderer &r, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::unique_ptr<Filter> createFilter(
Filter::Kind kind, RelationalOperator relOp,
const std::string &value) const override;
[[nodiscard]] std::unique_ptr<Aggregator> createAggregator(
AggregationFactory factory) const override;
// TODO(sp) What we actually want here is a stream of strings, not a
// concrete container.
virtual std::vector<std::string> getValue(
Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const = 0;
};
#endif // ListColumn_h

145
src/ListFilter.cc Normal file
View File

@@ -0,0 +1,145 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "ListFilter.h"
#include <sstream>
#include <string>
#include "Filter.h"
#include "ListColumn.h"
#include "Logger.h"
#include "RegExp.h"
#include "Row.h"
namespace {
RelationalOperator relOpForElement(RelationalOperator relOp) {
switch (relOp) {
case RelationalOperator::matches:
case RelationalOperator::doesnt_match:
case RelationalOperator::matches_icase:
case RelationalOperator::doesnt_match_icase:
return relOp;
case RelationalOperator::less:
case RelationalOperator::greater_or_equal:
return RelationalOperator::equal;
case RelationalOperator::greater:
case RelationalOperator::less_or_equal:
return RelationalOperator::equal_icase;
case RelationalOperator::equal:
case RelationalOperator::not_equal:
case RelationalOperator::equal_icase:
case RelationalOperator::not_equal_icase:
// optimization: do not create a RegExp later
return RelationalOperator::less;
};
return relOp; // make the compiler happy...
}
} // namespace
ListFilter::ListFilter(Kind kind, const ListColumn &column,
RelationalOperator relOp, const std::string &value)
: ColumnFilter(kind, column, relOp, value)
, _column(column)
, _regExp(makeRegExpFor(relOpForElement(relOp), value)) {}
bool ListFilter::accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const {
switch (oper()) {
case RelationalOperator::equal:
if (!value().empty()) {
Informational(_column.logger())
<< "Sorry, equality for lists implemented only for emptiness";
return false;
}
return !any(row, auth_user, timezone_offset,
[](const std::string & /*unused*/) { return true; });
case RelationalOperator::not_equal:
if (!value().empty()) {
Informational(_column.logger())
<< "Sorry, inequality for lists implemented only for emptiness";
return false;
}
return any(row, auth_user, timezone_offset,
[](const std::string & /*unused*/) { return true; });
case RelationalOperator::matches:
case RelationalOperator::matches_icase:
return any(
row, auth_user, timezone_offset,
[&](const std::string &elem) { return _regExp->search(elem); });
case RelationalOperator::doesnt_match:
case RelationalOperator::doesnt_match_icase:
return !any(
row, auth_user, timezone_offset,
[&](const std::string &elem) { return _regExp->search(elem); });
case RelationalOperator::greater_or_equal:
case RelationalOperator::less_or_equal:
return any(
row, auth_user, timezone_offset,
[&](const std::string &elem) { return _regExp->match(elem); });
case RelationalOperator::less:
case RelationalOperator::greater:
return !any(
row, auth_user, timezone_offset,
[&](const std::string &elem) { return _regExp->match(elem); });
case RelationalOperator::equal_icase:
case RelationalOperator::not_equal_icase:
Informational(_column.logger())
<< "Sorry. Operator " << oper()
<< " for list columns not implemented.";
return false;
}
return false; // unreachable
}
std::optional<std::string> ListFilter::stringValueRestrictionFor(
const std::string &column_name) const {
if (column_name != columnName()) {
return {}; // wrong column
}
switch (oper()) {
case RelationalOperator::greater_or_equal:
return {value()};
case RelationalOperator::equal:
case RelationalOperator::not_equal:
case RelationalOperator::matches:
case RelationalOperator::doesnt_match:
case RelationalOperator::equal_icase:
case RelationalOperator::not_equal_icase:
case RelationalOperator::matches_icase:
case RelationalOperator::doesnt_match_icase:
case RelationalOperator::less:
case RelationalOperator::greater:
case RelationalOperator::less_or_equal:
return {};
}
return {}; // unreachable
}
std::unique_ptr<Filter> ListFilter::copy() const {
return std::make_unique<ListFilter>(*this);
}
std::unique_ptr<Filter> ListFilter::negate() const {
return std::make_unique<ListFilter>(
kind(), _column, negateRelationalOperator(oper()), value());
}

66
src/ListFilter.h Normal file
View File

@@ -0,0 +1,66 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef ListFilter_h
#define ListFilter_h
#include "config.h" // IWYU pragma: keep
#include <algorithm>
#include <chrono>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "ColumnFilter.h"
#include "Filter.h"
#include "ListColumn.h"
#include "Row.h"
#include "contact_fwd.h"
#include "opids.h"
class RegExp;
class ListFilter : public ColumnFilter {
public:
ListFilter(Kind kind, const ListColumn &column, RelationalOperator relOp,
const std::string &value);
bool accepts(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset) const override;
[[nodiscard]] std::optional<std::string> stringValueRestrictionFor(
const std::string &column_name) const override;
[[nodiscard]] std::unique_ptr<Filter> copy() const override;
[[nodiscard]] std::unique_ptr<Filter> negate() const override;
private:
const ListColumn &_column;
std::shared_ptr<RegExp> _regExp;
template <typename UnaryPredicate>
bool any(Row row, const contact *auth_user,
std::chrono::seconds timezone_offset, UnaryPredicate pred) const {
auto val = _column.getValue(row, auth_user, timezone_offset);
return std::any_of(val.begin(), val.end(), pred);
}
};
#endif // ListFilter_h

206
src/LogCache.cc Normal file
View File

@@ -0,0 +1,206 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "LogCache.h"
#include <sstream>
#include <string>
#include <utility>
#include "FileSystem.h"
#include "LogEntry.h" // IWYU pragma: keep
#include "Logfile.h"
#include "Logger.h"
#include "MonitoringCore.h"
namespace {
// Check memory every N'th new message
constexpr unsigned long check_mem_cycle = 1000;
} // namespace
int num_cached_log_messages = 0;
LogCache::LogCache(MonitoringCore *mc, unsigned long max_cached_messages)
: _mc(mc)
, _max_cached_messages(max_cached_messages)
, _num_at_last_check(0) {
update();
}
#ifdef CMC
void LogCache::setMaxCachedMessages(unsigned long m) {
if (m != _max_cached_messages) {
Notice(logger())
<< "changing maximum number of messages for log file cache to "
<< m;
_max_cached_messages = m;
}
}
#endif
void LogCache::update() {
if (!_logfiles.empty() &&
_mc->last_logfile_rotation() <= _last_index_update) {
return;
}
Informational(logger()) << "updating log file index";
_logfiles.clear();
num_cached_log_messages = 0;
_last_index_update = std::chrono::system_clock::now();
// We need to find all relevant logfiles. This includes directory, the
// current nagios.log and all files in the archive.
addToIndex(
std::make_unique<Logfile>(_mc, this, _mc->historyFilePath(), true));
fs::path dirpath = _mc->logArchivePath();
try {
for (const auto &entry : fs::directory_iterator(dirpath)) {
addToIndex(
std::make_unique<Logfile>(_mc, this, entry.path(), false));
}
} catch (const fs::filesystem_error &e) {
Warning(logger()) << "updating log file index: " << e.what();
}
if (_logfiles.empty()) {
Notice(logger()) << "no log file found, not even "
<< _mc->historyFilePath();
}
}
void LogCache::addToIndex(std::unique_ptr<Logfile> logfile) {
time_t since = logfile->since();
if (since == 0) {
return;
}
// make sure that no entry with that 'since' is existing yet. Under normal
// circumstances this never happens, but the user might have copied files
// around.
if (_logfiles.find(since) != _logfiles.end()) {
Warning(logger()) << "ignoring duplicate log file " << logfile->path();
return;
}
_logfiles.emplace(since, std::move(logfile));
}
/* This method is called each time a log message is loaded
into memory. If the number of messages loaded in memory
is to large, memory will be freed by flushing logfiles
and message not needed by the current query.
The parameters to this method reflect the current query,
not the messages that just has been loaded.
*/
void LogCache::logLineHasBeenAdded(Logfile *logfile, unsigned logclasses) {
if (static_cast<unsigned long>(++num_cached_log_messages) <=
_max_cached_messages) {
return; // current message count still allowed, everything ok
}
/* Memory checking an freeing consumes CPU ressources. We save
ressources, by avoiding to make the memory check each time
a new message is loaded when being in a sitation where no
memory can be freed. We do this by suppressing the check when
the number of messages loaded into memory has not grown
by at least check_mem_cycle messages */
if (static_cast<unsigned long>(num_cached_log_messages) <
_num_at_last_check + check_mem_cycle) {
return; // Do not check this time
}
// [1] Begin by deleting old logfiles
// Begin deleting with the oldest logfile available
logfiles_t::iterator it;
for (it = _logfiles.begin(); it != _logfiles.end(); ++it) {
if (it->second.get() == logfile) {
// Do not touch the logfile the Query is currently accessing
break;
}
if (it->second->size() > 0) {
num_cached_log_messages -= it->second->size();
it->second->flush(); // drop all messages of that file
if (static_cast<unsigned long>(num_cached_log_messages) <=
_max_cached_messages) {
// remember the number of log messages in cache when
// the last memory-release was done. No further
// release-check shall be done until that number changes.
_num_at_last_check = num_cached_log_messages;
return;
}
}
}
// The end of this loop must be reached by 'break'. At least one logfile
// must be the current logfile. So now 'it' points to the current logfile.
// We save that pointer for later.
auto queryit = it;
// [2] Delete message classes irrelevent to current query
// Starting from the current logfile (wo broke out of the
// previous loop just when 'it' pointed to that)
for (; it != _logfiles.end(); ++it) {
if (it->second->size() > 0 &&
(it->second->classesRead() & ~logclasses) != 0) {
Debug(logger()) << "freeing classes " << ~logclasses << " of file "
<< it->second->path();
// flush only messages not needed for current query
long freed = it->second->freeMessages(~logclasses);
num_cached_log_messages -= freed;
if (static_cast<unsigned long>(num_cached_log_messages) <=
_max_cached_messages) {
_num_at_last_check = num_cached_log_messages;
return;
}
}
}
// [3] Flush newest logfiles
// If there are still too many messages loaded, continue
// flushing logfiles from the oldest to the newest starting
// at the file just after (i.e. newer than) the current logfile
for (it = ++queryit; it != _logfiles.end(); ++it) {
if (it->second->size() > 0) {
Debug(logger()) << "flush newer log, " << it->second->size()
<< " number of entries";
num_cached_log_messages -= it->second->size();
it->second->flush();
if (static_cast<unsigned long>(num_cached_log_messages) <=
_max_cached_messages) {
_num_at_last_check = num_cached_log_messages;
return;
}
}
}
_num_at_last_check = num_cached_log_messages;
// If we reach this point, no more logfiles can be unloaded,
// despite the fact that there are still too many messages
// loaded.
Debug(logger()) << "cannot unload more messages, still "
<< num_cached_log_messages << " loaded (max is "
<< _max_cached_messages << ")";
}
Logger *LogCache::logger() const { return _mc->loggerLivestatus(); }

64
src/LogCache.h Normal file
View File

@@ -0,0 +1,64 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef LogCache_h
#define LogCache_h
#include "config.h" // IWYU pragma: keep
#include <chrono>
#include <ctime>
#include <map>
#include <memory>
#include <mutex>
class Logfile;
class Logger;
class MonitoringCore;
using logfiles_t = std::map<time_t, std::unique_ptr<Logfile>>;
class LogCache {
public:
std::mutex _lock;
LogCache(MonitoringCore *mc, unsigned long max_cached_messages);
#ifdef CMC
void setMaxCachedMessages(unsigned long m);
#endif
void logLineHasBeenAdded(Logfile *logfile, unsigned logclasses);
void update();
auto begin() { return _logfiles.begin(); }
auto end() { return _logfiles.end(); }
private:
MonitoringCore *const _mc;
unsigned long _max_cached_messages;
unsigned long _num_at_last_check;
logfiles_t _logfiles;
std::chrono::system_clock::time_point _last_index_update;
void addToIndex(std::unique_ptr<Logfile> logfile);
[[nodiscard]] Logger *logger() const;
};
#endif // LogCache_h

417
src/LogEntry.cc Normal file
View File

@@ -0,0 +1,417 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "LogEntry.h"
#include <cstdlib>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include "MonitoringCore.h"
// 0123456789012345678901234567890
// [1234567890] FOO BAR: blah blah
static constexpr size_t timestamp_prefix_length = 13;
// TODO(sp) Fix classifyLogMessage() below to always set all fields and remove
// this set-me-to-zero-to-be-sure-block.
LogEntry::LogEntry(MonitoringCore *mc, size_t lineno, std::string line)
: _lineno(static_cast<int32_t>(lineno))
, _complete(std::move(line))
, _state(0)
, _attempt(0)
, _host(nullptr)
, _service(nullptr)
, _contact(nullptr) {
// pointer to options (everything after ':')
size_t pos = _complete.find(':');
if (pos != std::string::npos) {
pos = _complete.find_first_not_of(' ', pos + 1);
}
if (pos == std::string::npos) {
pos = _complete.size();
}
_options = &_complete[pos];
try {
if (_complete.size() < timestamp_prefix_length || _complete[0] != '[' ||
_complete[11] != ']' || _complete[12] != ' ') {
throw std::invalid_argument("timestamp delimiter");
}
_time = std::stoi(_complete.substr(1, 10));
} catch (const std::logic_error &e) {
_logclass = Class::invalid;
_type = LogEntryType::none;
return; // ignore invalid lines silently
}
classifyLogMessage();
applyWorkarounds();
updateReferences(mc);
}
bool LogEntry::assign(Param par, const std::string &field) {
switch (par) {
case Param::HostName:
this->_host_name = field;
break;
case Param::SvcDesc:
this->_svc_desc = field;
break;
case Param::HostState:
this->_state = static_cast<int>(parseHostState(field));
break;
case Param::ServiceState:
this->_state = static_cast<int>(parseServiceState(field));
break;
case Param::State:
this->_state = atoi(field.c_str());
break;
case Param::StateType:
this->_state_type = field;
break;
case Param::Attempt:
this->_attempt = atoi(field.c_str());
break;
case Param::Comment:
this->_comment = field;
break;
case Param::CommandName:
this->_command_name = field;
break;
case Param::ContactName:
this->_contact_name = field;
break;
case Param::CheckOutput:
this->_check_output = field;
break;
}
return true;
};
std::vector<LogEntry::LogDef> LogEntry::log_definitions{
LogDef{"INITIAL HOST STATE",
Class::state,
LogEntryType::state_host_initial,
{Param::HostName, Param::HostState, Param::StateType, Param::Attempt,
Param::CheckOutput}},
////////////////
LogDef{"CURRENT HOST STATE",
Class::state,
LogEntryType::state_host,
{Param::HostName, Param::HostState, Param::StateType, Param::Attempt,
Param::CheckOutput}},
////////////////
LogDef{"HOST ALERT",
Class::alert,
LogEntryType::alert_host,
{Param::HostName, Param::HostState, Param::StateType, Param::Attempt,
Param::CheckOutput}},
////////////////
LogDef{"HOST DOWNTIME ALERT",
Class::alert,
LogEntryType::downtime_alert_host,
{Param::HostName, Param::StateType, Param::Comment}},
////////////////
LogDef{"HOST ACKNOWLEDGE ALERT",
Class::alert,
LogEntryType::acknowledge_alert_host,
{Param::HostName, Param::StateType, Param::ContactName,
Param::Comment}},
////////////////
LogDef{"HOST FLAPPING ALERT",
Class::alert,
LogEntryType::flapping_host,
{Param::HostName, Param::StateType, Param::Comment}},
////////////////
LogDef{"INITIAL SERVICE STATE",
Class::state,
LogEntryType::state_service_initial,
{Param::HostName, Param::SvcDesc, Param::ServiceState,
Param::StateType, Param::Attempt, Param::CheckOutput}},
////////////////
LogDef{"CURRENT SERVICE STATE",
Class::state,
LogEntryType::state_service,
{Param::HostName, Param::SvcDesc, Param::ServiceState,
Param::StateType, Param::Attempt, Param::CheckOutput}},
////////////////
LogDef{"SERVICE ALERT",
Class::alert,
LogEntryType::alert_service,
{Param::HostName, Param::SvcDesc, Param::ServiceState,
Param::StateType, Param::Attempt, Param::CheckOutput}},
////////////////
LogDef{"SERVICE DOWNTIME ALERT",
Class::alert,
LogEntryType::downtime_alert_service,
{Param::HostName, Param::SvcDesc, Param::StateType, Param::Comment}},
////////////////
LogDef{"SERVICE ACKNOWLEDGE ALERT",
Class::alert,
LogEntryType::acknowledge_alert_service,
{Param::HostName, Param::SvcDesc, Param::StateType,
Param::ContactName, Param::Comment}},
////////////////
LogDef{"SERVICE FLAPPING ALERT",
Class::alert,
LogEntryType::flapping_service,
{Param::HostName, Param::SvcDesc, Param::StateType, Param::Comment}},
////////////////
LogDef{"TIMEPERIOD TRANSITION",
Class::state,
LogEntryType::timeperiod_transition,
{}},
////////////////
LogDef{"HOST NOTIFICATION",
Class::hs_notification,
LogEntryType::none,
{Param::ContactName, Param::HostName, Param::StateType,
Param::CommandName, Param::CheckOutput}},
////////////////
LogDef{"SERVICE NOTIFICATION",
Class::hs_notification,
LogEntryType::none,
{Param::ContactName, Param::HostName, Param::SvcDesc,
Param::StateType, Param::CommandName, Param::CheckOutput}},
////////////////
LogDef{"HOST NOTIFICATION RESULT",
Class::hs_notification,
LogEntryType::none,
{Param::ContactName, Param::HostName, Param::StateType,
Param::CommandName, Param::CheckOutput, Param::Comment}},
////////////////
LogDef{
"SERVICE NOTIFICATION RESULT",
Class::hs_notification,
LogEntryType::none,
{Param::ContactName, Param::HostName, Param::SvcDesc, Param::StateType,
Param::CommandName, Param::CheckOutput, Param::Comment}},
////////////////
LogDef{"HOST NOTIFICATION PROGRESS",
Class::hs_notification,
LogEntryType::none,
{Param::ContactName, Param::HostName, Param::StateType,
Param::CommandName, Param::CheckOutput}},
////////////////
LogDef{"SERVICE NOTIFICATION PROGRESS",
Class::hs_notification,
LogEntryType::none,
{Param::ContactName, Param::HostName, Param::SvcDesc,
Param::StateType, Param::CommandName, Param::CheckOutput}},
////////////////
LogDef{"HOST ALERT HANDLER STARTED",
Class::alert_handlers,
LogEntryType::none,
{Param::HostName, Param::CommandName}},
////////////////
LogDef{"SERVICE ALERT HANDLER STARTED",
Class::alert_handlers,
LogEntryType::none,
{Param::HostName, Param::SvcDesc, Param::CommandName}},
////////////////
LogDef{"HOST ALERT HANDLER STOPPED",
Class::alert_handlers,
LogEntryType::none,
{Param::HostName, Param::CommandName, Param::ServiceState,
Param::CheckOutput}},
////////////////
LogDef{"SERVICE ALERT HANDLER STOPPED",
Class::alert_handlers,
LogEntryType::none,
{Param::HostName, Param::SvcDesc, Param::CommandName,
Param::ServiceState, Param::CheckOutput}},
////////////////
LogDef{"PASSIVE SERVICE CHECK",
Class::passivecheck,
LogEntryType::none,
{Param::HostName, Param::SvcDesc, Param::State, Param::CheckOutput}},
////////////////
LogDef{"PASSIVE HOST CHECK",
Class::passivecheck,
LogEntryType::none,
{Param::HostName, Param::State, Param::CheckOutput}},
////////////////
LogDef{"EXTERNAL COMMAND", Class::ext_command, LogEntryType::none, {}}};
// A bit verbose, but we avoid unnecessary string copies below.
void LogEntry::classifyLogMessage() {
for (const auto &def : log_definitions) {
if (textStartsWith(def.prefix) &&
_complete.compare(timestamp_prefix_length + def.prefix.size(), 2,
": ") == 0) {
_text = &def.prefix[0];
_logclass = def.log_class;
_type = def.log_type;
// TODO(sp) Use boost::tokenizer instead of this index fiddling
size_t pos = timestamp_prefix_length + def.prefix.size() + 2;
for (Param par : def.params) {
size_t sep_pos = _complete.find(';', pos);
size_t end_pos =
sep_pos == std::string::npos ? _complete.size() : sep_pos;
assign(par, _complete.substr(pos, end_pos - pos));
pos = sep_pos == std::string::npos ? _complete.size()
: (sep_pos + 1);
}
return;
}
}
_text = &_complete[timestamp_prefix_length];
if (textStartsWith("LOG VERSION: 2.0")) {
_logclass = Class::program;
_type = LogEntryType::log_version;
return;
}
if (textStartsWith("logging initial states") ||
textStartsWith("logging intitial states")) {
_logclass = Class::program;
_type = LogEntryType::log_initial_states;
return;
}
if (textContains("starting...") || textContains("active mode...")) {
_logclass = Class::program;
_type = LogEntryType::core_starting;
return;
}
if (textContains("shutting down...") || textContains("Bailing out") ||
textContains("standby mode...")) {
_logclass = Class::program;
_type = LogEntryType::core_stopping;
return;
}
if (textContains("restarting...")) {
_logclass = Class::program;
_type = LogEntryType::none;
return;
}
_logclass = Class::info;
_type = LogEntryType::none;
}
bool LogEntry::textStartsWith(const std::string &what) {
return _complete.compare(timestamp_prefix_length, what.size(), what) == 0;
}
bool LogEntry::textContains(const std::string &what) {
return _complete.find(what, timestamp_prefix_length) != std::string::npos;
}
// The NotifyHelper class has a long, tragic history: Through a long series of
// commits, it suffered from spelling mistakes like "HOST_NOTIFICATION" or "HOST
// NOTIFICATION" (without a colon), parameter lists not matching the
// corresponding format strings, and last but not least wrong ordering of
// fields. The net result of this tragedy is that due to legacy reasons, we have
// to support parsing an incorrect ordering of "state type" and "command name"
// fields. :-P
void LogEntry::applyWorkarounds() {
if (_logclass != Class::hs_notification || // no need for any workaround
_state_type.empty()) { // extremely broken line
return;
}
if (_state_type == "check-mk-notify") {
// Ooops, we encounter one of our own buggy lines...
std::swap(_state_type, _command_name);
}
if (_state_type.empty()) {
return; // extremely broken line, even after a potential swap
}
_state = _svc_desc.empty()
? static_cast<int>(parseHostState(_state_type))
: static_cast<int>(parseServiceState(_state_type));
}
namespace {
// Ugly: Depending on where we're called, the actual state type can be in
// parentheses at the end, e.g. "ALERTHANDLER (OK)".
std::string extractStateType(const std::string &str) {
if (!str.empty() && str[str.size() - 1] == ')') {
size_t lparen = str.rfind('(');
if (lparen != std::string::npos) {
return str.substr(lparen + 1, str.size() - lparen - 2);
}
}
return str;
}
std::unordered_map<std::string, ServiceState> serviceStateTypes{
// normal states
{"OK", ServiceState::ok},
{"WARNING", ServiceState::warning},
{"CRITICAL", ServiceState::critical},
{"UNKNOWN", ServiceState::unknown},
// states from "... ALERT"/"... NOTIFICATION"
{"RECOVERY", ServiceState::ok}};
std::unordered_map<std::string, HostState> hostStateTypes{
// normal states
{"UP", HostState::up},
{"DOWN", HostState::down},
{"UNREACHABLE", HostState::unreachable},
// states from "... ALERT"/"... NOTIFICATION"
{"RECOVERY", HostState::up},
// states from "... ALERT HANDLER STOPPED" and "(HOST|SERVICE) NOTIFICATION
// (RESULT|PROGRESS)"
{"OK", HostState::up},
{"WARNING", HostState::down},
{"CRITICAL", HostState::unreachable},
{"UNKNOWN", HostState::up}};
} // namespace
ServiceState LogEntry::parseServiceState(const std::string &str) {
auto it = serviceStateTypes.find(extractStateType(str));
return it == serviceStateTypes.end() ? ServiceState::ok : it->second;
}
HostState LogEntry::parseHostState(const std::string &str) {
auto it = hostStateTypes.find(extractStateType(str));
return it == hostStateTypes.end() ? HostState::up : it->second;
}
unsigned LogEntry::updateReferences(MonitoringCore *mc) {
unsigned updated = 0;
if (!_host_name.empty()) {
// Older Nagios headers are not const-correct... :-P
_host = find_host(const_cast<char *>(_host_name.c_str()));
updated++;
}
if (!_svc_desc.empty()) {
// Older Nagios headers are not const-correct... :-P
_service = find_service(const_cast<char *>(_host_name.c_str()),
const_cast<char *>(_svc_desc.c_str()));
updated++;
}
if (!_contact_name.empty()) {
// Older Nagios headers are not const-correct... :-P
_contact = find_contact(const_cast<char *>(_contact_name.c_str()));
updated++;
}
if (!_command_name.empty()) {
_command = mc->find_command(_command_name);
updated++;
}
return updated;
}

166
src/LogEntry.h Normal file
View File

@@ -0,0 +1,166 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef LogEntry_h
#define LogEntry_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <ctime>
#include <string>
#include <vector>
#include "MonitoringCore.h"
#include "nagios.h"
enum class ServiceState { ok = 0, warning = 1, critical = 2, unknown = 3 };
inline double badness(ServiceState state) {
// unknown is effectively between warning and critical
return state == ServiceState::unknown
? (static_cast<double>(ServiceState::warning) +
static_cast<double>(ServiceState::critical)) /
2.0
: static_cast<double>(state);
}
inline bool worse(ServiceState state1, ServiceState state2) {
return badness(state1) > badness(state2);
}
enum class HostState { up = 0, down = 1, unreachable = 2 };
inline double badness(HostState state) {
// unreachable is effectively between up and down
return state == HostState::unreachable
? (static_cast<double>(HostState::up) +
static_cast<double>(HostState::down)) /
2.0
: static_cast<double>(state);
}
inline bool worse(HostState state1, HostState state2) {
return badness(state1) > badness(state2);
}
enum class LogEntryType {
none,
alert_host,
alert_service,
downtime_alert_host,
downtime_alert_service,
state_host,
state_host_initial,
state_service,
state_service_initial,
flapping_host,
flapping_service,
timeperiod_transition,
core_starting,
core_stopping,
log_version,
log_initial_states,
acknowledge_alert_host,
acknowledge_alert_service
};
class LogEntry {
public:
enum class Class {
info = 0, // all messages not in any other class
alert = 1, // alerts: the change service/host state
program = 2, // important programm events (restart, ...)
hs_notification = 3, // host/service notifications
passivecheck = 4, // passive checks
ext_command = 5, // external commands
state = 6, // initial or current states
text = 7, // specific text passages
alert_handlers = 8, // Started and stopped alert handlers
// TODO(sp): This class sets different logclasses on match -> fix this
invalid = 0x7fffffff // never stored
};
static constexpr uint32_t all_classes = 0xffffU;
// TODO(sp): Wrong type, caused by TableLog accessing it via
// OffsetIntColumn, should be size_t
int _lineno; // line number in file
time_t _time;
Class _logclass;
LogEntryType _type;
std::string _complete; // copy of complete unsplit message
const char *_options; // points into _complete after ':'
const char *_text; // points into _complete or into static data
std::string _host_name;
std::string _svc_desc;
std::string _command_name;
std::string _contact_name;
int _state;
std::string _state_type;
int _attempt;
std::string _check_output;
std::string _comment;
host *_host;
service *_service;
contact *_contact;
Command _command;
// NOTE: line gets modified!
LogEntry(MonitoringCore *mc, size_t lineno, std::string line);
unsigned updateReferences(MonitoringCore *mc);
static ServiceState parseServiceState(const std::string &str);
static HostState parseHostState(const std::string &str);
private:
enum class Param {
HostName,
SvcDesc,
CommandName,
ContactName,
HostState,
ServiceState,
State,
StateType,
Attempt,
Comment,
CheckOutput
};
struct LogDef {
std::string prefix;
Class log_class;
LogEntryType log_type;
std::vector<Param> params;
};
static std::vector<LogDef> log_definitions;
bool assign(Param par, const std::string &field);
void applyWorkarounds();
void classifyLogMessage();
bool textStartsWith(const std::string &what);
bool textContains(const std::string &what);
};
#endif // LogEntry_h

252
src/Logfile.cc Normal file
View File

@@ -0,0 +1,252 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
// https://github.com/include-what-you-use/include-what-you-use/issues/166
// IWYU pragma: no_include <ext/alloc_traits.h>
#include "Logfile.h"
#include <fcntl.h>
#include <cstdlib>
#include <sstream>
#include <utility>
#include <vector>
#include "LogCache.h"
#include "LogEntry.h"
#include "Logger.h"
#include "MonitoringCore.h"
#include "Query.h"
#include "Row.h"
#ifdef CMC
#include "cmc.h"
#endif
namespace {
time_t firstTimestampOf(const fs::path &path, Logger *logger) {
std::ifstream is(path, std::ios::binary);
if (!is) {
generic_error ge("cannot open logfile " + path.string());
Informational(logger) << ge;
return 0;
}
char line[12];
is.read(line, sizeof(line));
if (!is) {
return 0; // ignoring. might be empty
}
if (line[0] != '[' || line[11] != ']') {
Informational(logger) << "ignoring logfile '" << path
<< "': does not begin with '[123456789] '";
return 0;
}
line[11] = 0;
return atoi(line + 1);
}
} // namespace
Logfile::Logfile(MonitoringCore *mc, LogCache *logcache, fs::path path,
bool watch)
: _mc(mc)
, _logcache(logcache)
, _path(std::move(path))
, _since(firstTimestampOf(_path, logger()))
, _watch(watch)
, _read_pos{}
, _lineno(0)
#ifdef CMC
, _world(nullptr)
#endif
, _logclasses_read(0) {
}
void Logfile::flush() {
_entries.clear();
_logclasses_read = 0;
}
void Logfile::load(unsigned logclasses) {
unsigned missing_types = logclasses & ~_logclasses_read;
// The current logfile has the _watch flag set to true.
// In that case, if the logfile has grown, we need to
// load the rest of the file, even if no logclasses
// are missing.
if (_watch) {
FILE *file = fopen(_path.c_str(), "r");
if (file == nullptr) {
generic_error ge("cannot open logfile " + _path.string());
Informational(logger()) << ge;
return;
}
// If we read this file for the first time, we initialize
// the current file position to 0
if (_lineno == 0) {
fgetpos(file, &_read_pos);
}
// file might have grown. Read all classes that we already
// have read to the end of the file
if (_logclasses_read != 0U) {
fsetpos(file, &_read_pos); // continue at previous end
loadRange(file, _logclasses_read, logclasses);
fgetpos(file, &_read_pos);
}
if (missing_types != 0U) {
fseek(file, 0, SEEK_SET);
_lineno = 0;
loadRange(file, missing_types, logclasses);
_logclasses_read |= missing_types;
fgetpos(file, &_read_pos); // remember current end of file
}
fclose(file);
} else {
if (missing_types == 0) {
return;
}
FILE *file = fopen(_path.c_str(), "r");
if (file == nullptr) {
generic_error ge("cannot open logfile " + _path.string());
Informational(logger()) << ge;
return;
}
_lineno = 0;
loadRange(file, missing_types, logclasses);
_logclasses_read |= missing_types;
fclose(file);
}
}
void Logfile::loadRange(FILE *file, unsigned missing_types,
unsigned logclasses) {
std::vector<char> linebuffer(65536);
// TODO(sp) We should really use C++ I/O here...
while (fgets(&linebuffer[0], static_cast<int>(linebuffer.size()), file) !=
nullptr) {
if (_lineno >= _mc->maxLinesPerLogFile()) {
Error(logger()) << "more than " << _mc->maxLinesPerLogFile()
<< " lines in " << _path << ", ignoring the rest!";
return;
}
_lineno++;
// remove trailing newline (should be nuked, see above)
for (auto &ch : linebuffer) {
if (ch == '\0' || ch == '\n') {
ch = '\0';
break;
}
}
if (processLogLine(_lineno, &linebuffer[0], missing_types)) {
_logcache->logLineHasBeenAdded(this, logclasses);
}
}
}
long Logfile::freeMessages(unsigned logclasses) {
long freed = 0;
// We have to be careful here: Erasing an element from an associative
// container invalidates the iterator pointing to it. The solution is the
// usual post-increment idiom, see Scott Meyers' "Effective STL", item 9
// ("Choose carefully among erasing options.").
for (auto it = _entries.begin(); it != _entries.end();) {
if (((1U << static_cast<int>(it->second->_logclass)) & logclasses) !=
0U) {
_entries.erase(it++);
freed++;
} else {
++it;
}
}
_logclasses_read &= ~logclasses;
return freed;
}
bool Logfile::processLogLine(size_t lineno, std::string line,
unsigned logclasses) {
auto entry = std::make_unique<LogEntry>(_mc, lineno, std::move(line));
// ignored invalid lines
if (entry->_logclass == LogEntry::Class::invalid) {
return false;
}
if (((1U << static_cast<int>(entry->_logclass)) & logclasses) == 0U) {
return false;
}
uint64_t key = makeKey(entry->_time, entry->_lineno);
if (_entries.find(key) != _entries.end()) {
// this should never happen. The lineno must be unique!
Error(logger()) << "strange duplicate logfile line "
<< entry->_complete;
return false;
}
_entries[key] = std::move(entry);
return true;
}
const logfile_entries_t *Logfile::getEntriesFor(unsigned logclasses) {
// Make sure existing references to objects point to correct world
updateReferences();
// make sure all messages are present
load(logclasses);
return &_entries;
}
bool Logfile::answerQueryReverse(Query *query, time_t since, time_t until,
unsigned logclasses) {
auto entries = getEntriesFor(logclasses);
// TODO(sp) Move the stuff below out of this class. Tricky part: makeKey
auto it = entries->upper_bound(makeKey(until, 999999999));
while (it != entries->begin()) {
--it;
// end found or limit exceeded?
if (it->second->_time < since ||
!query->processDataset(Row(it->second.get()))) {
return false;
}
}
return true;
}
uint64_t Logfile::makeKey(time_t t, size_t lineno) {
return (static_cast<uint64_t>(t) << 32) | static_cast<uint64_t>(lineno);
}
void Logfile::updateReferences() {
#ifdef CMC
// If our references in cached log entries do not point to the currently
// active configuration world, then update all references
if (_world != g_live_world) {
unsigned num = 0;
for (auto &entry : _entries) {
num += entry.second->updateReferences(_mc);
}
Notice(logger()) << "updated " << num << " log cache references of "
<< _path << " to new world.";
_world = g_live_world;
}
#endif
}
Logger *Logfile::logger() const { return _mc->loggerLivestatus(); }

90
src/Logfile.h Normal file
View File

@@ -0,0 +1,90 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef Logfile_h
#define Logfile_h
#include "config.h" // IWYU pragma: keep
#include <cstdint>
#include <cstdio>
#include <ctime>
#include <map>
#include <memory>
#include <string>
#include "FileSystem.h"
class LogCache;
class LogEntry;
class Logger;
class MonitoringCore;
class Query;
#ifdef CMC
class World;
#endif
// key is time_t . lineno
using logfile_entries_t = std::map<uint64_t, std::unique_ptr<LogEntry>>;
class Logfile {
public:
Logfile(MonitoringCore *mc, LogCache *logcache, fs::path path, bool watch);
[[nodiscard]] fs::path path() const { return _path; }
// for tricky protocol between LogCache::logLineHasBeenAdded and this class
void flush();
[[nodiscard]] time_t since() const { return _since; }
[[nodiscard]] unsigned classesRead() const { return _logclasses_read; }
[[nodiscard]] size_t size() const { return _entries.size(); }
long freeMessages(unsigned logclasses);
// for TableStateHistory
const logfile_entries_t *getEntriesFor(unsigned logclasses);
// for TableLog::answerQuery
bool answerQueryReverse(Query *query, time_t since, time_t until,
unsigned logclasses);
private:
MonitoringCore *const _mc;
LogCache *const _logcache;
const fs::path _path;
const time_t _since; // time of first entry
const bool _watch; // true only for current logfile
fpos_t _read_pos; // read until this position
size_t _lineno; // read until this line
logfile_entries_t _entries;
#ifdef CMC
World *_world; // CMC: world our references point into
#endif
unsigned _logclasses_read; // only these types have been read
void load(unsigned logclasses);
void loadRange(FILE *file, unsigned missing_types, unsigned logclasses);
bool processLogLine(size_t lineno, std::string line, unsigned logclasses);
uint64_t makeKey(time_t t, size_t lineno);
void updateReferences();
[[nodiscard]] Logger *logger() const;
};
#endif // Logfile_h

192
src/Logger.cc Normal file
View File

@@ -0,0 +1,192 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#include "Logger.h"
#include <cstddef>
#include <iostream>
#include <utility>
#include "ChronoUtils.h"
// -----------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &os, const LogLevel &c) {
return os << static_cast<int>(c);
}
// -----------------------------------------------------------------------------
void SimpleFormatter::format(std::ostream &os, const LogRecord &record) {
os << FormattedTimePoint(record.getTimePoint()) << //
" [" << record.getLevel() << "] " << record.getMessage();
}
SharedStreamHandler::SharedStreamHandler(std::mutex &mutex, std::ostream &os)
: _mutex(mutex), _os(os) {}
void SharedStreamHandler::publish(const LogRecord &record) {
std::lock_guard<std::mutex> lg(_mutex);
getFormatter()->format(_os, record);
_os << std::endl;
}
StreamHandler::StreamHandler(std::ostream &os)
: SharedStreamHandler(_mutex, os) {}
FileHandler::FileHandler(const std::string &filename) : StreamHandler(_os) {
_os.open(filename, std::ofstream::app);
if (!_os) {
throw generic_error("could not open logfile " + filename);
}
}
// -----------------------------------------------------------------------------
// static
Logger *Logger::getLogger(const std::string &name) {
return LogManager::getLogManager()->getLogger(name);
}
bool Logger::isLoggable(LogLevel level) const { return level <= getLevel(); }
ConcreteLogger::ConcreteLogger(const std::string &name, Logger *parent)
: _name(name)
, _parent(parent)
, _level(LogLevel::debug)
, _handler(name.empty() ? nullptr : new StreamHandler(std::cerr))
, _use_parent_handlers(true) {}
ConcreteLogger::~ConcreteLogger() { delete _handler; }
std::string ConcreteLogger::getName() const { return _name; }
Logger *ConcreteLogger::getParent() const { return _parent; }
LogLevel ConcreteLogger::getLevel() const { return _level; }
void ConcreteLogger::setLevel(LogLevel level) { _level = level; }
Handler *ConcreteLogger::getHandler() const { return _handler; }
void ConcreteLogger::setHandler(std::unique_ptr<Handler> handler) {
delete _handler;
_handler = handler.release();
}
bool ConcreteLogger::getUseParentHandlers() const {
return _use_parent_handlers;
}
void ConcreteLogger::setUseParentHandlers(bool useParentHandlers) {
_use_parent_handlers = useParentHandlers;
}
void ConcreteLogger::emitContext(std::ostream & /*unused*/) const {}
void ConcreteLogger::log(const LogRecord &record) {
if (!isLoggable(record.getLevel())) {
return;
}
for (Logger *logger = this; logger != nullptr;
logger = logger->getParent()) {
if (Handler *handler = logger->getHandler()) {
handler->publish(record);
}
if (!logger->getUseParentHandlers()) {
break;
}
}
}
LoggerDecorator::LoggerDecorator(Logger *logger) : _logger(logger) {}
std::string LoggerDecorator::getName() const { return _logger->getName(); }
Logger *LoggerDecorator::getParent() const { return _logger->getParent(); }
LogLevel LoggerDecorator::getLevel() const { return _logger->getLevel(); }
void LoggerDecorator::setLevel(LogLevel level) { _logger->setLevel(level); }
Handler *LoggerDecorator::getHandler() const { return _logger->getHandler(); }
void LoggerDecorator::setHandler(std::unique_ptr<Handler> handler) {
_logger->setHandler(std::move(handler));
}
bool LoggerDecorator::getUseParentHandlers() const {
return _logger->getUseParentHandlers();
}
void LoggerDecorator::setUseParentHandlers(bool useParentHandlers) {
_logger->setUseParentHandlers(useParentHandlers);
}
void LoggerDecorator::emitContext(std::ostream &os) const {
_logger->emitContext(os);
}
void LoggerDecorator::log(const LogRecord &record) { _logger->log(record); }
void ContextLogger::emitContext(std::ostream &os) const {
_logger->emitContext(os);
_context(os);
}
// -----------------------------------------------------------------------------
Logger *LogManager::getLogger(const std::string &name) {
Logger *current = lookup("", nullptr);
for (size_t pos = 0; pos <= name.size();) {
size_t dot = name.find('.', pos);
if (dot == std::string::npos) {
dot = name.size();
}
if (dot != pos) {
current = lookup(
(current->getName().empty() ? "" : (current->getName() + ".")) +
name.substr(pos, dot - pos),
current);
}
pos = dot + 1;
}
return current;
}
Logger *LogManager::lookup(const std::string &name, Logger *parent) {
std::lock_guard<std::mutex> lg(_mutex);
auto it = _known_loggers.find(name);
if (it == _known_loggers.end()) {
it = _known_loggers
.emplace(name, std::make_unique<ConcreteLogger>(name, parent))
.first;
}
return it->second.get();
}
LogManager LogManager::_global_log_manager;
// -----------------------------------------------------------------------------
std::ostream &operator<<(std::ostream &os, const generic_error &ge) {
return os << ge.what();
}

341
src/Logger.h Normal file
View File

@@ -0,0 +1,341 @@
// +------------------------------------------------------------------+
// | ____ _ _ __ __ _ __ |
// | / ___| |__ ___ ___| | __ | \/ | |/ / |
// | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
// | | |___| | | | __/ (__| < | | | | . \ |
// | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
// | |
// | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
// +------------------------------------------------------------------+
//
// This file is part of Check_MK.
// The official homepage is at http://mathias-kettner.de/check_mk.
//
// check_mk is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation in version 2. check_mk is distributed
// in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
// out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more de-
// tails. You should have received a copy of the GNU General Public
// License along with GNU Make; see the file COPYING. If not, write
// to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02110-1301 USA.
#ifndef Logger_h
#define Logger_h
#include "config.h" // IWYU pragma: keep
#include <atomic>
#include <cerrno>
#include <chrono>
#include <fstream>
#include <functional>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <system_error>
#include <unordered_map>
#include <utility>
// -----------------------------------------------------------------------------
// values must be in sync with config
enum class LogLevel {
emergency = 0,
alert = 1,
critical = 2,
error = 3,
warning = 4,
notice = 5,
informational = 6,
debug = 7
};
std::ostream &operator<<(std::ostream &os, const LogLevel &c);
// -----------------------------------------------------------------------------
class LogRecord {
public:
LogRecord(LogLevel level, std::string message)
: _level(level)
, _message(std::move(message))
, _time_point(std::chrono::system_clock::now()) {}
virtual ~LogRecord() = default;
[[nodiscard]] LogLevel getLevel() const { return _level; }
void setLevel(LogLevel level) { _level = level; }
[[nodiscard]] std::string getMessage() const { return _message; }
void setMessage(const std::string &message) { _message = message; }
[[nodiscard]] std::chrono::system_clock::time_point getTimePoint() const {
return _time_point;
}
void setTimePoint(std::chrono::system_clock::time_point time_point) {
_time_point = time_point;
}
private:
LogLevel _level;
std::string _message;
std::chrono::system_clock::time_point _time_point;
};
// -----------------------------------------------------------------------------
class Formatter {
public:
virtual ~Formatter() = default;
virtual void format(std::ostream &os, const LogRecord &record) = 0;
};
class SimpleFormatter : public Formatter {
friend class Handler;
void format(std::ostream &os, const LogRecord &record) override;
};
// -----------------------------------------------------------------------------
class Handler {
public:
virtual ~Handler() { setFormatter(std::unique_ptr<Formatter>()); }
virtual void publish(const LogRecord &record) = 0;
[[nodiscard]] Formatter *getFormatter() const { return _formatter; }
void setFormatter(std::unique_ptr<Formatter> formatter) {
delete _formatter;
_formatter = formatter.release();
}
protected:
Handler() : _formatter(new SimpleFormatter()) {}
private:
std::atomic<Formatter *> _formatter;
};
class SharedStreamHandler : public Handler {
public:
SharedStreamHandler(std::mutex &mutex, std::ostream &os);
private:
// The mutex protects the _os.
std::mutex &_mutex;
std::ostream &_os;
void publish(const LogRecord &record) override;
};
class StreamHandler : public SharedStreamHandler {
public:
explicit StreamHandler(std::ostream &os);
private:
// The mutex protects the output stream, see SharedStreamHandler.
std::mutex _mutex;
};
class FileHandler : public StreamHandler {
public:
explicit FileHandler(const std::string &filename);
private:
std::ofstream _os;
};
// -----------------------------------------------------------------------------
class Logger {
public:
static Logger *getLogger(const std::string &name);
virtual ~Logger() = default;
[[nodiscard]] bool isLoggable(LogLevel level) const;
[[nodiscard]] virtual std::string getName() const = 0;
[[nodiscard]] virtual Logger *getParent() const = 0;
[[nodiscard]] virtual LogLevel getLevel() const = 0;
virtual void setLevel(LogLevel level) = 0;
[[nodiscard]] virtual Handler *getHandler() const = 0;
virtual void setHandler(std::unique_ptr<Handler> handler) = 0;
[[nodiscard]] virtual bool getUseParentHandlers() const = 0;
virtual void setUseParentHandlers(bool useParentHandlers) = 0;
virtual void emitContext(std::ostream &os) const = 0;
virtual void log(const LogRecord &record) = 0;
};
class ConcreteLogger : public Logger {
public:
ConcreteLogger(const std::string &name, Logger *parent);
~ConcreteLogger() override;
[[nodiscard]] std::string getName() const override;
[[nodiscard]] Logger *getParent() const override;
[[nodiscard]] LogLevel getLevel() const override;
void setLevel(LogLevel level) override;
[[nodiscard]] Handler *getHandler() const override;
void setHandler(std::unique_ptr<Handler> handler) override;
[[nodiscard]] bool getUseParentHandlers() const override;
void setUseParentHandlers(bool useParentHandlers) override;
void emitContext(std::ostream &os) const override;
void log(const LogRecord &record) override;
private:
const std::string _name;
Logger *const _parent;
std::atomic<LogLevel> _level;
std::atomic<Handler *> _handler;
std::atomic<bool> _use_parent_handlers;
};
class LoggerDecorator : public Logger {
public:
explicit LoggerDecorator(Logger *logger);
[[nodiscard]] std::string getName() const override;
[[nodiscard]] Logger *getParent() const override;
[[nodiscard]] LogLevel getLevel() const override;
void setLevel(LogLevel level) override;
[[nodiscard]] Handler *getHandler() const override;
void setHandler(std::unique_ptr<Handler> handler) override;
[[nodiscard]] bool getUseParentHandlers() const override;
void setUseParentHandlers(bool useParentHandlers) override;
void emitContext(std::ostream &os) const override;
void log(const LogRecord &record) override;
protected:
Logger *const _logger;
};
class ContextLogger : public LoggerDecorator {
public:
using ContextEmitter = std::function<void(std::ostream &)>;
ContextLogger(Logger *logger, ContextEmitter context)
: LoggerDecorator(logger), _context(std::move(context)) {}
void emitContext(std::ostream &os) const override;
private:
const ContextEmitter _context;
};
// -----------------------------------------------------------------------------
class LogManager {
public:
static LogManager *getLogManager() { return &_global_log_manager; }
Logger *getLogger(const std::string &name);
private:
static LogManager _global_log_manager;
// The mutex protects _known_loggers.
std::mutex _mutex;
std::unordered_map<std::string, std::unique_ptr<Logger>> _known_loggers;
Logger *lookup(const std::string &name, Logger *parent);
};
// -----------------------------------------------------------------------------
class LogStream {
public:
LogStream(Logger *logger, LogLevel level) : _logger(logger), _level(level) {
// The test and all the similar ones below are just optimizations.
if (_logger->isLoggable(_level)) {
_logger->emitContext(_os);
}
}
virtual ~LogStream() {
if (_logger->isLoggable(_level)) {
_logger->log(LogRecord(_level, _os.str()));
}
}
template <typename T>
std::ostream &operator<<(const T &t) {
return _logger->isLoggable(_level) ? (_os << t) : _os;
}
protected:
Logger *const _logger;
const LogLevel _level;
std::ostringstream _os;
};
// -----------------------------------------------------------------------------
struct Emergency : public LogStream {
explicit Emergency(Logger *logger)
: LogStream(logger, LogLevel::emergency) {}
};
struct Alert : public LogStream {
explicit Alert(Logger *logger) : LogStream(logger, LogLevel::alert) {}
};
struct Critical : public LogStream {
explicit Critical(Logger *logger) : LogStream(logger, LogLevel::critical) {}
};
struct Error : public LogStream {
explicit Error(Logger *logger) : LogStream(logger, LogLevel::error) {}
};
struct Warning : public LogStream {
explicit Warning(Logger *logger) : LogStream(logger, LogLevel::warning) {}
};
struct Notice : public LogStream {
explicit Notice(Logger *logger) : LogStream(logger, LogLevel::notice) {}
};
struct Informational : public LogStream {
explicit Informational(Logger *logger)
: LogStream(logger, LogLevel::informational) {}
};
struct Debug : public LogStream {
explicit Debug(Logger *logger) : LogStream(logger, LogLevel::debug) {}
};
// -----------------------------------------------------------------------------
class generic_error : public std::system_error {
public:
generic_error() : std::system_error(errno, std::generic_category()) {}
explicit generic_error(const char *what_arg)
: std::system_error(errno, std::generic_category(), what_arg) {}
explicit generic_error(const std::string &what_arg)
: std::system_error(errno, std::generic_category(), what_arg) {}
};
std::ostream &operator<<(std::ostream &os, const generic_error &ge);
#endif // Logger_h

Some files were not shown because too many files have changed in this diff Show More