1 // +------------------------------------------------------------------+
2 // | ____ _ _ __ __ _ __ |
3 // | / ___| |__ ___ ___| | __ | \/ | |/ / |
4 // | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
5 // | | |___| | | | __/ (__| < | | | | . \ |
6 // | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
7 // | |
8 // | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
10 //
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
13 //
14 // check_mk is free software; you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License as published by
16 // the Free Software Foundation in version 2. check_mk is distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
18 // out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 // PARTICULAR PURPOSE. See the GNU General Public License for more de-
20 // ails. You should have received a copy of the GNU General Public
21 // License along with GNU Make; see the file COPYING. If not, write
22 // to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 // Boston, MA 02110-1301 USA.
24
25 #include "IntColumnFilter.h"
26 #include <stdlib.h>
27 #include <string.h>
28 #include "IntColumn.h"
29 #include "logger.h"
30 #include "opids.h"
31
IntColumnFilter(IntColumn * column,int opid,char * value)32 IntColumnFilter::IntColumnFilter(IntColumn *column, int opid, char *value)
33 : _column(column)
34 , _opid(abs(opid))
35 , _negate(opid < 0)
36 , _ref_string(value) {}
37
38 // overridden by TimeColumnFilter in order to apply timezone
39 // offset from Localtime: header
convertRefValue()40 int32_t IntColumnFilter::convertRefValue() { return atoi(_ref_string.c_str()); }
41
accepts(void * data)42 bool IntColumnFilter::accepts(void *data) {
43 bool pass = true;
44 int32_t act_value = _column->getValue(data, _query);
45 int32_t ref_value = convertRefValue();
46 switch (_opid) {
47 case OP_EQUAL:
48 pass = act_value == ref_value;
49 break;
50 case OP_GREATER:
51 pass = act_value > ref_value;
52 break;
53 case OP_LESS:
54 pass = act_value < ref_value;
55 break;
56 default:
57 logger(LG_INFO, "Sorry. Operator %s for integers not implemented.",
58 op_names_plus_8[_opid]);
59 break;
60 }
61 return pass != _negate;
62 }
63
findIntLimits(const char * columnname,int * lower,int * upper)64 void IntColumnFilter::findIntLimits(const char *columnname, int *lower,
65 int *upper) {
66 if (strcmp(columnname, _column->name()) != 0) {
67 return; // wrong column
68 }
69 if (*lower >= *upper) {
70 return; // already empty interval
71 }
72
73 int32_t ref_value =
74 convertRefValue(); // TimeColumnFilter applies timezone offset here
75
76 /* [lower, upper[ is some interval. This filter might restrict
77 that interval to a smaller interval.
78 */
79 int opref = _opid * (_negate ? -1 : 1);
80 switch (opref) {
81 case OP_EQUAL:
82 if (ref_value >= *lower && ref_value < *upper) {
83 *lower = ref_value;
84 *upper = ref_value + 1;
85 } else {
86 *lower = *upper;
87 }
88 return;
89
90 case -OP_EQUAL:
91 if (ref_value == *lower) {
92 *lower = *lower + 1;
93 } else if (ref_value == *upper - 1) {
94 *upper = *upper - 1;
95 }
96 return;
97
98 case OP_GREATER:
99 if (ref_value >= *lower) {
100 *lower = ref_value + 1;
101 }
102
103 return;
104
105 case OP_LESS:
106 if (ref_value < *upper) {
107 *upper = ref_value;
108 }
109 return;
110
111 case -OP_GREATER: // LESS OR EQUAL
112 if (ref_value < *upper - 1) {
113 *upper = ref_value + 1;
114 }
115 return;
116
117 case -OP_LESS: // GREATER OR EQUAL
118 if (ref_value > *lower) {
119 *lower = ref_value;
120 }
121 return;
122 }
123 }
124
optimizeBitmask(const char * columnname,uint32_t * mask)125 bool IntColumnFilter::optimizeBitmask(const char *columnname, uint32_t *mask) {
126 int32_t ref_value = convertRefValue();
127
128 if (strcmp(columnname, _column->name()) != 0) {
129 return false; // wrong column
130 }
131
132 if (ref_value < 0 || ref_value > 31) {
133 return true; // not optimizable by 32bit bit mask
134 }
135
136 // Our task is to remove those bits from mask that are deselected
137 // by the filter.
138 uint32_t bit = 1 << ref_value;
139
140 int opref = _opid * (_negate ? -1 : 1);
141 switch (opref) {
142 case OP_EQUAL:
143 *mask &= bit; // bit must be set
144 return true;
145
146 case -OP_EQUAL:
147 *mask &= ~bit; // bit must not be set
148 return true;
149
150 case -OP_LESS: // >=
151 bit >>= 1;
152 case OP_GREATER:
153 while (bit != 0u) {
154 *mask &= ~bit;
155 bit >>= 1;
156 }
157 return true;
158
159 case -OP_GREATER: // <=
160 if (ref_value == 31) {
161 return true;
162 }
163 bit <<= 1;
164 case OP_LESS:
165 while (true) {
166 *mask &= ~bit;
167 if (bit == 0x80000000) {
168 return true;
169 }
170 bit <<= 1;
171 }
172 return true;
173 }
174 return false; // should not be reached
175 }
176