Module: check_mk
Branch: master
Commit: 60264e518261cb654fcd060c39e0a12ac0737a61
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=60264e518261cb…
Author: Mathias Kettner <mk(a)mathias-kettner.de>
Date: Thu Jul 4 16:28:38 2013 +0200
Availability: fix exceptions when no hosts/services are selected
---
livestatus/src/Column.h | 4 ++
livestatus/src/Filter.h | 4 ++
livestatus/src/Query.cc | 4 +-
livestatus/src/Table.cc | 4 +-
livestatus/src/TableStateHistory.cc | 83 ++++++++++++++++++++++++++++++++++-
livestatus/src/TableStateHistory.h | 58 +-----------------------
web/plugins/views/availability.py | 4 ++
7 files changed, 102 insertions(+), 59 deletions(-)
diff --git a/livestatus/src/Column.h b/livestatus/src/Column.h
index 197d427..eba28fe 100644
--- a/livestatus/src/Column.h
+++ b/livestatus/src/Column.h
@@ -40,11 +40,13 @@ using namespace std;
class Filter;
class Query;
+class Table;
class Column
{
string _name;
string _description;
+ Table *_table;
public:
int _indirect_offset;
int _extra_offset;
@@ -61,6 +63,8 @@ public:
virtual Filter *createFilter(int opid __attribute__ ((__unused__)), char *value
__attribute__ ((__unused__))) { return 0; }
void *shiftPointer(void *data);
void setExtraOffset(int o) { _extra_offset = o; }
+ void setTable(Table *t) { _table = t; }
+ Table *table() { return _table; }
};
diff --git a/livestatus/src/Filter.h b/livestatus/src/Filter.h
index 577a78f..d7beef8 100644
--- a/livestatus/src/Filter.h
+++ b/livestatus/src/Filter.h
@@ -33,11 +33,13 @@
using namespace std;
class Query;
+class Table;
class Filter
{
string _error_message; // Error in constructor
unsigned _error_code;
+ Table *_table;
protected:
Query *_query; // needed by TimeOffsetFilter (currently)
@@ -50,6 +52,8 @@ public:
unsigned errorCode() { return _error_code; }
bool hasError() { return _error_message != ""; }
void setQuery(Query *q) { _query = q; }
+ void setTable(Table *t) { _table = t; }
+ Table *table() { return _table; }
virtual bool accepts(void *data) = 0;
virtual void *indexFilter(const char *columnname __attribute__ ((__unused__))) {
return 0; }
virtual void findIntLimits(const char *columnname __attribute__ ((__unused__)), int
*lower __attribute__ ((__unused__)), int *upper __attribute__ ((__unused__))) {}
diff --git a/livestatus/src/Query.cc b/livestatus/src/Query.cc
index cd0521e..0fccb09 100644
--- a/livestatus/src/Query.cc
+++ b/livestatus/src/Query.cc
@@ -247,8 +247,10 @@ Filter *Query::createFilter(Column *column, int operator_id, char
*value)
delete filter;
filter = 0;
}
- else
+ else {
filter->setQuery(this);
+ filter->setTable(column->table());
+ }
return filter;
}
diff --git a/livestatus/src/Table.cc b/livestatus/src/Table.cc
index 8e3d350..a64abb3 100644
--- a/livestatus/src/Table.cc
+++ b/livestatus/src/Table.cc
@@ -38,8 +38,10 @@ void Table::addColumn(Column *col)
if (column(col->name())) {
delete col;
}
- else
+ else {
_columns.insert(make_pair(col->name(), col));
+ col->setTable(this);
+ }
}
diff --git a/livestatus/src/TableStateHistory.cc b/livestatus/src/TableStateHistory.cc
index ce774df..0c6d32d 100644
--- a/livestatus/src/TableStateHistory.cc
+++ b/livestatus/src/TableStateHistory.cc
@@ -49,6 +49,62 @@
#endif
+typedef pair<string, string> HostServiceKey;
+
+struct HostServiceState {
+ bool _is_host;
+ time_t _time;
+ int _lineno;
+ time_t _from;
+ time_t _until;
+
+ time_t _duration;
+ double _duration_part;
+
+ // Do not change order within this block!
+ // These durations will be bzero'd
+ 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_downtime;
+ int _in_host_downtime;
+ int _is_flapping;
+
+
+ // Absent state handling
+ bool _may_no_longer_exist;
+ bool _has_vanished;
+ time_t _last_known_time;
+
+
+ const char *_debug_info;
+ // Pointer to dynamically allocated strings (strdup) that live here.
+ // These pointers are 0, if there is no output (e.g. downtime)
+ char *_log_output;
+ char *_notification_period; // may be "": -> no period known, we
assume "always"
+ host *_host;
+ service *_service;
+ const char *_host_name; // Fallback if host no longer exists
+ const char *_service_description; // Fallback if service no longer exists
+
+ HostServiceState() { bzero(this, sizeof(HostServiceState)); }
+ ~HostServiceState();
+ void debug_me(const char *loginfo, ...);
+};
+
+
#define CHECK_MEM_CYCLE 1000 /* Check memory every N'th new message */
extern Store *g_store;
@@ -203,9 +259,14 @@ void TableStateHistory::answerQuery(Query *query)
g_store->logCache()->lockLogCache();
g_store->logCache()->logCachePreChecks();
+ // Keep track of the historic state of services/hosts here
typedef map<HostServiceKey, HostServiceState*> state_info_t;
state_info_t state_info;
+ // Store hosts/services that we have filtered out here
+ typedef set<HostServiceKey> object_blacklist_t;
+ object_blacklist_t object_blacklist;
+
_query = query;
_since = 0;
_until = time(0) + 1;
@@ -317,9 +378,24 @@ void TableStateHistory::answerQuery(Query *query)
key.first = entry->_host_name;
key.second = entry->_svc_desc != 0 ? entry->_svc_desc : "";
+ if (object_blacklist.find(key) != object_blacklist.end())
+ {
+ // Host/Service is not needed for this query and has already
+ // been filtered out.
+ continue;
+ }
+
+ // Find state object for this host/service
HostServiceState *state;
state_info_t::iterator it_hst = state_info.find(key);
- if (it_hst == state_info.end()) {
+ if (it_hst == state_info.end())
+ {
+ // No state found. Now check if this host/services is filtered out
+ if (objectFilteredOut(entry->_host_name, entry->_svc_desc)) {
+ object_blacklist.insert(key);
+ continue;
+ }
+
state = new HostServiceState();
state_info.insert(std::make_pair(key, state));
@@ -448,6 +524,11 @@ void TableStateHistory::answerQuery(Query *query)
g_store->logCache()->unlockLogCache();
}
+bool TableStateHistory::objectFilteredOut(const char *host_name, const char
*service_description)
+{
+ return true;
+}
+
void TableStateHistory::updateHostServiceState(Query *query, const LogEntry *entry,
HostServiceState *hs_state, const bool only_update){
// Revive host / service if it was unmonitored
if (entry->_type != TIMEPERIOD_TRANSITION && hs_state->_has_vanished)
diff --git a/livestatus/src/TableStateHistory.h b/livestatus/src/TableStateHistory.h
index e7e5bc3..5c0b82e 100644
--- a/livestatus/src/TableStateHistory.h
+++ b/livestatus/src/TableStateHistory.h
@@ -35,62 +35,7 @@
#include "LogCache.h"
#include "Query.h"
-
-typedef pair<string, string> HostServiceKey;
-
-struct HostServiceState {
- bool _is_host;
- time_t _time;
- int _lineno;
- time_t _from;
- time_t _until;
-
- time_t _duration;
- double _duration_part;
-
- // Do not change order within this block!
- // These durations will be bzero'd
- 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_downtime;
- int _in_host_downtime;
- int _is_flapping;
-
-
- // Absent state handling
- bool _may_no_longer_exist;
- bool _has_vanished;
- time_t _last_known_time;
-
-
- const char *_debug_info;
- // Pointer to dynamically allocated strings (strdup) that live here.
- // These pointers are 0, if there is no output (e.g. downtime)
- char *_log_output;
- char *_notification_period; // may be "": -> no period known, we
assume "always"
- host *_host;
- service *_service;
- const char *_host_name; // Fallback if host no longer exists
- const char *_service_description; // Fallback if service no longer exists
-
- HostServiceState() { bzero(this, sizeof(HostServiceState)); }
- ~HostServiceState();
- void debug_me(const char *loginfo, ...);
-};
-
+class HostServiceState;
class TableStateHistory : public Table
{
@@ -123,6 +68,7 @@ private:
LogEntry* getPreviousLogentry();
LogEntry* getNextLogentry();
void process(Query *query, HostServiceState *hs_state);
+ bool objectFilteredOut(const char *host_name, const char *service_description);
};
diff --git a/web/plugins/views/availability.py b/web/plugins/views/availability.py
index 2500d52..e497fca 100644
--- a/web/plugins/views/availability.py
+++ b/web/plugins/views/availability.py
@@ -707,6 +707,10 @@ def history_url_of(site, host, service, from_time, until_time):
return "view.py?" + htmllib.urlencode_vars(history_url_vars)
def render_availability_table(availability, from_time, until_time, range_title, what,
avoptions, render_number):
+ if not availability:
+ html.message(_("No matching hosts/services."))
+ return # No objects
+
# Some columns might be unneeded due to state treatment options
sg = avoptions["state_grouping"]
state_groups = [ sg["warn"], sg["unknown"],
sg["host_down"] ]