1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "lld.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxalgo.h"
24 #include "zbxserver.h"
25 #include "zbxregexp.h"
26
27 typedef struct
28 {
29 zbx_uint64_t itemid;
30 zbx_uint64_t valuemapid;
31 zbx_uint64_t interfaceid;
32 zbx_uint64_t master_itemid;
33 char *name;
34 char *key;
35 char *delay;
36 char *history;
37 char *trends;
38 char *trapper_hosts;
39 char *units;
40 char *formula;
41 char *logtimefmt;
42 char *params;
43 char *ipmi_sensor;
44 char *snmp_community;
45 char *snmp_oid;
46 char *snmpv3_securityname;
47 char *snmpv3_authpassphrase;
48 char *snmpv3_privpassphrase;
49 char *snmpv3_contextname;
50 char *username;
51 char *password;
52 char *publickey;
53 char *privatekey;
54 char *description;
55 char *port;
56 char *jmx_endpoint;
57 char *timeout;
58 char *url;
59 char *query_fields;
60 char *posts;
61 char *status_codes;
62 char *http_proxy;
63 char *headers;
64 char *ssl_cert_file;
65 char *ssl_key_file;
66 char *ssl_key_password;
67 unsigned char verify_peer;
68 unsigned char verify_host;
69 unsigned char follow_redirects;
70 unsigned char post_type;
71 unsigned char retrieve_mode;
72 unsigned char request_method;
73 unsigned char output_format;
74 unsigned char type;
75 unsigned char value_type;
76 unsigned char status;
77 unsigned char snmpv3_securitylevel;
78 unsigned char snmpv3_authprotocol;
79 unsigned char snmpv3_privprotocol;
80 unsigned char authtype;
81 unsigned char allow_traps;
82 zbx_vector_ptr_t lld_rows;
83 zbx_vector_ptr_t applications;
84 zbx_vector_ptr_t preproc_ops;
85 }
86 zbx_lld_item_prototype_t;
87
88 #define ZBX_DEPENDENT_ITEM_MAX_COUNT 999
89 #define ZBX_DEPENDENT_ITEM_MAX_LEVELS 3
90
91 typedef struct
92 {
93 zbx_uint64_t itemid;
94 zbx_uint64_t master_itemid;
95 unsigned char item_flags;
96 }
97 zbx_item_dependence_t;
98
99 typedef struct
100 {
101 zbx_uint64_t itemid;
102 zbx_uint64_t parent_itemid;
103 zbx_uint64_t master_itemid;
104 #define ZBX_FLAG_LLD_ITEM_UNSET __UINT64_C(0x0000000000000000)
105 #define ZBX_FLAG_LLD_ITEM_DISCOVERED __UINT64_C(0x0000000000000001)
106 #define ZBX_FLAG_LLD_ITEM_UPDATE_NAME __UINT64_C(0x0000000000000002)
107 #define ZBX_FLAG_LLD_ITEM_UPDATE_KEY __UINT64_C(0x0000000000000004)
108 #define ZBX_FLAG_LLD_ITEM_UPDATE_TYPE __UINT64_C(0x0000000000000008)
109 #define ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE __UINT64_C(0x0000000000000010)
110 #define ZBX_FLAG_LLD_ITEM_UPDATE_DELAY __UINT64_C(0x0000000000000040)
111 #define ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY __UINT64_C(0x0000000000000100)
112 #define ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS __UINT64_C(0x0000000000000200)
113 #define ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS __UINT64_C(0x0000000000000400)
114 #define ZBX_FLAG_LLD_ITEM_UPDATE_UNITS __UINT64_C(0x0000000000000800)
115 #define ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA __UINT64_C(0x0000000000004000)
116 #define ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT __UINT64_C(0x0000000000008000)
117 #define ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID __UINT64_C(0x0000000000010000)
118 #define ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS __UINT64_C(0x0000000000020000)
119 #define ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR __UINT64_C(0x0000000000040000)
120 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY __UINT64_C(0x0000000000080000)
121 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID __UINT64_C(0x0000000000100000)
122 #define ZBX_FLAG_LLD_ITEM_UPDATE_PORT __UINT64_C(0x0000000000200000)
123 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME __UINT64_C(0x0000000000400000)
124 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL __UINT64_C(0x0000000000800000)
125 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL __UINT64_C(0x0000000001000000)
126 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE __UINT64_C(0x0000000002000000)
127 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL __UINT64_C(0x0000000004000000)
128 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE __UINT64_C(0x0000000008000000)
129 #define ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE __UINT64_C(0x0000000010000000)
130 #define ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME __UINT64_C(0x0000000020000000)
131 #define ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD __UINT64_C(0x0000000040000000)
132 #define ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY __UINT64_C(0x0000000080000000)
133 #define ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY __UINT64_C(0x0000000100000000)
134 #define ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION __UINT64_C(0x0000000200000000)
135 #define ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID __UINT64_C(0x0000000400000000)
136 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME __UINT64_C(0x0000000800000000)
137 #define ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT __UINT64_C(0x0000001000000000)
138 #define ZBX_FLAG_LLD_ITEM_UPDATE_MASTER_ITEM __UINT64_C(0x0000002000000000)
139 #define ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT __UINT64_C(0x0000004000000000)
140 #define ZBX_FLAG_LLD_ITEM_UPDATE_URL __UINT64_C(0x0000008000000000)
141 #define ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS __UINT64_C(0x0000010000000000)
142 #define ZBX_FLAG_LLD_ITEM_UPDATE_POSTS __UINT64_C(0x0000020000000000)
143 #define ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES __UINT64_C(0x0000040000000000)
144 #define ZBX_FLAG_LLD_ITEM_UPDATE_FOLLOW_REDIRECTS __UINT64_C(0x0000080000000000)
145 #define ZBX_FLAG_LLD_ITEM_UPDATE_POST_TYPE __UINT64_C(0x0000100000000000)
146 #define ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY __UINT64_C(0x0000200000000000)
147 #define ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS __UINT64_C(0x0000400000000000)
148 #define ZBX_FLAG_LLD_ITEM_UPDATE_RETRIEVE_MODE __UINT64_C(0x0000800000000000)
149 #define ZBX_FLAG_LLD_ITEM_UPDATE_REQUEST_METHOD __UINT64_C(0x0001000000000000)
150 #define ZBX_FLAG_LLD_ITEM_UPDATE_OUTPUT_FORMAT __UINT64_C(0x0002000000000000)
151 #define ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE __UINT64_C(0x0004000000000000)
152 #define ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE __UINT64_C(0x0008000000000000)
153 #define ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD __UINT64_C(0x0010000000000000)
154 #define ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_PEER __UINT64_C(0x0020000000000000)
155 #define ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_HOST __UINT64_C(0x0040000000000000)
156 #define ZBX_FLAG_LLD_ITEM_UPDATE_ALLOW_TRAPS __UINT64_C(0x0080000000000000)
157 #define ZBX_FLAG_LLD_ITEM_UPDATE (~ZBX_FLAG_LLD_ITEM_DISCOVERED)
158 zbx_uint64_t flags;
159 char *key_proto;
160 char *name;
161 char *name_proto;
162 char *key;
163 char *key_orig;
164 char *delay;
165 char *delay_orig;
166 char *history;
167 char *history_orig;
168 char *trends;
169 char *trends_orig;
170 char *units;
171 char *units_orig;
172 char *params;
173 char *params_orig;
174 char *username;
175 char *username_orig;
176 char *password;
177 char *password_orig;
178 char *ipmi_sensor;
179 char *ipmi_sensor_orig;
180 char *snmp_oid;
181 char *snmp_oid_orig;
182 char *description;
183 char *description_orig;
184 char *jmx_endpoint;
185 char *jmx_endpoint_orig;
186 char *timeout;
187 char *timeout_orig;
188 char *url;
189 char *url_orig;
190 char *query_fields;
191 char *query_fields_orig;
192 char *posts;
193 char *posts_orig;
194 char *status_codes;
195 char *status_codes_orig;
196 char *http_proxy;
197 char *http_proxy_orig;
198 char *headers;
199 char *headers_orig;
200 char *ssl_cert_file;
201 char *ssl_cert_file_orig;
202 char *ssl_key_file;
203 char *ssl_key_file_orig;
204 char *ssl_key_password;
205 char *ssl_key_password_orig;
206 int lastcheck;
207 int ts_delete;
208 const zbx_lld_row_t *lld_row;
209 zbx_vector_ptr_t preproc_ops;
210 zbx_vector_ptr_t dependent_items;
211 unsigned char type;
212 }
213 zbx_lld_item_t;
214
215 typedef struct
216 {
217 zbx_uint64_t item_preprocid;
218 int step;
219 int type;
220 char *params;
221
222 #define ZBX_FLAG_LLD_ITEM_PREPROC_UNSET __UINT64_C(0x00)
223 #define ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED __UINT64_C(0x01)
224 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE __UINT64_C(0x02)
225 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS __UINT64_C(0x04)
226 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP __UINT64_C(0x08)
227 #define ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE \
228 (ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE | ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS | \
229 ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP)
230 #define ZBX_FLAG_LLD_ITEM_PREPROC_DELETE __UINT64_C(0x08)
231 zbx_uint64_t flags;
232 }
233 zbx_lld_item_preproc_t;
234
235 /* item index by prototype (parent) id and lld row */
236 typedef struct
237 {
238 zbx_uint64_t parent_itemid;
239 zbx_lld_row_t *lld_row;
240 zbx_lld_item_t *item;
241 }
242 zbx_lld_item_index_t;
243
244 typedef struct
245 {
246 zbx_uint64_t application_prototypeid;
247 zbx_uint64_t itemid;
248 char *name;
249 }
250 zbx_lld_application_prototype_t;
251
252 typedef struct
253 {
254 zbx_uint64_t applicationid;
255 zbx_uint64_t application_prototypeid;
256 zbx_uint64_t application_discoveryid;
257 int lastcheck;
258 int ts_delete;
259 #define ZBX_FLAG_LLD_APPLICATION_UNSET __UINT64_C(0x0000000000000000)
260 #define ZBX_FLAG_LLD_APPLICATION_DISCOVERED __UINT64_C(0x0000000000000001)
261 #define ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME __UINT64_C(0x0000000000000002)
262 #define ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY __UINT64_C(0x0000000100000000)
263 #define ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY __UINT64_C(0x0000000200000000)
264 #define ZBX_FLAG_LLD_APPLICATION_REMOVE __UINT64_C(0x0000000400000000)
265 zbx_uint64_t flags;
266 char *name;
267 char *name_proto;
268 char *name_orig;
269 const zbx_lld_row_t *lld_row;
270 }
271 zbx_lld_application_t;
272
273 /* reference to an item either by its id (existing items) or structure (new items) */
274 typedef struct
275 {
276 zbx_uint64_t itemid;
277 zbx_lld_item_t *item;
278 }
279 zbx_lld_item_ref_t;
280
281 /* reference to an application either by its id (existing applications) or structure (new applications) */
282 typedef struct
283 {
284 zbx_uint64_t applicationid;
285 zbx_lld_application_t *application;
286 }
287 zbx_lld_application_ref_t;
288
289 /* item prototype-application link reference by application id (existing applications) */
290 /* or application prototype structure (application prototypes) */
291 typedef struct
292 {
293 zbx_lld_application_prototype_t *application_prototype;
294 zbx_uint64_t applicationid;
295 }
296 zbx_lld_item_application_ref_t;
297
298 /* item-application link */
299 typedef struct
300 {
301 zbx_uint64_t itemappid;
302 zbx_lld_item_ref_t item_ref;
303 zbx_lld_application_ref_t application_ref;
304 #define ZBX_FLAG_LLD_ITEM_APPLICATION_UNSET __UINT64_C(0x0000000000000000)
305 #define ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED __UINT64_C(0x0000000000000001)
306 zbx_uint64_t flags;
307 }
308 zbx_lld_item_application_t;
309
310 /* application index by prototypeid and lld row */
311 typedef struct
312 {
313 zbx_uint64_t application_prototypeid;
314 const zbx_lld_row_t *lld_row;
315 zbx_lld_application_t *application;
316 }
317 zbx_lld_application_index_t;
318
319 /* items index hashset support functions */
lld_item_index_hash_func(const void * data)320 static zbx_hash_t lld_item_index_hash_func(const void *data)
321 {
322 zbx_lld_item_index_t *item_index = (zbx_lld_item_index_t *)data;
323 zbx_hash_t hash;
324
325 hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&item_index->parent_itemid,
326 sizeof(item_index->parent_itemid), ZBX_DEFAULT_HASH_SEED);
327 return ZBX_DEFAULT_PTR_HASH_ALGO(&item_index->lld_row, sizeof(item_index->lld_row), hash);
328 }
329
lld_item_index_compare_func(const void * d1,const void * d2)330 static int lld_item_index_compare_func(const void *d1, const void *d2)
331 {
332 zbx_lld_item_index_t *i1 = (zbx_lld_item_index_t *)d1;
333 zbx_lld_item_index_t *i2 = (zbx_lld_item_index_t *)d2;
334
335 ZBX_RETURN_IF_NOT_EQUAL(i1->parent_itemid, i2->parent_itemid);
336 ZBX_RETURN_IF_NOT_EQUAL(i1->lld_row, i2->lld_row);
337
338 return 0;
339 }
340
341 /* application index hashset support functions */
lld_application_index_hash_func(const void * data)342 static zbx_hash_t lld_application_index_hash_func(const void *data)
343 {
344 zbx_lld_application_index_t *application_index = (zbx_lld_application_index_t *)data;
345 zbx_hash_t hash;
346
347 hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&application_index->application_prototypeid,
348 sizeof(application_index->application_prototypeid), ZBX_DEFAULT_HASH_SEED);
349 return ZBX_DEFAULT_PTR_HASH_ALGO(&application_index->lld_row, sizeof(application_index->lld_row), hash);
350 }
351
lld_application_index_compare_func(const void * d1,const void * d2)352 static int lld_application_index_compare_func(const void *d1, const void *d2)
353 {
354 zbx_lld_application_index_t *i1 = (zbx_lld_application_index_t *)d1;
355 zbx_lld_application_index_t *i2 = (zbx_lld_application_index_t *)d2;
356
357 ZBX_RETURN_IF_NOT_EQUAL(i1->application_prototypeid, i2->application_prototypeid);
358 ZBX_RETURN_IF_NOT_EQUAL(i1->lld_row, i2->lld_row);
359
360 return 0;
361 }
362
363 /* comparison function for discovered application lookup by name */
lld_application_compare_name(const void * d1,const void * d2)364 static int lld_application_compare_name(const void *d1, const void *d2)
365 {
366 const zbx_lld_application_t *a1 = *(zbx_lld_application_t **)d1;
367 const zbx_lld_application_t *a2 = *(zbx_lld_application_t **)d2;
368
369 if (0 == (a1->flags & a2->flags))
370 return -1;
371
372 if (NULL == a1->name || NULL == a2->name)
373 return -1;
374
375 return strcmp(a1->name, a2->name);
376 }
377
378 /* comparison function for discovered application lookup by original name name */
lld_application_compare_name_orig(const void * d1,const void * d2)379 static int lld_application_compare_name_orig(const void *d1, const void *d2)
380 {
381 const zbx_lld_application_t *a1 = *(zbx_lld_application_t **)d1;
382 const zbx_lld_application_t *a2 = *(zbx_lld_application_t **)d2;
383
384 if (0 == (a1->flags & a2->flags))
385 return -1;
386
387 if (NULL == a1->name_orig || NULL == a2->name_orig)
388 return -1;
389
390 return strcmp(a1->name_orig, a2->name_orig);
391 }
392
393 /* string pointer hashset (used to check for duplicate item keys) support functions */
lld_items_keys_hash_func(const void * data)394 static zbx_hash_t lld_items_keys_hash_func(const void *data)
395 {
396 return ZBX_DEFAULT_STRING_HASH_FUNC(*(char **)data);
397 }
398
lld_items_keys_compare_func(const void * d1,const void * d2)399 static int lld_items_keys_compare_func(const void *d1, const void *d2)
400 {
401 return ZBX_DEFAULT_STR_COMPARE_FUNC(d1, d2);
402 }
403
404 /* items - applications hashset support */
lld_item_application_hash_func(const void * data)405 static zbx_hash_t lld_item_application_hash_func(const void *data)
406 {
407 const zbx_lld_item_application_t *item_application = (zbx_lld_item_application_t *)data;
408 zbx_hash_t hash;
409
410 hash = ZBX_DEFAULT_HASH_ALGO(&item_application->item_ref.itemid, sizeof(item_application->item_ref.itemid),
411 ZBX_DEFAULT_HASH_SEED);
412 hash = ZBX_DEFAULT_HASH_ALGO(&item_application->item_ref.item, sizeof(item_application->item_ref.item), hash);
413
414 hash = ZBX_DEFAULT_HASH_ALGO(&item_application->application_ref.applicationid,
415 sizeof(item_application->application_ref.applicationid), hash);
416 return ZBX_DEFAULT_HASH_ALGO(&item_application->application_ref.application,
417 sizeof(item_application->application_ref.application), hash);
418 }
419
lld_item_application_compare_func(const void * d1,const void * d2)420 static int lld_item_application_compare_func(const void *d1, const void *d2)
421 {
422 const zbx_lld_item_application_t *ia1 = (zbx_lld_item_application_t *)d1;
423 const zbx_lld_item_application_t *ia2 = (zbx_lld_item_application_t *)d2;
424
425 ZBX_RETURN_IF_NOT_EQUAL(ia1->item_ref.itemid, ia2->item_ref.itemid);
426 ZBX_RETURN_IF_NOT_EQUAL(ia1->item_ref.item, ia2->item_ref.item);
427 ZBX_RETURN_IF_NOT_EQUAL(ia1->application_ref.applicationid, ia2->application_ref.applicationid);
428 ZBX_RETURN_IF_NOT_EQUAL(ia1->application_ref.application, ia2->application_ref.application);
429
430 return 0;
431 }
432
lld_item_preproc_sort_by_step(const void * d1,const void * d2)433 static int lld_item_preproc_sort_by_step(const void *d1, const void *d2)
434 {
435 zbx_lld_item_preproc_t *op1 = *(zbx_lld_item_preproc_t **)d1;
436 zbx_lld_item_preproc_t *op2 = *(zbx_lld_item_preproc_t **)d2;
437
438 ZBX_RETURN_IF_NOT_EQUAL(op1->step, op2->step);
439 return 0;
440 }
441
lld_application_prototype_free(zbx_lld_application_prototype_t * application_prototype)442 static void lld_application_prototype_free(zbx_lld_application_prototype_t *application_prototype)
443 {
444 zbx_free(application_prototype->name);
445 zbx_free(application_prototype);
446 }
447
lld_application_free(zbx_lld_application_t * application)448 static void lld_application_free(zbx_lld_application_t *application)
449 {
450 zbx_free(application->name_orig);
451 zbx_free(application->name_proto);
452 zbx_free(application->name);
453 zbx_free(application);
454 }
455
lld_item_preproc_free(zbx_lld_item_preproc_t * op)456 static void lld_item_preproc_free(zbx_lld_item_preproc_t *op)
457 {
458 zbx_free(op->params);
459 zbx_free(op);
460 }
461
lld_item_prototype_free(zbx_lld_item_prototype_t * item_prototype)462 static void lld_item_prototype_free(zbx_lld_item_prototype_t *item_prototype)
463 {
464 zbx_free(item_prototype->name);
465 zbx_free(item_prototype->key);
466 zbx_free(item_prototype->delay);
467 zbx_free(item_prototype->history);
468 zbx_free(item_prototype->trends);
469 zbx_free(item_prototype->trapper_hosts);
470 zbx_free(item_prototype->units);
471 zbx_free(item_prototype->formula);
472 zbx_free(item_prototype->logtimefmt);
473 zbx_free(item_prototype->params);
474 zbx_free(item_prototype->ipmi_sensor);
475 zbx_free(item_prototype->snmp_community);
476 zbx_free(item_prototype->snmp_oid);
477 zbx_free(item_prototype->snmpv3_securityname);
478 zbx_free(item_prototype->snmpv3_authpassphrase);
479 zbx_free(item_prototype->snmpv3_privpassphrase);
480 zbx_free(item_prototype->snmpv3_contextname);
481 zbx_free(item_prototype->username);
482 zbx_free(item_prototype->password);
483 zbx_free(item_prototype->publickey);
484 zbx_free(item_prototype->privatekey);
485 zbx_free(item_prototype->description);
486 zbx_free(item_prototype->port);
487 zbx_free(item_prototype->jmx_endpoint);
488 zbx_free(item_prototype->timeout);
489 zbx_free(item_prototype->url);
490 zbx_free(item_prototype->query_fields);
491 zbx_free(item_prototype->posts);
492 zbx_free(item_prototype->status_codes);
493 zbx_free(item_prototype->http_proxy);
494 zbx_free(item_prototype->headers);
495 zbx_free(item_prototype->ssl_cert_file);
496 zbx_free(item_prototype->ssl_key_file);
497 zbx_free(item_prototype->ssl_key_password);
498
499 zbx_vector_ptr_destroy(&item_prototype->lld_rows);
500
501 zbx_vector_ptr_clear_ext(&item_prototype->applications, zbx_default_mem_free_func);
502 zbx_vector_ptr_destroy(&item_prototype->applications);
503
504 zbx_vector_ptr_clear_ext(&item_prototype->preproc_ops, (zbx_clean_func_t)lld_item_preproc_free);
505 zbx_vector_ptr_destroy(&item_prototype->preproc_ops);
506
507 zbx_free(item_prototype);
508 }
509
lld_item_free(zbx_lld_item_t * item)510 static void lld_item_free(zbx_lld_item_t *item)
511 {
512 zbx_free(item->key_proto);
513 zbx_free(item->name);
514 zbx_free(item->name_proto);
515 zbx_free(item->key);
516 zbx_free(item->key_orig);
517 zbx_free(item->delay);
518 zbx_free(item->delay_orig);
519 zbx_free(item->history);
520 zbx_free(item->history_orig);
521 zbx_free(item->trends);
522 zbx_free(item->trends_orig);
523 zbx_free(item->units);
524 zbx_free(item->units_orig);
525 zbx_free(item->params);
526 zbx_free(item->params_orig);
527 zbx_free(item->ipmi_sensor);
528 zbx_free(item->ipmi_sensor_orig);
529 zbx_free(item->snmp_oid);
530 zbx_free(item->snmp_oid_orig);
531 zbx_free(item->username);
532 zbx_free(item->username_orig);
533 zbx_free(item->password);
534 zbx_free(item->password_orig);
535 zbx_free(item->description);
536 zbx_free(item->description_orig);
537 zbx_free(item->jmx_endpoint);
538 zbx_free(item->jmx_endpoint_orig);
539 zbx_free(item->timeout);
540 zbx_free(item->timeout_orig);
541 zbx_free(item->url);
542 zbx_free(item->url_orig);
543 zbx_free(item->query_fields);
544 zbx_free(item->query_fields_orig);
545 zbx_free(item->posts);
546 zbx_free(item->posts_orig);
547 zbx_free(item->status_codes);
548 zbx_free(item->status_codes_orig);
549 zbx_free(item->http_proxy);
550 zbx_free(item->http_proxy_orig);
551 zbx_free(item->headers);
552 zbx_free(item->headers_orig);
553 zbx_free(item->ssl_cert_file);
554 zbx_free(item->ssl_cert_file_orig);
555 zbx_free(item->ssl_key_file);
556 zbx_free(item->ssl_key_file_orig);
557 zbx_free(item->ssl_key_password);
558 zbx_free(item->ssl_key_password_orig);
559
560 zbx_vector_ptr_clear_ext(&item->preproc_ops, (zbx_clean_func_t)lld_item_preproc_free);
561 zbx_vector_ptr_destroy(&item->preproc_ops);
562 zbx_vector_ptr_destroy(&item->dependent_items);
563
564 zbx_free(item);
565 }
566
567 /******************************************************************************
568 * *
569 * Function: lld_items_get *
570 * *
571 * Purpose: retrieves existing items for the specified item prototypes *
572 * *
573 * Parameters: item_prototypes - [IN] item prototypes *
574 * items - [OUT] list of items *
575 * *
576 ******************************************************************************/
lld_items_get(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items)577 static void lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items)
578 {
579 const char *__function_name = "lld_items_get";
580
581 DB_RESULT result;
582 DB_ROW row;
583 zbx_lld_item_t *item, *master;
584 zbx_lld_item_preproc_t *preproc_op;
585 const zbx_lld_item_prototype_t *item_prototype;
586 zbx_uint64_t db_valuemapid, db_interfaceid, itemid, master_itemid;
587 zbx_vector_uint64_t parent_itemids;
588 int i, index;
589 char *sql = NULL;
590 size_t sql_alloc = 0, sql_offset = 0;
591
592 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
593
594 zbx_vector_uint64_create(&parent_itemids);
595 zbx_vector_uint64_reserve(&parent_itemids, item_prototypes->values_num);
596
597 for (i = 0; i < item_prototypes->values_num; i++)
598 {
599 item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[i];
600
601 zbx_vector_uint64_append(&parent_itemids, item_prototype->itemid);
602 }
603
604 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
605 "select id.itemid,id.key_,id.lastcheck,id.ts_delete,i.name,i.key_,i.type,i.value_type,"
606 "i.delay,i.history,i.trends,i.trapper_hosts,i.units,"
607 "i.formula,i.logtimefmt,i.valuemapid,i.params,i.ipmi_sensor,"
608 "i.snmp_community,i.snmp_oid,i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,"
609 "i.snmpv3_authprotocol,i.snmpv3_authpassphrase,i.snmpv3_privprotocol,"
610 "i.snmpv3_privpassphrase,i.authtype,i.username,i.password,i.publickey,i.privatekey,"
611 "i.description,i.interfaceid,i.snmpv3_contextname,i.jmx_endpoint,i.master_itemid,"
612 "i.timeout,i.url,i.query_fields,i.posts,i.status_codes,i.follow_redirects,i.post_type,"
613 "i.http_proxy,i.headers,i.retrieve_mode,i.request_method,i.output_format,"
614 "i.ssl_cert_file,i.ssl_key_file,i.ssl_key_password,i.verify_peer,i.verify_host,"
615 "id.parent_itemid,i.allow_traps"
616 " from item_discovery id"
617 " join items i"
618 " on id.itemid=i.itemid"
619 " where");
620
621 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "id.parent_itemid", parent_itemids.values,
622 parent_itemids.values_num);
623
624 result = DBselect("%s", sql);
625
626 while (NULL != (row = DBfetch(result)))
627 {
628 ZBX_STR2UINT64(itemid, row[54]);
629
630 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &itemid,
631 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
632 {
633 THIS_SHOULD_NEVER_HAPPEN;
634 continue;
635 }
636
637 item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[index];
638
639 item = (zbx_lld_item_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_t));
640
641 ZBX_STR2UINT64(item->itemid, row[0]);
642 item->parent_itemid = itemid;
643 item->key_proto = zbx_strdup(NULL, row[1]);
644 item->lastcheck = atoi(row[2]);
645 item->ts_delete = atoi(row[3]);
646 item->name = zbx_strdup(NULL, row[4]);
647 item->name_proto = NULL;
648 item->key = zbx_strdup(NULL, row[5]);
649 item->key_orig = NULL;
650 item->flags = ZBX_FLAG_LLD_ITEM_UNSET;
651
652 item->type = item_prototype->type;
653 if ((unsigned char)atoi(row[6]) != item_prototype->type)
654 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TYPE;
655
656 if ((unsigned char)atoi(row[7]) != item_prototype->value_type)
657 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE;
658
659 item->delay = zbx_strdup(NULL, row[8]);
660 item->delay_orig = NULL;
661
662 item->history = zbx_strdup(NULL, row[9]);
663 item->history_orig = NULL;
664
665 item->trends = zbx_strdup(NULL, row[10]);
666 item->trends_orig = NULL;
667
668 if (0 != strcmp(row[11], item_prototype->trapper_hosts))
669 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS;
670
671 item->units = zbx_strdup(NULL, row[12]);
672 item->units_orig = NULL;
673
674 if (0 != strcmp(row[13], item_prototype->formula))
675 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA;
676
677 if (0 != strcmp(row[14], item_prototype->logtimefmt))
678 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT;
679
680 ZBX_DBROW2UINT64(db_valuemapid, row[15]);
681 if (db_valuemapid != item_prototype->valuemapid)
682 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID;
683
684 item->params = zbx_strdup(NULL, row[16]);
685 item->params_orig = NULL;
686
687 item->ipmi_sensor = zbx_strdup(NULL, row[17]);
688 item->ipmi_sensor_orig = NULL;
689
690 if (0 != strcmp(row[18], item_prototype->snmp_community))
691 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY;
692
693 item->snmp_oid = zbx_strdup(NULL, row[19]);
694 item->snmp_oid_orig = NULL;
695
696 if (0 != strcmp(row[20], item_prototype->port))
697 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PORT;
698
699 if (0 != strcmp(row[21], item_prototype->snmpv3_securityname))
700 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME;
701
702 if ((unsigned char)atoi(row[22]) != item_prototype->snmpv3_securitylevel)
703 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL;
704
705 if ((unsigned char)atoi(row[23]) != item_prototype->snmpv3_authprotocol)
706 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL;
707
708 if (0 != strcmp(row[24], item_prototype->snmpv3_authpassphrase))
709 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE;
710
711 if ((unsigned char)atoi(row[25]) != item_prototype->snmpv3_privprotocol)
712 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL;
713
714 if (0 != strcmp(row[26], item_prototype->snmpv3_privpassphrase))
715 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE;
716
717 if ((unsigned char)atoi(row[27]) != item_prototype->authtype)
718 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE;
719
720 item->username = zbx_strdup(NULL, row[28]);
721 item->username_orig = NULL;
722
723 item->password = zbx_strdup(NULL, row[29]);
724 item->password_orig = NULL;
725
726 if (0 != strcmp(row[30], item_prototype->publickey))
727 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY;
728
729 if (0 != strcmp(row[31], item_prototype->privatekey))
730 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY;
731
732 item->description = zbx_strdup(NULL, row[32]);
733 item->description_orig = NULL;
734
735 ZBX_DBROW2UINT64(db_interfaceid, row[33]);
736 if (db_interfaceid != item_prototype->interfaceid)
737 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID;
738
739 if (0 != strcmp(row[34], item_prototype->snmpv3_contextname))
740 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME;
741
742 item->jmx_endpoint = zbx_strdup(NULL, row[35]);
743 item->jmx_endpoint_orig = NULL;
744
745 ZBX_DBROW2UINT64(item->master_itemid, row[36]);
746
747 item->timeout = zbx_strdup(NULL, row[37]);
748 item->timeout_orig = NULL;
749
750 item->url = zbx_strdup(NULL, row[38]);
751 item->url_orig = NULL;
752
753 item->query_fields = zbx_strdup(NULL, row[39]);
754 item->query_fields_orig = NULL;
755
756 item->posts = zbx_strdup(NULL, row[40]);
757 item->posts_orig = NULL;
758
759 item->status_codes = zbx_strdup(NULL, row[41]);
760 item->status_codes_orig = NULL;
761
762 if ((unsigned char)atoi(row[42]) != item_prototype->follow_redirects)
763 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_FOLLOW_REDIRECTS;
764
765 if ((unsigned char)atoi(row[43]) != item_prototype->post_type)
766 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_POST_TYPE;
767
768 item->http_proxy = zbx_strdup(NULL, row[44]);
769 item->http_proxy_orig = NULL;
770
771 item->headers = zbx_strdup(NULL, row[45]);
772 item->headers_orig = NULL;
773
774 if ((unsigned char)atoi(row[46]) != item_prototype->retrieve_mode)
775 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_RETRIEVE_MODE;
776
777 if ((unsigned char)atoi(row[47]) != item_prototype->request_method)
778 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_REQUEST_METHOD;
779
780 if ((unsigned char)atoi(row[48]) != item_prototype->output_format)
781 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_OUTPUT_FORMAT;
782
783 item->ssl_cert_file = zbx_strdup(NULL, row[49]);
784 item->ssl_cert_file_orig = NULL;
785
786 item->ssl_key_file = zbx_strdup(NULL, row[50]);
787 item->ssl_key_file_orig = NULL;
788
789 item->ssl_key_password = zbx_strdup(NULL, row[51]);
790 item->ssl_key_password_orig = NULL;
791
792 if ((unsigned char)atoi(row[52]) != item_prototype->verify_peer)
793 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_PEER;
794
795 if ((unsigned char)atoi(row[53]) != item_prototype->verify_host)
796 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_HOST;
797
798 if ((unsigned char)atoi(row[55]) != item_prototype->allow_traps)
799 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_ALLOW_TRAPS;
800
801 item->lld_row = NULL;
802
803 zbx_vector_ptr_create(&item->preproc_ops);
804 zbx_vector_ptr_create(&item->dependent_items);
805
806 zbx_vector_ptr_append(items, item);
807 }
808 DBfree_result(result);
809
810 zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
811
812 if (0 == items->values_num)
813 goto out;
814
815 for (i = items->values_num - 1; i >= 0; i--)
816 {
817 item = (zbx_lld_item_t *)items->values[i];
818 master_itemid = item->master_itemid;
819
820 if (0 != master_itemid && FAIL != (index = zbx_vector_ptr_bsearch(items, &master_itemid,
821 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
822 {
823 /* dependent items based on prototypes should contain prototype itemid */
824 master = (zbx_lld_item_t *)items->values[index];
825 master_itemid = master->parent_itemid;
826 }
827
828 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
829 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
830 {
831 THIS_SHOULD_NEVER_HAPPEN;
832 continue;
833 }
834
835 item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[index];
836
837 if (master_itemid != item_prototype->master_itemid)
838 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_MASTER_ITEM;
839
840 item->master_itemid = item_prototype->master_itemid;
841 }
842
843 sql_offset = 0;
844 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
845 "select ip.item_preprocid,ip.itemid,ip.step,ip.type,ip.params"
846 " from item_discovery id"
847 " join item_preproc ip"
848 " on id.itemid=ip.itemid"
849 " where");
850
851 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "id.parent_itemid", parent_itemids.values,
852 parent_itemids.values_num);
853
854 result = DBselect("%s", sql);
855
856 while (NULL != (row = DBfetch(result)))
857 {
858 ZBX_STR2UINT64(itemid, row[1]);
859
860 if (FAIL == (index = zbx_vector_ptr_bsearch(items, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
861 {
862 THIS_SHOULD_NEVER_HAPPEN;
863 continue;
864 }
865
866 item = (zbx_lld_item_t *)items->values[index];
867
868 preproc_op = (zbx_lld_item_preproc_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_preproc_t));
869 preproc_op->flags = ZBX_FLAG_LLD_ITEM_PREPROC_UNSET;
870 ZBX_STR2UINT64(preproc_op->item_preprocid, row[0]);
871 preproc_op->step = atoi(row[2]);
872 preproc_op->type = atoi(row[3]);
873 preproc_op->params = zbx_strdup(NULL, row[4]);
874 zbx_vector_ptr_append(&item->preproc_ops, preproc_op);
875 }
876 DBfree_result(result);
877 out:
878 zbx_free(sql);
879 zbx_vector_uint64_destroy(&parent_itemids);
880
881 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
882 }
883
884 /******************************************************************************
885 * *
886 * Function: is_user_macro *
887 * *
888 * Purpose: checks if string is user macro *
889 * *
890 * Parameters: str - [IN] string to validate *
891 * *
892 * Returns: SUCCEED - either "{$MACRO}" or "{$MACRO:"{#MACRO}"}" *
893 * FAIL - not user macro or contains other characters for example:*
894 * "dummy{$MACRO}", "{$MACRO}dummy" or "{$MACRO}{$MACRO}" *
895 * *
896 ******************************************************************************/
is_user_macro(const char * str)897 static int is_user_macro(const char *str)
898 {
899 zbx_token_t token;
900
901 if (FAIL == zbx_token_find(str, 0, &token, ZBX_TOKEN_SEARCH_BASIC) ||
902 0 == (token.type & ZBX_TOKEN_USER_MACRO) ||
903 0 != token.loc.l || '\0' != str[token.loc.r + 1])
904 {
905 return FAIL;
906 }
907
908 return SUCCEED;
909 }
910
911 /******************************************************************************
912 * *
913 * Function: lld_validate_item_field *
914 * *
915 ******************************************************************************/
lld_validate_item_field(zbx_lld_item_t * item,char ** field,char ** field_orig,zbx_uint64_t flag,size_t field_len,char ** error)916 static void lld_validate_item_field(zbx_lld_item_t *item, char **field, char **field_orig, zbx_uint64_t flag,
917 size_t field_len, char **error)
918 {
919 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
920 return;
921
922 /* only new items or items with changed data or item type will be validated */
923 if (0 != item->itemid && 0 == (item->flags & flag) && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE))
924 return;
925
926 if (SUCCEED != zbx_is_utf8(*field))
927 {
928 zbx_replace_invalid_utf8(*field);
929 *error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" has invalid UTF-8 sequence.\n",
930 (0 != item->itemid ? "update" : "create"), *field);
931 }
932 else if (zbx_strlen_utf8(*field) > field_len)
933 {
934 *error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" is too long.\n",
935 (0 != item->itemid ? "update" : "create"), *field);
936 }
937 else
938 {
939 int value;
940 char *errmsg = NULL;
941
942 switch (flag)
943 {
944 case ZBX_FLAG_LLD_ITEM_UPDATE_NAME:
945 if ('\0' != **field)
946 return;
947
948 *error = zbx_strdcatf(*error, "Cannot %s item: name is empty.\n",
949 (0 != item->itemid ? "update" : "create"));
950 break;
951 case ZBX_FLAG_LLD_ITEM_UPDATE_DELAY:
952 switch (item->type)
953 {
954 case ITEM_TYPE_TRAPPER:
955 case ITEM_TYPE_SNMPTRAP:
956 case ITEM_TYPE_DEPENDENT:
957 return;
958 }
959
960 if (SUCCEED == zbx_validate_interval(*field, &errmsg))
961 return;
962
963 *error = zbx_strdcatf(*error, "Cannot %s item: %s\n",
964 (0 != item->itemid ? "update" : "create"), errmsg);
965 zbx_free(errmsg);
966
967 /* delay alone cannot be rolled back as it depends on item type, revert all updates */
968 if (0 != item->itemid)
969 {
970 item->flags &= ZBX_FLAG_LLD_ITEM_DISCOVERED;
971 return;
972 }
973 break;
974 case ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY:
975 if (SUCCEED == is_user_macro(*field))
976 return;
977
978 if (SUCCEED == is_time_suffix(*field, &value, ZBX_LENGTH_UNLIMITED) && (0 == value ||
979 (ZBX_HK_HISTORY_MIN <= value && ZBX_HK_PERIOD_MAX >= value)))
980 {
981 return;
982 }
983
984 *error = zbx_strdcatf(*error, "Cannot %s item: invalid history storage period"
985 " \"%s\".\n", (0 != item->itemid ? "update" : "create"), *field);
986 break;
987 case ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS:
988 if (SUCCEED == is_user_macro(*field))
989 return;
990
991 if (SUCCEED == is_time_suffix(*field, &value, ZBX_LENGTH_UNLIMITED) && (0 == value ||
992 (ZBX_HK_TRENDS_MIN <= value && ZBX_HK_PERIOD_MAX >= value)))
993 {
994 return;
995 }
996
997 *error = zbx_strdcatf(*error, "Cannot %s item: invalid trends storage period"
998 " \"%s\".\n", (0 != item->itemid ? "update" : "create"), *field);
999 break;
1000 default:
1001 return;
1002 }
1003 }
1004
1005 if (0 != item->itemid)
1006 lld_field_str_rollback(field, field_orig, &item->flags, flag);
1007 else
1008 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1009 }
1010
1011 /******************************************************************************
1012 * *
1013 * Function: lld_item_dependence_add *
1014 * *
1015 * Purpose: add a new dependency *
1016 * *
1017 * Parameters: item_dependencies - [IN\OUT] list of dependencies *
1018 * itemid - [IN] item id *
1019 * master_itemid - [IN] master item id *
1020 * item_flags - [IN] item flags (ZBX_FLAG_DISCOVERY_*) *
1021 * *
1022 * Returns: item dependence *
1023 * *
1024 * Comments: Memory is allocated to store item dependence. This memory must *
1025 * be freed by the caller. *
1026 * *
1027 ******************************************************************************/
lld_item_dependence_add(zbx_vector_ptr_t * item_dependencies,zbx_uint64_t itemid,zbx_uint64_t master_itemid,unsigned int item_flags)1028 static zbx_item_dependence_t *lld_item_dependence_add(zbx_vector_ptr_t *item_dependencies, zbx_uint64_t itemid,
1029 zbx_uint64_t master_itemid, unsigned int item_flags)
1030 {
1031 zbx_item_dependence_t *dependence = (zbx_item_dependence_t *)zbx_malloc(NULL, sizeof(zbx_item_dependence_t));
1032
1033 dependence->itemid = itemid;
1034 dependence->master_itemid = master_itemid;
1035 dependence->item_flags = item_flags;
1036
1037 zbx_vector_ptr_append(item_dependencies, dependence);
1038
1039 return dependence;
1040 }
1041
1042 /******************************************************************************
1043 * *
1044 * Function: lld_item_dependencies_get *
1045 * *
1046 * Purpose: recursively get dependencies with dependent items taking into *
1047 * account item prototypes *
1048 * *
1049 * Parameters: item_prototypes - [IN] item prototypes *
1050 * item_dependencies - [OUT] list of dependencies *
1051 * *
1052 ******************************************************************************/
lld_item_dependencies_get(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * item_dependencies)1053 static void lld_item_dependencies_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *item_dependencies)
1054 {
1055 #define NEXT_CHECK_BY_ITEM_IDS 0
1056 #define NEXT_CHECK_BY_MASTERITEM_IDS 1
1057
1058 const char *__function_name = "lld_item_dependencies_get";
1059
1060 int i, check_type;
1061 zbx_vector_uint64_t processed_masterid, processed_itemid, next_check_itemids, next_check_masterids,
1062 *check_ids;
1063 char *sql = NULL;
1064 size_t sql_alloc = 0, sql_offset;
1065 DB_RESULT result;
1066 DB_ROW row;
1067
1068 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1069
1070 zbx_vector_uint64_create(&processed_masterid);
1071 zbx_vector_uint64_create(&processed_itemid);
1072 zbx_vector_uint64_create(&next_check_itemids);
1073 zbx_vector_uint64_create(&next_check_masterids);
1074
1075 /* collect the item id of prototypes for searching dependencies into database */
1076 for (i = 0; i < item_prototypes->values_num; i++)
1077 {
1078 const zbx_lld_item_prototype_t *item_prototype;
1079
1080 item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[i];
1081
1082 if (0 != item_prototype->master_itemid)
1083 {
1084 lld_item_dependence_add(item_dependencies, item_prototype->itemid,
1085 item_prototype->master_itemid, ZBX_FLAG_DISCOVERY_PROTOTYPE);
1086 zbx_vector_uint64_append(&next_check_itemids, item_prototype->master_itemid);
1087 zbx_vector_uint64_append(&next_check_masterids, item_prototype->master_itemid);
1088 }
1089 }
1090
1091 /* search dependency in two directions (masteritem_id->itemid and itemid->masteritem_id) */
1092 while (0 < next_check_itemids.values_num || 0 < next_check_masterids.values_num)
1093 {
1094 if (0 < next_check_itemids.values_num)
1095 {
1096 check_type = NEXT_CHECK_BY_ITEM_IDS;
1097 check_ids = &next_check_itemids;
1098 }
1099 else
1100 {
1101 check_type = NEXT_CHECK_BY_MASTERITEM_IDS;
1102 check_ids = &next_check_masterids;
1103 }
1104
1105 sql_offset = 0;
1106 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select itemid,master_itemid,flags from items where");
1107 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset,
1108 NEXT_CHECK_BY_ITEM_IDS == check_type ? "itemid" : "master_itemid",
1109 check_ids->values, check_ids->values_num);
1110
1111 if (NEXT_CHECK_BY_ITEM_IDS == check_type)
1112 zbx_vector_uint64_append_array(&processed_itemid, check_ids->values, check_ids->values_num);
1113 else
1114 zbx_vector_uint64_append_array(&processed_masterid, check_ids->values, check_ids->values_num);
1115
1116 zbx_vector_uint64_clear(check_ids);
1117
1118 result = DBselect("%s", sql);
1119
1120 while (NULL != (row = DBfetch(result)))
1121 {
1122 zbx_item_dependence_t *dependence = NULL;
1123 zbx_uint64_t itemid, master_itemid;
1124 unsigned int item_flags;
1125
1126 ZBX_STR2UINT64(itemid, row[0]);
1127 ZBX_DBROW2UINT64(master_itemid, row[1]);
1128 ZBX_STR2UCHAR(item_flags, row[2]);
1129
1130 for (i = 0; i < item_dependencies->values_num; i++)
1131 {
1132 dependence = (zbx_item_dependence_t *)item_dependencies->values[i];
1133 if (dependence->itemid == itemid && dependence->master_itemid == master_itemid)
1134 break;
1135 }
1136
1137 if (i == item_dependencies->values_num)
1138 {
1139 dependence = lld_item_dependence_add(item_dependencies, itemid, master_itemid,
1140 item_flags);
1141 }
1142
1143 if (FAIL == zbx_vector_uint64_search(&processed_masterid, dependence->itemid,
1144 ZBX_DEFAULT_UINT64_COMPARE_FUNC))
1145 {
1146 zbx_vector_uint64_append(&next_check_masterids, dependence->itemid);
1147 }
1148
1149 if (NEXT_CHECK_BY_ITEM_IDS != check_type || 0 == dependence->master_itemid)
1150 continue;
1151
1152 if (FAIL == zbx_vector_uint64_search(&processed_itemid, dependence->master_itemid,
1153 ZBX_DEFAULT_UINT64_COMPARE_FUNC))
1154 {
1155 zbx_vector_uint64_append(&next_check_itemids, dependence->master_itemid);
1156 }
1157 }
1158 DBfree_result(result);
1159 }
1160 zbx_free(sql);
1161
1162 zbx_vector_uint64_destroy(&processed_masterid);
1163 zbx_vector_uint64_destroy(&processed_itemid);
1164 zbx_vector_uint64_destroy(&next_check_itemids);
1165 zbx_vector_uint64_destroy(&next_check_masterids);
1166
1167 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1168
1169 #undef NEXT_CHECK_BY_ITEM_IDS
1170 #undef NEXT_CHECK_BY_MASTERITEM_IDS
1171 }
1172
1173 /******************************************************************************
1174 * *
1175 * Function: lld_item_dependencies_count *
1176 * *
1177 * Purpose: recursively count the number of dependencies *
1178 * *
1179 * Parameters: itemid - [IN] item ID to be checked *
1180 * dependencies - [IN] item dependencies *
1181 * processed_itemids - [IN\OUT] list of checked item ids *
1182 * dependencies_num - [IN\OUT] number of dependencies *
1183 * depth_level - [IN\OUT] depth level *
1184 * *
1185 * Returns: SUCCEED - the number of dependencies was successfully counted *
1186 * FAIL - the limit of dependencies is reached *
1187 * *
1188 ******************************************************************************/
lld_item_dependencies_count(const zbx_uint64_t itemid,const zbx_vector_ptr_t * dependencies,zbx_vector_uint64_t * processed_itemids,int * dependencies_num,unsigned char * depth_level)1189 static int lld_item_dependencies_count(const zbx_uint64_t itemid, const zbx_vector_ptr_t *dependencies,
1190 zbx_vector_uint64_t *processed_itemids, int *dependencies_num, unsigned char *depth_level)
1191 {
1192 int ret = FAIL, i, curr_depth_calculated = 0;
1193
1194 for (i = 0; i < dependencies->values_num; i++)
1195 {
1196 zbx_item_dependence_t *dep = (zbx_item_dependence_t *)dependencies->values[i];
1197
1198 /* check if item is a master for someone else */
1199 if (dep->master_itemid != itemid)
1200 continue;
1201
1202 /* check the limit of dependent items */
1203 if (0 == (dep->item_flags & ZBX_FLAG_DISCOVERY_PROTOTYPE) &&
1204 ZBX_DEPENDENT_ITEM_MAX_COUNT <= ++(*dependencies_num))
1205 {
1206 goto out;
1207 }
1208
1209 /* check the depth level */
1210 if (0 == curr_depth_calculated)
1211 {
1212 curr_depth_calculated = 1;
1213
1214 if (ZBX_DEPENDENT_ITEM_MAX_LEVELS < ++(*depth_level))
1215 {
1216 /* API shouldn't allow to create dependencies deeper */
1217 THIS_SHOULD_NEVER_HAPPEN;
1218 goto out;
1219 }
1220 }
1221
1222 /* check if item was calculated in previous iterations */
1223 if (FAIL != zbx_vector_uint64_search(processed_itemids, dep->itemid, ZBX_DEFAULT_UINT64_COMPARE_FUNC))
1224 continue;
1225
1226 if (SUCCEED != lld_item_dependencies_count(dep->itemid, dependencies, processed_itemids,
1227 dependencies_num, depth_level))
1228 {
1229 goto out;
1230 }
1231
1232 /* add counted item id */
1233 zbx_vector_uint64_append(processed_itemids, dep->itemid);
1234 }
1235
1236 ret = SUCCEED;
1237 out:
1238 if (1 == curr_depth_calculated)
1239 (*depth_level)--;
1240
1241 return ret;
1242 }
1243
1244 /******************************************************************************
1245 * *
1246 * Function: lld_item_dependencies_check *
1247 * *
1248 * Purpose: check the limits of dependent items *
1249 * *
1250 * Parameters: item - [IN] discovered item *
1251 * item_prototype - [IN] item prototype to be checked for limit *
1252 * dependencies - [IN] item dependencies *
1253 * *
1254 * Returns: SUCCEED - the check was successful *
1255 * FAIL - the limit of dependencies is exceeded *
1256 * *
1257 ******************************************************************************/
lld_item_dependencies_check(const zbx_lld_item_t * item,const zbx_lld_item_prototype_t * item_prototype,zbx_vector_ptr_t * dependencies)1258 static int lld_item_dependencies_check(const zbx_lld_item_t *item, const zbx_lld_item_prototype_t *item_prototype,
1259 zbx_vector_ptr_t *dependencies)
1260 {
1261 zbx_item_dependence_t *dependence = NULL, *top_dependence = NULL, *tmp_dep;
1262 int ret = FAIL, i, dependence_num = 0, item_in_deps = FAIL;
1263 unsigned char depth_level = 0;
1264 zbx_vector_uint64_t processed_itemids;
1265
1266 /* find the dependency of the item by item id */
1267 for (i = 0; i < dependencies->values_num; i++)
1268 {
1269 dependence = (zbx_item_dependence_t *)dependencies->values[i];
1270 if (item_prototype->itemid == dependence->itemid)
1271 break;
1272 }
1273
1274 if (NULL == dependence || i == dependencies->values_num)
1275 return SUCCEED;
1276
1277 /* find the top dependency that doesn't have a master item id */
1278 while (NULL == top_dependence)
1279 {
1280 for (i = 0; i < dependencies->values_num; i++)
1281 {
1282 tmp_dep = (zbx_item_dependence_t *)dependencies->values[i];
1283
1284 if (item->itemid == tmp_dep->itemid)
1285 item_in_deps = SUCCEED;
1286
1287 if (dependence->master_itemid == tmp_dep->itemid)
1288 {
1289 dependence = tmp_dep;
1290 break;
1291 }
1292 }
1293
1294 if (0 == dependence->master_itemid)
1295 {
1296 top_dependence = dependence;
1297 }
1298 else if (ZBX_DEPENDENT_ITEM_MAX_LEVELS < ++depth_level)
1299 {
1300 /* API shouldn't allow to create dependencies deeper than ZBX_DEPENDENT_ITEM_MAX_LEVELS */
1301 THIS_SHOULD_NEVER_HAPPEN;
1302 goto out;
1303 }
1304 }
1305
1306 depth_level = 0;
1307 zbx_vector_uint64_create(&processed_itemids);
1308
1309 ret = lld_item_dependencies_count(top_dependence->itemid, dependencies, &processed_itemids, &dependence_num,
1310 &depth_level);
1311
1312 zbx_vector_uint64_destroy(&processed_itemids);
1313
1314 if (SUCCEED == ret && SUCCEED != item_in_deps
1315 && 0 == (top_dependence->item_flags & ZBX_FLAG_DISCOVERY_PROTOTYPE))
1316 {
1317 lld_item_dependence_add(dependencies, item_prototype->itemid, item->master_itemid,
1318 ZBX_FLAG_DISCOVERY_CREATED);
1319 }
1320
1321 out:
1322 return ret;
1323 }
1324
1325 /******************************************************************************
1326 * *
1327 * Function: lld_items_preproc_step_validate *
1328 * *
1329 * Purpose: validation of a item preprocessing step expressions for discovery *
1330 * process *
1331 * *
1332 * Parameters: pp - [IN] the item preprocessing step *
1333 * itemid - [IN] item ID for logging *
1334 * error - [IN/OUT] the lld error message *
1335 * *
1336 * Return value: SUCCEED - if preprocessing step is valid *
1337 * FAIL - if preprocessing step is not valid *
1338 * *
1339 ******************************************************************************/
lld_items_preproc_step_validate(const zbx_lld_item_preproc_t * pp,zbx_uint64_t itemid,char ** error)1340 static int lld_items_preproc_step_validate(const zbx_lld_item_preproc_t * pp, zbx_uint64_t itemid, char ** error)
1341 {
1342 int ret = SUCCEED;
1343 zbx_token_t token;
1344 char err[MAX_STRING_LEN];
1345 char pattern[ITEM_PREPROC_PARAMS_LEN * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1], *output;
1346 const char* regexp_err = NULL;
1347 zbx_jsonpath_t jsonpath;
1348
1349 *err = '\0';
1350
1351 if (0 == (pp->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE)
1352 || (SUCCEED == zbx_token_find(pp->params, 0, &token, ZBX_TOKEN_SEARCH_BASIC)
1353 && 0 != (token.type & ZBX_TOKEN_USER_MACRO)))
1354 {
1355 return SUCCEED;
1356 }
1357
1358 switch (pp->type)
1359 {
1360 case ZBX_PREPROC_REGSUB:
1361 zbx_strlcpy(pattern, pp->params, sizeof(pattern));
1362 if (NULL == (output = strchr(pattern, '\n')))
1363 {
1364 zbx_snprintf(err, sizeof(err), "cannot find second parameter: %s", pp->params);
1365 ret = FAIL;
1366 break;
1367 }
1368
1369 *output++ = '\0';
1370
1371 if (FAIL == (ret = zbx_regexp_compile(pattern, NULL, ®exp_err)))
1372 {
1373 zbx_strlcpy(err, regexp_err, sizeof(err));
1374 }
1375 break;
1376 case ZBX_PREPROC_JSONPATH:
1377 if (FAIL == (ret = zbx_jsonpath_compile(pp->params, &jsonpath)))
1378 zbx_strlcpy(err, zbx_json_strerror(), sizeof(err));
1379 else
1380 zbx_jsonpath_clear(&jsonpath);
1381 break;
1382 case ZBX_PREPROC_XPATH:
1383 ret = xml_xpath_check(pp->params, err, sizeof(err));
1384 break;
1385 case ZBX_PREPROC_MULTIPLIER:
1386 if (FAIL == (ret = is_double(pp->params, NULL)))
1387 zbx_snprintf(err, sizeof(err), "value is not numeric or out of range: %s", pp->params);
1388 break;
1389 }
1390
1391 if (SUCCEED != ret)
1392 {
1393 *error = zbx_strdcatf(*error, "Cannot %s item: invalid value for preprocessing step #%d: %s.\n",
1394 (0 != itemid ? "update" : "create"), pp->step, err);
1395 }
1396
1397 return ret;
1398 }
1399
1400 /******************************************************************************
1401 * *
1402 * Function: lld_items_validate *
1403 * *
1404 * Parameters: hostid - [IN] host id *
1405 * items - [IN] list of items *
1406 * item_prototypes - [IN] the item prototypes *
1407 * item_dependencies - [IN] list of dependencies *
1408 * error - [IN/OUT] the lld error message *
1409 * *
1410 *****************************************************************************/
lld_items_validate(zbx_uint64_t hostid,zbx_vector_ptr_t * items,zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * item_dependencies,char ** error)1411 static void lld_items_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *items, zbx_vector_ptr_t *item_prototypes,
1412 zbx_vector_ptr_t *item_dependencies, char **error)
1413 {
1414 const char *__function_name = "lld_items_validate";
1415
1416 DB_RESULT result;
1417 DB_ROW row;
1418 int i, j;
1419 zbx_lld_item_t *item;
1420 zbx_vector_uint64_t itemids;
1421 zbx_vector_str_t keys;
1422 zbx_hashset_t items_keys;
1423
1424 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1425
1426 zbx_vector_uint64_create(&itemids);
1427 zbx_vector_str_create(&keys); /* list of item keys */
1428
1429 /* check an item name validity */
1430 for (i = 0; i < items->values_num; i++)
1431 {
1432 item = (zbx_lld_item_t *)items->values[i];
1433
1434 lld_validate_item_field(item, &item->name, &item->name_proto,
1435 ZBX_FLAG_LLD_ITEM_UPDATE_NAME, ITEM_NAME_LEN, error);
1436 lld_validate_item_field(item, &item->key, &item->key_orig,
1437 ZBX_FLAG_LLD_ITEM_UPDATE_KEY, ITEM_KEY_LEN, error);
1438 lld_validate_item_field(item, &item->delay, &item->delay_orig,
1439 ZBX_FLAG_LLD_ITEM_UPDATE_DELAY, ITEM_DELAY_LEN, error);
1440 lld_validate_item_field(item, &item->history, &item->history_orig,
1441 ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY, ITEM_HISTORY_LEN, error);
1442 lld_validate_item_field(item, &item->trends, &item->trends_orig,
1443 ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS, ITEM_TRENDS_LEN, error);
1444 lld_validate_item_field(item, &item->units, &item->units_orig,
1445 ZBX_FLAG_LLD_ITEM_UPDATE_UNITS, ITEM_UNITS_LEN, error);
1446 lld_validate_item_field(item, &item->params, &item->params_orig,
1447 ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS, ITEM_PARAM_LEN, error);
1448 lld_validate_item_field(item, &item->ipmi_sensor, &item->ipmi_sensor_orig,
1449 ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR, ITEM_IPMI_SENSOR_LEN, error);
1450 lld_validate_item_field(item, &item->snmp_oid, &item->snmp_oid_orig,
1451 ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID, ITEM_SNMP_OID_LEN, error);
1452 lld_validate_item_field(item, &item->username, &item->username_orig,
1453 ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME, ITEM_USERNAME_LEN, error);
1454 lld_validate_item_field(item, &item->password, &item->password_orig,
1455 ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD, ITEM_PASSWORD_LEN, error);
1456 lld_validate_item_field(item, &item->description, &item->description_orig,
1457 ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION, ITEM_DESCRIPTION_LEN, error);
1458 lld_validate_item_field(item, &item->jmx_endpoint, &item->jmx_endpoint_orig,
1459 ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT, ITEM_JMX_ENDPOINT_LEN, error);
1460 lld_validate_item_field(item, &item->timeout, &item->timeout_orig,
1461 ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT, ITEM_TIMEOUT_LEN, error);
1462 lld_validate_item_field(item, &item->url, &item->url_orig,
1463 ZBX_FLAG_LLD_ITEM_UPDATE_URL, ITEM_URL_LEN, error);
1464 lld_validate_item_field(item, &item->query_fields, &item->query_fields_orig,
1465 ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS, ITEM_QUERY_FIELDS_LEN, error);
1466 lld_validate_item_field(item, &item->posts, &item->posts_orig,
1467 ZBX_FLAG_LLD_ITEM_UPDATE_POSTS, ITEM_POSTS_LEN, error);
1468 lld_validate_item_field(item, &item->status_codes, &item->status_codes_orig,
1469 ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES, ITEM_STATUS_CODES_LEN, error);
1470 lld_validate_item_field(item, &item->http_proxy, &item->http_proxy_orig,
1471 ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY, ITEM_HTTP_PROXY_LEN, error);
1472 lld_validate_item_field(item, &item->headers, &item->headers_orig,
1473 ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS, ITEM_HEADERS_LEN, error);
1474 lld_validate_item_field(item, &item->ssl_cert_file, &item->ssl_cert_file_orig,
1475 ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE, ITEM_SSL_CERT_FILE_LEN, error);
1476 lld_validate_item_field(item, &item->ssl_key_file, &item->ssl_key_file_orig,
1477 ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE, ITEM_SSL_KEY_FILE_LEN, error);
1478 lld_validate_item_field(item, &item->ssl_key_password, &item->ssl_key_password_orig,
1479 ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD, ITEM_SSL_KEY_PASSWORD_LEN, error);
1480 }
1481
1482 /* check duplicated item keys */
1483
1484 zbx_hashset_create(&items_keys, items->values_num, lld_items_keys_hash_func, lld_items_keys_compare_func);
1485
1486 /* add 'good' (existing, discovered and not updated) keys to the hashset */
1487 for (i = 0; i < items->values_num; i++)
1488 {
1489 item = (zbx_lld_item_t *)items->values[i];
1490
1491 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1492 continue;
1493
1494 /* skip new or updated item keys */
1495 if (0 == item->itemid || 0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1496 continue;
1497
1498 zbx_hashset_insert(&items_keys, &item->key, sizeof(char *));
1499 }
1500
1501 /* check new and updated keys for duplicated keys in discovered items */
1502 for (i = 0; i < items->values_num; i++)
1503 {
1504 item = (zbx_lld_item_t *)items->values[i];
1505
1506 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1507 continue;
1508
1509 /* only new items or items with changed key will be validated */
1510 if (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1511 continue;
1512
1513 if (NULL != zbx_hashset_search(&items_keys, &item->key))
1514 {
1515 *error = zbx_strdcatf(*error, "Cannot %s item: item with the same key \"%s\" already exists.\n",
1516 (0 != item->itemid ? "update" : "create"), item->key);
1517
1518 if (0 != item->itemid)
1519 {
1520 lld_field_str_rollback(&item->key, &item->key_orig, &item->flags,
1521 ZBX_FLAG_LLD_ITEM_UPDATE_KEY);
1522 }
1523 else
1524 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1525 }
1526 else
1527 zbx_hashset_insert(&items_keys, &item->key, sizeof(char *));
1528 }
1529
1530 zbx_hashset_destroy(&items_keys);
1531
1532 /* check preprocessing steps for new and updated discovered items */
1533 for (i = 0; i < items->values_num; i++)
1534 {
1535 item = (zbx_lld_item_t *)items->values[i];
1536
1537 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1538 continue;
1539
1540 for (j = 0; j < item->preproc_ops.values_num; j++)
1541 {
1542 if (SUCCEED != lld_items_preproc_step_validate(item->preproc_ops.values[j], item->itemid,
1543 error))
1544 {
1545 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1546 break;
1547 }
1548 }
1549 }
1550
1551
1552 /* check duplicated keys in DB */
1553 for (i = 0; i < items->values_num; i++)
1554 {
1555 item = (zbx_lld_item_t *)items->values[i];
1556
1557 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1558 continue;
1559
1560 if (0 != item->itemid)
1561 zbx_vector_uint64_append(&itemids, item->itemid);
1562
1563 if (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1564 continue;
1565
1566 zbx_vector_str_append(&keys, item->key);
1567 }
1568
1569 if (0 != keys.values_num)
1570 {
1571 char *sql = NULL;
1572 size_t sql_alloc = 256, sql_offset = 0;
1573
1574 sql = (char *)zbx_malloc(sql, sql_alloc);
1575
1576 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1577 "select key_"
1578 " from items"
1579 " where hostid=" ZBX_FS_UI64
1580 " and",
1581 hostid);
1582 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "key_",
1583 (const char **)keys.values, keys.values_num);
1584
1585 if (0 != itemids.values_num)
1586 {
1587 zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1588 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
1589 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
1590 itemids.values, itemids.values_num);
1591 }
1592
1593 result = DBselect("%s", sql);
1594
1595 while (NULL != (row = DBfetch(result)))
1596 {
1597 for (i = 0; i < items->values_num; i++)
1598 {
1599 item = (zbx_lld_item_t *)items->values[i];
1600
1601 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1602 continue;
1603
1604 if (0 == strcmp(item->key, row[0]))
1605 {
1606 *error = zbx_strdcatf(*error, "Cannot %s item:"
1607 " item with the same key \"%s\" already exists.\n",
1608 (0 != item->itemid ? "update" : "create"), item->key);
1609
1610 if (0 != item->itemid)
1611 {
1612 lld_field_str_rollback(&item->key, &item->key_orig, &item->flags,
1613 ZBX_FLAG_LLD_ITEM_UPDATE_KEY);
1614 }
1615 else
1616 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1617
1618 continue;
1619 }
1620 }
1621 }
1622 DBfree_result(result);
1623
1624 zbx_free(sql);
1625 }
1626
1627 zbx_vector_str_destroy(&keys);
1628 zbx_vector_uint64_destroy(&itemids);
1629
1630 /* check limit of dependent items in the dependency tree */
1631 if (0 != item_dependencies->values_num)
1632 {
1633 for (i = 0; i < items->values_num; i++)
1634 {
1635 int index;
1636 const zbx_lld_item_prototype_t *item_prototype;
1637
1638 item = (zbx_lld_item_t *)items->values[i];
1639
1640 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) || 0 == item->master_itemid
1641 || (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE)))
1642 {
1643 continue;
1644 }
1645
1646 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
1647 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1648 {
1649 THIS_SHOULD_NEVER_HAPPEN;
1650 continue;
1651 }
1652
1653 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
1654
1655 if (SUCCEED != lld_item_dependencies_check(item, item_prototype, item_dependencies))
1656 {
1657 *error = zbx_strdcatf(*error,
1658 "Cannot create item \"%s\": maximum dependent item count reached.\n",
1659 item->key);
1660
1661 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1662 }
1663 }
1664 }
1665
1666 /* check for broken dependent items */
1667 for (i = 0; i < items->values_num; i++)
1668 {
1669 item = (zbx_lld_item_t *)items->values[i];
1670
1671 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1672 {
1673 for (j = 0; j < item->dependent_items.values_num; j++)
1674 {
1675 zbx_lld_item_t *dependent;
1676
1677 dependent = (zbx_lld_item_t *)item->dependent_items.values[j];
1678 dependent->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
1679 }
1680 }
1681 }
1682
1683 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1684 }
1685
1686 /******************************************************************************
1687 * *
1688 * Function: substitute_formula_macros *
1689 * *
1690 * Purpose: substitutes lld macros in calculated item formula expression *
1691 * *
1692 * Parameters: data - [IN/OUT] the expression *
1693 * jp_row - [IN] the lld data row *
1694 * error - [IN] pointer to string for reporting errors *
1695 * max_error_len - [IN] size of 'error' string *
1696 * *
1697 ******************************************************************************/
substitute_formula_macros(char ** data,const struct zbx_json_parse * jp_row,char * error,size_t max_error_len)1698 static int substitute_formula_macros(char **data, const struct zbx_json_parse *jp_row,
1699 char *error, size_t max_error_len)
1700 {
1701 const char *__function_name = "substitute_formula_macros";
1702
1703 char *exp, *tmp, *e;
1704 size_t exp_alloc = 128, exp_offset = 0, tmp_alloc = 128, tmp_offset = 0, f_pos, par_l, par_r;
1705 int ret = FAIL;
1706
1707 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1708
1709 exp = (char *)zbx_malloc(NULL, exp_alloc);
1710 tmp = (char *)zbx_malloc(NULL, tmp_alloc);
1711
1712 for (e = *data; SUCCEED == zbx_function_find(e, &f_pos, &par_l, &par_r, error, max_error_len); e += par_r + 1)
1713 {
1714 /* substitute LLD macros in the part of the string preceding function parameters */
1715
1716 zbx_strncpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e, par_l + 1);
1717 if (SUCCEED != substitute_lld_macros(&tmp, jp_row, ZBX_MACRO_NUMERIC, error, max_error_len))
1718 goto out;
1719
1720 tmp_offset = strlen(tmp);
1721 zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, tmp, tmp_offset);
1722
1723 tmp_alloc = tmp_offset + 1;
1724 tmp_offset = 0;
1725
1726 /* substitute LLD macros in function parameters */
1727
1728 if (SUCCEED != substitute_function_lld_param(e + par_l + 1, par_r - (par_l + 1), 1,
1729 &exp, &exp_alloc, &exp_offset, jp_row, error, max_error_len))
1730 {
1731 goto out;
1732 }
1733
1734 zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, ")");
1735 }
1736
1737 if (par_l > par_r)
1738 goto out;
1739
1740 /* substitute LLD macros in the remaining part */
1741
1742 zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e);
1743 if (SUCCEED != substitute_lld_macros(&tmp, jp_row, ZBX_MACRO_NUMERIC, error, max_error_len))
1744 goto out;
1745
1746 zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, tmp);
1747
1748 ret = SUCCEED;
1749 out:
1750 zbx_free(tmp);
1751
1752 if (SUCCEED == ret)
1753 {
1754 zbx_free(*data);
1755 *data = exp;
1756 }
1757 else
1758 zbx_free(exp);
1759
1760 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1761
1762 return ret;
1763 }
1764
1765 /******************************************************************************
1766 * *
1767 * Function: lld_item_make *
1768 * *
1769 * Purpose: creates a new item based on item prototype and lld data row *
1770 * *
1771 * Parameters: item_prototype - [IN] the item prototype *
1772 * lld_row - [IN] the lld row *
1773 * *
1774 * Returns: The created item or NULL if cannot create new item from prototype *
1775 * *
1776 ******************************************************************************/
lld_item_make(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_row_t * lld_row,char ** error)1777 static zbx_lld_item_t *lld_item_make(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_row_t *lld_row,
1778 char **error)
1779 {
1780 const char *__function_name = "lld_item_make";
1781
1782 zbx_lld_item_t *item;
1783 const struct zbx_json_parse *jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
1784 char err[MAX_STRING_LEN];
1785 int ret;
1786
1787 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1788
1789 item = (zbx_lld_item_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_t));
1790
1791 item->itemid = 0;
1792 item->parent_itemid = item_prototype->itemid;
1793 item->lastcheck = 0;
1794 item->ts_delete = 0;
1795 item->type = item_prototype->type;
1796 item->key_proto = NULL;
1797 item->master_itemid = item_prototype->master_itemid;
1798
1799 item->name = zbx_strdup(NULL, item_prototype->name);
1800 item->name_proto = NULL;
1801 substitute_lld_macros(&item->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
1802 zbx_lrtrim(item->name, ZBX_WHITESPACE);
1803
1804 item->key = zbx_strdup(NULL, item_prototype->key);
1805 item->key_orig = NULL;
1806
1807 if (FAIL == (ret = substitute_key_macros(&item->key, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, err,
1808 sizeof(err))))
1809 {
1810 *error = zbx_strdcatf(*error, "Cannot create item, error in item key parameters %s.\n", err);
1811 }
1812
1813 item->delay = zbx_strdup(NULL, item_prototype->delay);
1814 item->delay_orig = NULL;
1815 substitute_lld_macros(&item->delay, jp_row, ZBX_MACRO_ANY, NULL, 0);
1816 zbx_lrtrim(item->delay, ZBX_WHITESPACE);
1817
1818 item->history = zbx_strdup(NULL, item_prototype->history);
1819 item->history_orig = NULL;
1820 substitute_lld_macros(&item->history, jp_row, ZBX_MACRO_ANY, NULL, 0);
1821 zbx_lrtrim(item->history, ZBX_WHITESPACE);
1822
1823 item->trends = zbx_strdup(NULL, item_prototype->trends);
1824 item->trends_orig = NULL;
1825 substitute_lld_macros(&item->trends, jp_row, ZBX_MACRO_ANY, NULL, 0);
1826 zbx_lrtrim(item->trends, ZBX_WHITESPACE);
1827
1828 item->units = zbx_strdup(NULL, item_prototype->units);
1829 item->units_orig = NULL;
1830 substitute_lld_macros(&item->units, jp_row, ZBX_MACRO_ANY, NULL, 0);
1831 zbx_lrtrim(item->units, ZBX_WHITESPACE);
1832
1833 item->params = zbx_strdup(NULL, item_prototype->params);
1834 item->params_orig = NULL;
1835
1836 if (ITEM_TYPE_CALCULATED == item_prototype->type)
1837 {
1838 if (SUCCEED == ret && FAIL == (ret = substitute_formula_macros(&item->params, jp_row, err,
1839 sizeof(err))))
1840 {
1841 *error = zbx_strdcatf(*error, "Cannot create item, error in formula: %s.\n", err);
1842 }
1843 }
1844 else
1845 substitute_lld_macros(&item->params, jp_row, ZBX_MACRO_ANY, NULL, 0);
1846
1847 zbx_lrtrim(item->params, ZBX_WHITESPACE);
1848
1849 item->ipmi_sensor = zbx_strdup(NULL, item_prototype->ipmi_sensor);
1850 item->ipmi_sensor_orig = NULL;
1851 substitute_lld_macros(&item->ipmi_sensor, jp_row, ZBX_MACRO_ANY, NULL, 0);
1852 /* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1853
1854 item->snmp_oid = zbx_strdup(NULL, item_prototype->snmp_oid);
1855 item->snmp_oid_orig = NULL;
1856
1857 if (SUCCEED == ret && (ITEM_TYPE_SNMPv1 == item_prototype->type || ITEM_TYPE_SNMPv2c == item_prototype->type ||
1858 ITEM_TYPE_SNMPv3 == item_prototype->type) &&
1859 FAIL == (ret = substitute_key_macros(&item->snmp_oid, NULL, NULL, jp_row, MACRO_TYPE_SNMP_OID,
1860 err, sizeof(err))))
1861 {
1862 *error = zbx_strdcatf(*error, "Cannot create item, error in SNMP OID key parameters: %s.\n", err);
1863 }
1864
1865 zbx_lrtrim(item->snmp_oid, ZBX_WHITESPACE);
1866
1867 item->username = zbx_strdup(NULL, item_prototype->username);
1868 item->username_orig = NULL;
1869 substitute_lld_macros(&item->username, jp_row, ZBX_MACRO_ANY, NULL, 0);
1870 /* zbx_lrtrim(item->username, ZBX_WHITESPACE); is not missing here */
1871
1872 item->password = zbx_strdup(NULL, item_prototype->password);
1873 item->password_orig = NULL;
1874 substitute_lld_macros(&item->password, jp_row, ZBX_MACRO_ANY, NULL, 0);
1875 /* zbx_lrtrim(item->password, ZBX_WHITESPACE); is not missing here */
1876
1877 item->description = zbx_strdup(NULL, item_prototype->description);
1878 item->description_orig = NULL;
1879 substitute_lld_macros(&item->description, jp_row, ZBX_MACRO_ANY, NULL, 0);
1880 zbx_lrtrim(item->description, ZBX_WHITESPACE);
1881
1882 item->jmx_endpoint = zbx_strdup(NULL, item_prototype->jmx_endpoint);
1883 item->jmx_endpoint_orig = NULL;
1884 substitute_lld_macros(&item->jmx_endpoint, jp_row, ZBX_MACRO_ANY, NULL, 0);
1885 /* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1886
1887 item->timeout = zbx_strdup(NULL, item_prototype->timeout);
1888 item->timeout_orig = NULL;
1889 substitute_lld_macros(&item->timeout, jp_row, ZBX_MACRO_ANY, NULL, 0);
1890 zbx_lrtrim(item->timeout, ZBX_WHITESPACE);
1891
1892 item->url = zbx_strdup(NULL, item_prototype->url);
1893 item->url_orig = NULL;
1894 substitute_lld_macros(&item->url, jp_row, ZBX_MACRO_ANY, NULL, 0);
1895 zbx_lrtrim(item->url, ZBX_WHITESPACE);
1896
1897 item->query_fields = zbx_strdup(NULL, item_prototype->query_fields);
1898 item->query_fields_orig = NULL;
1899
1900 if (SUCCEED == ret && FAIL == (ret = substitute_macros_in_json_pairs(&item->query_fields, jp_row, err,
1901 sizeof(err))))
1902 {
1903 *error = zbx_strdcatf(*error, "Cannot create item, error in JSON: %s.\n", err);
1904 }
1905
1906 item->posts = zbx_strdup(NULL, item_prototype->posts);
1907 item->posts_orig = NULL;
1908
1909 switch (item_prototype->post_type)
1910 {
1911 case ZBX_POSTTYPE_JSON:
1912 substitute_lld_macros(&item->posts, jp_row, ZBX_MACRO_JSON, NULL, 0);
1913 break;
1914 case ZBX_POSTTYPE_XML:
1915 if (SUCCEED == ret && FAIL == (ret = substitute_macros_xml(&item->posts, NULL, jp_row, err,
1916 sizeof(err))))
1917 {
1918 zbx_lrtrim(err, ZBX_WHITESPACE);
1919 *error = zbx_strdcatf(*error, "Cannot create item, error in XML: %s.\n", err);
1920 }
1921 break;
1922 default:
1923 substitute_lld_macros(&item->posts, jp_row, ZBX_MACRO_ANY, NULL, 0);
1924 /* zbx_lrtrim(item->posts, ZBX_WHITESPACE); is not missing here */
1925 break;
1926 }
1927
1928 item->status_codes = zbx_strdup(NULL, item_prototype->status_codes);
1929 item->status_codes_orig = NULL;
1930 substitute_lld_macros(&item->status_codes, jp_row, ZBX_MACRO_ANY, NULL, 0);
1931 zbx_lrtrim(item->status_codes, ZBX_WHITESPACE);
1932
1933 item->http_proxy = zbx_strdup(NULL, item_prototype->http_proxy);
1934 item->http_proxy_orig = NULL;
1935 substitute_lld_macros(&item->http_proxy, jp_row, ZBX_MACRO_ANY, NULL, 0);
1936 zbx_lrtrim(item->http_proxy, ZBX_WHITESPACE);
1937
1938 item->headers = zbx_strdup(NULL, item_prototype->headers);
1939 item->headers_orig = NULL;
1940 substitute_lld_macros(&item->headers, jp_row, ZBX_MACRO_ANY, NULL, 0);
1941 /* zbx_lrtrim(item->headers, ZBX_WHITESPACE); is not missing here */
1942
1943 item->ssl_cert_file = zbx_strdup(NULL, item_prototype->ssl_cert_file);
1944 item->ssl_cert_file_orig = NULL;
1945 substitute_lld_macros(&item->ssl_cert_file, jp_row, ZBX_MACRO_ANY, NULL, 0);
1946 /* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1947
1948 item->ssl_key_file = zbx_strdup(NULL, item_prototype->ssl_key_file);
1949 item->ssl_key_file_orig = NULL;
1950 substitute_lld_macros(&item->ssl_key_file, jp_row, ZBX_MACRO_ANY, NULL, 0);
1951 /* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1952
1953 item->ssl_key_password = zbx_strdup(NULL, item_prototype->ssl_key_password);
1954 item->ssl_key_password_orig = NULL;
1955 substitute_lld_macros(&item->ssl_key_password, jp_row, ZBX_MACRO_ANY, NULL, 0);
1956 /* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1957
1958 item->flags = ZBX_FLAG_LLD_ITEM_DISCOVERED;
1959 item->lld_row = lld_row;
1960
1961 zbx_vector_ptr_create(&item->preproc_ops);
1962 zbx_vector_ptr_create(&item->dependent_items);
1963
1964 if (SUCCEED != ret)
1965 {
1966 lld_item_free(item);
1967 item = NULL;
1968 }
1969
1970 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1971
1972 return item;
1973 }
1974
1975 /******************************************************************************
1976 * *
1977 * Function: lld_item_update *
1978 * *
1979 * Purpose: updates an existing item based on item prototype and lld data row *
1980 * *
1981 * Parameters: item_prototype - [IN] the item prototype *
1982 * lld_row - [IN] the lld row *
1983 * item - [IN] an existing item or NULL *
1984 * *
1985 ******************************************************************************/
lld_item_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_row_t * lld_row,zbx_lld_item_t * item,char ** error)1986 static void lld_item_update(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_row_t *lld_row,
1987 zbx_lld_item_t *item, char **error)
1988 {
1989 const char *__function_name = "lld_item_update";
1990
1991 char *buffer = NULL, err[MAX_STRING_LEN];
1992 struct zbx_json_parse *jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
1993
1994 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1995
1996 buffer = zbx_strdup(buffer, item_prototype->name);
1997 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1998 zbx_lrtrim(buffer, ZBX_WHITESPACE);
1999 if (0 != strcmp(item->name, buffer))
2000 {
2001 item->name_proto = item->name;
2002 item->name = buffer;
2003 buffer = NULL;
2004 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_NAME;
2005 }
2006
2007 if (0 != strcmp(item->key_proto, item_prototype->key))
2008 {
2009 buffer = zbx_strdup(buffer, item_prototype->key);
2010
2011 if (SUCCEED == substitute_key_macros(&buffer, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, err,
2012 sizeof(err)))
2013 {
2014 item->key_orig = item->key;
2015 item->key = buffer;
2016 buffer = NULL;
2017 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_KEY;
2018 }
2019 else
2020 *error = zbx_strdcatf(*error, "Cannot update item, error in item key parameters: %s.\n", err);
2021 }
2022
2023 buffer = zbx_strdup(buffer, item_prototype->delay);
2024 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2025 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2026 if (0 != strcmp(item->delay, buffer))
2027 {
2028 item->delay_orig = item->delay;
2029 item->delay = buffer;
2030 buffer = NULL;
2031 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DELAY;
2032 }
2033
2034 buffer = zbx_strdup(buffer, item_prototype->history);
2035 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2036 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2037 if (0 != strcmp(item->history, buffer))
2038 {
2039 item->history_orig = item->history;
2040 item->history = buffer;
2041 buffer = NULL;
2042 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY;
2043 }
2044
2045 buffer = zbx_strdup(buffer, item_prototype->trends);
2046 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2047 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2048 if (0 != strcmp(item->trends, buffer))
2049 {
2050 item->trends_orig = item->trends;
2051 item->trends = buffer;
2052 buffer = NULL;
2053 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS;
2054 }
2055
2056 buffer = zbx_strdup(buffer, item_prototype->units);
2057 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2058 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2059 if (0 != strcmp(item->units, buffer))
2060 {
2061 item->units_orig = item->units;
2062 item->units = buffer;
2063 buffer = NULL;
2064 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_UNITS;
2065 }
2066
2067 buffer = zbx_strdup(buffer, item_prototype->params);
2068
2069 if (ITEM_TYPE_CALCULATED == item_prototype->type)
2070 {
2071 if (SUCCEED == substitute_formula_macros(&buffer, jp_row, err, sizeof(err)))
2072 {
2073 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2074
2075 if (0 != strcmp(item->params, buffer))
2076 {
2077 item->params_orig = item->params;
2078 item->params = buffer;
2079 buffer = NULL;
2080 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS;
2081 }
2082 }
2083 else
2084 *error = zbx_strdcatf(*error, "Cannot update item, error in formula: %s.\n", err);
2085 }
2086 else
2087 {
2088 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2089 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2090
2091 if (0 != strcmp(item->params, buffer))
2092 {
2093 item->params_orig = item->params;
2094 item->params = buffer;
2095 buffer = NULL;
2096 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS;
2097 }
2098 }
2099
2100 buffer = zbx_strdup(buffer, item_prototype->ipmi_sensor);
2101 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2102 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2103 if (0 != strcmp(item->ipmi_sensor, buffer))
2104 {
2105 item->ipmi_sensor_orig = item->ipmi_sensor;
2106 item->ipmi_sensor = buffer;
2107 buffer = NULL;
2108 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR;
2109 }
2110
2111 buffer = zbx_strdup(buffer, item_prototype->snmp_oid);
2112
2113 if ((ITEM_TYPE_SNMPv1 == item_prototype->type || ITEM_TYPE_SNMPv2c == item_prototype->type ||
2114 ITEM_TYPE_SNMPv3 == item_prototype->type) &&
2115 FAIL == substitute_key_macros(&buffer, NULL, NULL, jp_row, MACRO_TYPE_SNMP_OID, err,
2116 sizeof(err)))
2117 {
2118 *error = zbx_strdcatf(*error, "Cannot update item, error in SNMP OID key parameters: %s.\n", err);
2119 }
2120
2121 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2122 if (0 != strcmp(item->snmp_oid, buffer))
2123 {
2124 item->snmp_oid_orig = item->snmp_oid;
2125 item->snmp_oid = buffer;
2126 buffer = NULL;
2127 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID;
2128 }
2129
2130 buffer = zbx_strdup(buffer, item_prototype->username);
2131 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2132 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2133 if (0 != strcmp(item->username, buffer))
2134 {
2135 item->username_orig = item->username;
2136 item->username = buffer;
2137 buffer = NULL;
2138 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME;
2139 }
2140
2141 buffer = zbx_strdup(buffer, item_prototype->password);
2142 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2143 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2144 if (0 != strcmp(item->password, buffer))
2145 {
2146 item->password_orig = item->password;
2147 item->password = buffer;
2148 buffer = NULL;
2149 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD;
2150 }
2151
2152 buffer = zbx_strdup(buffer, item_prototype->description);
2153 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2154 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2155 if (0 != strcmp(item->description, buffer))
2156 {
2157 item->description_orig = item->description;
2158 item->description = buffer;
2159 buffer = NULL;
2160 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION;
2161 }
2162
2163 buffer = zbx_strdup(buffer, item_prototype->jmx_endpoint);
2164 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2165 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2166 if (0 != strcmp(item->jmx_endpoint, buffer))
2167 {
2168 item->jmx_endpoint_orig = item->jmx_endpoint;
2169 item->jmx_endpoint = buffer;
2170 buffer = NULL;
2171 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT;
2172 }
2173
2174 buffer = zbx_strdup(buffer, item_prototype->timeout);
2175 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2176 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2177 if (0 != strcmp(item->timeout, buffer))
2178 {
2179 item->timeout_orig = item->timeout;
2180 item->timeout = buffer;
2181 buffer = NULL;
2182 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT;
2183 }
2184
2185 buffer = zbx_strdup(buffer, item_prototype->url);
2186 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2187 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2188 if (0 != strcmp(item->url, buffer))
2189 {
2190 item->url_orig = item->url;
2191 item->url = buffer;
2192 buffer = NULL;
2193 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_URL;
2194 }
2195
2196 buffer = zbx_strdup(buffer, item_prototype->query_fields);
2197
2198 if (FAIL == substitute_macros_in_json_pairs(&buffer, jp_row, err, sizeof(err)))
2199 *error = zbx_strdcatf(*error, "Cannot update item, error in JSON: %s.\n", err);
2200
2201 if (0 != strcmp(item->query_fields, buffer))
2202 {
2203 item->query_fields_orig = item->query_fields;
2204 item->query_fields = buffer;
2205 buffer = NULL;
2206 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS;
2207 }
2208
2209 buffer = zbx_strdup(buffer, item_prototype->posts);
2210
2211 if (ZBX_POSTTYPE_JSON == item_prototype->post_type)
2212 {
2213 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_JSON, NULL, 0);
2214 }
2215 else if (ZBX_POSTTYPE_XML == item_prototype->post_type)
2216 {
2217 if (FAIL == substitute_macros_xml(&buffer, NULL, jp_row, err, sizeof(err)))
2218 {
2219 zbx_lrtrim(err, ZBX_WHITESPACE);
2220 *error = zbx_strdcatf(*error, "Cannot update item, error in XML: %s.\n", err);
2221 }
2222 }
2223 else
2224 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2225 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2226 if (0 != strcmp(item->posts, buffer))
2227 {
2228 item->posts_orig = item->posts;
2229 item->posts = buffer;
2230 buffer = NULL;
2231 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_POSTS;
2232 }
2233
2234 buffer = zbx_strdup(buffer, item_prototype->status_codes);
2235 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2236 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2237 if (0 != strcmp(item->status_codes, buffer))
2238 {
2239 item->status_codes_orig = item->status_codes;
2240 item->status_codes = buffer;
2241 buffer = NULL;
2242 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES;
2243 }
2244
2245 buffer = zbx_strdup(buffer, item_prototype->http_proxy);
2246 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2247 zbx_lrtrim(buffer, ZBX_WHITESPACE);
2248 if (0 != strcmp(item->http_proxy, buffer))
2249 {
2250 item->http_proxy_orig = item->http_proxy;
2251 item->http_proxy = buffer;
2252 buffer = NULL;
2253 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY;
2254 }
2255
2256 buffer = zbx_strdup(buffer, item_prototype->headers);
2257 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2258 /*zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2259 if (0 != strcmp(item->headers, buffer))
2260 {
2261 item->headers_orig = item->headers;
2262 item->headers = buffer;
2263 buffer = NULL;
2264 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS;
2265 }
2266
2267 buffer = zbx_strdup(buffer, item_prototype->ssl_cert_file);
2268 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2269 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2270 if (0 != strcmp(item->ssl_cert_file, buffer))
2271 {
2272 item->ssl_cert_file_orig = item->ssl_cert_file;
2273 item->ssl_cert_file = buffer;
2274 buffer = NULL;
2275 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE;
2276 }
2277
2278 buffer = zbx_strdup(buffer, item_prototype->ssl_key_file);
2279 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2280 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2281 if (0 != strcmp(item->ssl_key_file, buffer))
2282 {
2283 item->ssl_key_file_orig = item->ssl_key_file;
2284 item->ssl_key_file = buffer;
2285 buffer = NULL;
2286 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE;
2287 }
2288
2289 buffer = zbx_strdup(buffer, item_prototype->ssl_key_password);
2290 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2291 /* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
2292 if (0 != strcmp(item->ssl_key_password, buffer))
2293 {
2294 item->ssl_key_password_orig = item->ssl_key_password;
2295 item->ssl_key_password = buffer;
2296 buffer = NULL;
2297 item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD;
2298 }
2299
2300 item->flags |= ZBX_FLAG_LLD_ITEM_DISCOVERED;
2301 item->lld_row = lld_row;
2302
2303 zbx_free(buffer);
2304
2305 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2306 }
2307
2308 /******************************************************************************
2309 * *
2310 * Function: lld_items_make *
2311 * *
2312 * Purpose: updates existing items and creates new ones based on item *
2313 * item prototypes and lld data *
2314 * *
2315 * Parameters: item_prototypes - [IN] the item prototypes *
2316 * lld_rows - [IN] the lld data rows *
2317 * items - [IN/OUT] sorted list of items *
2318 * items_index - [OUT] index of items based on prototype ids *
2319 * and lld rows. Used to quckly find an *
2320 * item by prototype and lld_row. *
2321 * error - [IN/OUT] the lld error message *
2322 * *
2323 ******************************************************************************/
lld_items_make(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * lld_rows,zbx_vector_ptr_t * items,zbx_hashset_t * items_index,char ** error)2324 static void lld_items_make(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *lld_rows,
2325 zbx_vector_ptr_t *items, zbx_hashset_t *items_index, char **error)
2326 {
2327 const char *__function_name = "lld_items_make";
2328 int i, j, index;
2329 zbx_lld_item_prototype_t *item_prototype;
2330 zbx_lld_item_t *item;
2331 zbx_lld_row_t *lld_row;
2332 zbx_lld_item_index_t *item_index, item_index_local;
2333 char *buffer = NULL;
2334
2335 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2336
2337 /* create the items index */
2338 for (i = 0; i < item_prototypes->values_num; i++)
2339 {
2340 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
2341
2342 for (j = 0; j < lld_rows->values_num; j++)
2343 zbx_vector_ptr_append(&item_prototype->lld_rows, lld_rows->values[j]);
2344 }
2345
2346 /* Iterate in reverse order because usually the items are created in the same order as */
2347 /* incoming lld rows. Iterating in reverse optimizes lld_row removal from item prototypes. */
2348 for (i = items->values_num - 1; i >= 0; i--)
2349 {
2350 item = (zbx_lld_item_t *)items->values[i];
2351
2352 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
2353 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2354 {
2355 THIS_SHOULD_NEVER_HAPPEN;
2356 continue;
2357 }
2358
2359 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2360
2361 for (j = item_prototype->lld_rows.values_num - 1; j >= 0; j--)
2362 {
2363 lld_row = (zbx_lld_row_t *)item_prototype->lld_rows.values[j];
2364
2365 buffer = zbx_strdup(buffer, item->key_proto);
2366
2367 if (SUCCEED != substitute_key_macros(&buffer, NULL, NULL, &lld_row->jp_row, MACRO_TYPE_ITEM_KEY,
2368 NULL, 0))
2369 {
2370 continue;
2371 }
2372
2373 if (0 == strcmp(item->key, buffer))
2374 {
2375 item_index_local.parent_itemid = item->parent_itemid;
2376 item_index_local.lld_row = lld_row;
2377 item_index_local.item = item;
2378 zbx_hashset_insert(items_index, &item_index_local, sizeof(item_index_local));
2379
2380 zbx_vector_ptr_remove_noorder(&item_prototype->lld_rows, j);
2381 break;
2382 }
2383 }
2384 }
2385
2386 zbx_free(buffer);
2387
2388 /* update/create discovered items */
2389 for (i = 0; i < item_prototypes->values_num; i++)
2390 {
2391 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
2392 item_index_local.parent_itemid = item_prototype->itemid;
2393
2394 for (j = 0; j < lld_rows->values_num; j++)
2395 {
2396 item_index_local.lld_row = (zbx_lld_row_t *)lld_rows->values[j];
2397
2398 if (NULL == (item_index = (zbx_lld_item_index_t *)zbx_hashset_search(items_index, &item_index_local)))
2399 {
2400 if (NULL != (item = lld_item_make(item_prototype, item_index_local.lld_row, error)))
2401 {
2402 /* add the created item to items vector and update index */
2403 zbx_vector_ptr_append(items, item);
2404 item_index_local.item = item;
2405 zbx_hashset_insert(items_index, &item_index_local, sizeof(item_index_local));
2406 }
2407 }
2408 else
2409 lld_item_update(item_prototype, item_index_local.lld_row, item_index->item, error);
2410 }
2411 }
2412
2413 zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2414
2415 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d items", __function_name, items->values_num);
2416 }
2417
2418 /******************************************************************************
2419 * *
2420 * Function: lld_items_preproc_susbstitute_params_macros *
2421 * *
2422 * Purpose: escaping of a symbols in items preprocessing steps for discovery *
2423 * process *
2424 * *
2425 * Parameters: pp - [IN] the item preprocessing step *
2426 * lld_row - [IN] lld source value *
2427 * itemid - [IN] item ID for logging *
2428 * sub_params - [IN/OUT] the pp params value after substitute *
2429 * error - [IN/OUT] the lld error message *
2430 * *
2431 * Return value: SUCCEED - if preprocessing steps are valid *
2432 * FAIL - if substitute_lld_macros fails *
2433 * *
2434 ******************************************************************************/
lld_items_preproc_susbstitute_params_macros(const zbx_lld_item_preproc_t * pp,const zbx_lld_row_t * lld_row,zbx_uint64_t itemid,char ** sub_params,char ** error)2435 static int lld_items_preproc_susbstitute_params_macros(const zbx_lld_item_preproc_t * pp,
2436 const zbx_lld_row_t * lld_row, zbx_uint64_t itemid, char **sub_params, char **error)
2437 {
2438 int flags1, flags2, params_num = 1;
2439
2440 switch(pp->type)
2441 {
2442 case ZBX_PREPROC_REGSUB:
2443 flags1 = ZBX_MACRO_ANY | ZBX_TOKEN_REGEXP;
2444 flags2 = ZBX_MACRO_ANY | ZBX_TOKEN_REGEXP_OUTPUT;
2445 params_num = 2;
2446 break;
2447 case ZBX_PREPROC_XPATH:
2448 flags1 = ZBX_MACRO_ANY | ZBX_TOKEN_XPATH;
2449 break;
2450 case ZBX_PREPROC_JSONPATH:
2451 flags1 = ZBX_MACRO_ANY | ZBX_TOKEN_JSONPATH;
2452 break;
2453 default:
2454 flags1 = ZBX_MACRO_ANY;
2455 }
2456
2457 if (2 == params_num)
2458 {
2459 char *param1 = NULL, *param2 = NULL;
2460 size_t sub_params_size;
2461
2462 zbx_strsplit(pp->params, '\n', ¶m1, ¶m2);
2463
2464 if (NULL == param2)
2465 {
2466 zbx_free(param1);
2467 *error = zbx_strdcatf(*error, "Cannot %s item: invalid preprocessing step #%d parameters: %s.\n",
2468 (0 != itemid ? "update" : "create"), pp->step, pp->params);
2469 return FAIL;
2470 }
2471
2472 substitute_lld_macros(¶m1, &lld_row->jp_row, flags1, NULL, 0);
2473 substitute_lld_macros(¶m2, &lld_row->jp_row, flags2, NULL, 0);
2474
2475 sub_params_size = strlen(param1) + strlen(param2) + 2;
2476 *sub_params = zbx_malloc(NULL, sub_params_size);
2477
2478 zbx_snprintf(*sub_params, sub_params_size, "%s\n%s", param1, param2);
2479
2480 zbx_free(param1);
2481 zbx_free(param2);
2482 }
2483 else
2484 {
2485 *sub_params = zbx_strdup(NULL, pp->params);
2486 substitute_lld_macros(sub_params, &lld_row->jp_row, flags1, NULL, 0);
2487 }
2488
2489 return SUCCEED;
2490 }
2491
2492 /******************************************************************************
2493 * *
2494 * Function: lld_items_preproc_make *
2495 * *
2496 * Purpose: updates existing items preprocessing operations and create new *
2497 * based on item item prototypes *
2498 * *
2499 * Parameters: item_prototypes - [IN] the item prototypes *
2500 * items - [IN/OUT] sorted list of items *
2501 * error - [IN/OUT] the lld error message *
2502 * *
2503 ******************************************************************************/
lld_items_preproc_make(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items,char ** error)2504 static void lld_items_preproc_make(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items, char **error)
2505 {
2506 int i, j, index, preproc_num;
2507 zbx_lld_item_t *item;
2508 zbx_lld_item_prototype_t *item_proto;
2509 zbx_lld_item_preproc_t *ppsrc, *ppdst;
2510 char *sub_params;
2511
2512 for (i = 0; i < items->values_num; i++)
2513 {
2514 item = (zbx_lld_item_t *)items->values[i];
2515
2516 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
2517 continue;
2518
2519 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
2520 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2521 {
2522 THIS_SHOULD_NEVER_HAPPEN;
2523 continue;
2524 }
2525
2526 zbx_vector_ptr_sort(&item->preproc_ops, lld_item_preproc_sort_by_step);
2527
2528 item_proto = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2529
2530 preproc_num = MAX(item->preproc_ops.values_num, item_proto->preproc_ops.values_num);
2531
2532 for (j = 0; j < preproc_num; j++)
2533 {
2534 if (j >= item->preproc_ops.values_num)
2535 {
2536 ppsrc = (zbx_lld_item_preproc_t *)item_proto->preproc_ops.values[j];
2537 ppdst = (zbx_lld_item_preproc_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_preproc_t));
2538 ppdst->item_preprocid = 0;
2539 ppdst->flags = ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED | ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE;
2540 ppdst->step = ppsrc->step;
2541 ppdst->type = ppsrc->type;
2542
2543 if (SUCCEED != lld_items_preproc_susbstitute_params_macros(ppsrc, item->lld_row,
2544 item->itemid, &sub_params, error))
2545 {
2546 zbx_free(ppdst);
2547 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
2548 break;
2549 }
2550
2551 ppdst->params = sub_params;
2552 zbx_vector_ptr_append(&item->preproc_ops, ppdst);
2553 continue;
2554 }
2555
2556 ppdst = (zbx_lld_item_preproc_t *)item->preproc_ops.values[j];
2557
2558 if (j >= item_proto->preproc_ops.values_num)
2559 {
2560 ppdst->flags &= ~ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED;
2561 continue;
2562 }
2563
2564 ppsrc = (zbx_lld_item_preproc_t *)item_proto->preproc_ops.values[j];
2565
2566 ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED;
2567
2568 if (ppdst->type != ppsrc->type)
2569 {
2570 ppdst->type = ppsrc->type;
2571 ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE;
2572 }
2573
2574 if (ppdst->step != ppsrc->step)
2575 {
2576 /* this should never happen */
2577 ppdst->step = ppsrc->step;
2578 ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP;
2579 }
2580
2581 if (SUCCEED != lld_items_preproc_susbstitute_params_macros(ppsrc, item->lld_row, item->itemid,
2582 &sub_params, error))
2583 {
2584 item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
2585 break;
2586 }
2587
2588 if (0 != strcmp(ppdst->params, sub_params))
2589 {
2590 zbx_free(ppdst->params);
2591 ppdst->params = sub_params;
2592 ppdst->flags |= ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS;
2593 }
2594 else
2595 zbx_free(sub_params);
2596 }
2597 }
2598 }
2599
2600 /******************************************************************************
2601 * *
2602 * Function: lld_item_save *
2603 * *
2604 * Purpose: recursively prepare LLD item bulk insert if any and *
2605 * update dependent items with their masters *
2606 * *
2607 * Parameters: hostid - [IN] parent host id *
2608 * item_prototypes - [IN] item prototypes *
2609 * item - [IN/OUT] item to be saved and set *
2610 * master for dependentent items *
2611 * itemid - [IN/OUT] item id used for insert *
2612 * operations *
2613 * itemdiscoveryid - [IN/OUT] item discovery id used for *
2614 * insert operations *
2615 * db_insert - [IN] prepared item bulk insert *
2616 * db_insert_idiscovery - [IN] prepared item discovery bulk *
2617 * insert *
2618 * *
2619 ******************************************************************************/
lld_item_save(zbx_uint64_t hostid,const zbx_vector_ptr_t * item_prototypes,zbx_lld_item_t * item,zbx_uint64_t * itemid,zbx_uint64_t * itemdiscoveryid,zbx_db_insert_t * db_insert,zbx_db_insert_t * db_insert_idiscovery)2620 static void lld_item_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *item_prototypes, zbx_lld_item_t *item,
2621 zbx_uint64_t *itemid, zbx_uint64_t *itemdiscoveryid, zbx_db_insert_t *db_insert,
2622 zbx_db_insert_t *db_insert_idiscovery)
2623 {
2624 int index;
2625
2626 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
2627 return;
2628
2629 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
2630 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2631 {
2632 THIS_SHOULD_NEVER_HAPPEN;
2633 return;
2634 }
2635
2636 if (0 == item->itemid)
2637 {
2638 const zbx_lld_item_prototype_t *item_prototype;
2639
2640 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2641 item->itemid = (*itemid)++;
2642
2643 zbx_db_insert_add_values(db_insert, item->itemid, item->name, item->key, hostid,
2644 (int)item_prototype->type, (int)item_prototype->value_type,
2645 item->delay, item->history, item->trends,
2646 (int)item_prototype->status, item_prototype->trapper_hosts, item->units,
2647 item_prototype->formula, item_prototype->logtimefmt, item_prototype->valuemapid,
2648 item->params, item->ipmi_sensor, item_prototype->snmp_community, item->snmp_oid,
2649 item_prototype->port, item_prototype->snmpv3_securityname,
2650 (int)item_prototype->snmpv3_securitylevel,
2651 (int)item_prototype->snmpv3_authprotocol, item_prototype->snmpv3_authpassphrase,
2652 (int)item_prototype->snmpv3_privprotocol, item_prototype->snmpv3_privpassphrase,
2653 (int)item_prototype->authtype, item->username,
2654 item->password, item_prototype->publickey, item_prototype->privatekey,
2655 item->description, item_prototype->interfaceid, (int)ZBX_FLAG_DISCOVERY_CREATED,
2656 item_prototype->snmpv3_contextname, item->jmx_endpoint, item->master_itemid,
2657 item->timeout, item->url, item->query_fields, item->posts, item->status_codes,
2658 item_prototype->follow_redirects, item_prototype->post_type, item->http_proxy,
2659 item->headers, item_prototype->retrieve_mode, item_prototype->request_method,
2660 item_prototype->output_format, item->ssl_cert_file, item->ssl_key_file,
2661 item->ssl_key_password, item_prototype->verify_peer, item_prototype->verify_host,
2662 item_prototype->allow_traps);
2663
2664 zbx_db_insert_add_values(db_insert_idiscovery, (*itemdiscoveryid)++, item->itemid,
2665 item->parent_itemid, item_prototype->key);
2666 }
2667
2668 for (index = 0; index < item->dependent_items.values_num; index++)
2669 {
2670 zbx_lld_item_t *dependent;
2671
2672 dependent = (zbx_lld_item_t *)item->dependent_items.values[index];
2673 dependent->master_itemid = item->itemid;
2674 lld_item_save(hostid, item_prototypes, dependent, itemid, itemdiscoveryid, db_insert,
2675 db_insert_idiscovery);
2676 }
2677 }
2678
2679 /******************************************************************************
2680 * *
2681 * Function: lld_item_prepare_update *
2682 * *
2683 * Purpose: prepare sql to update LLD item *
2684 * *
2685 * Parameters: item_prototype - [IN] item prototype *
2686 * item - [IN] item to be updated *
2687 * sql - [IN/OUT] sql buffer pointer used for *
2688 * update operations *
2689 * sql_alloc - [IN/OUT] sql buffer already allocated *
2690 * memory *
2691 * sql_offset - [IN/OUT] offset for writing within sql *
2692 * buffer *
2693 * *
2694 ******************************************************************************/
lld_item_prepare_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_item_t * item,char ** sql,size_t * sql_alloc,size_t * sql_offset)2695 static void lld_item_prepare_update(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_item_t *item,
2696 char **sql, size_t *sql_alloc, size_t *sql_offset)
2697 {
2698 char *value_esc;
2699 const char *d = "";
2700
2701 zbx_strcpy_alloc(sql, sql_alloc, sql_offset, "update items set ");
2702 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_NAME))
2703 {
2704 value_esc = DBdyn_escape_string(item->name);
2705 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "name='%s'", value_esc);
2706 zbx_free(value_esc);
2707 d = ",";
2708 }
2709 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
2710 {
2711 value_esc = DBdyn_escape_string(item->key);
2712 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%skey_='%s'", d, value_esc);
2713 zbx_free(value_esc);
2714 d = ",";
2715 }
2716 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE))
2717 {
2718 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%stype=%d", d, (int)item_prototype->type);
2719 d = ",";
2720 }
2721 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE))
2722 {
2723 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%svalue_type=%d", d, (int)item_prototype->value_type);
2724 d = ",";
2725 }
2726 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DELAY))
2727 {
2728 value_esc = DBdyn_escape_string(item->delay);
2729 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sdelay='%s'", d, value_esc);
2730 zbx_free(value_esc);
2731 d = ",";
2732 }
2733 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY))
2734 {
2735 value_esc = DBdyn_escape_string(item->history);
2736 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%shistory='%s'", d, value_esc);
2737 zbx_free(value_esc);
2738 d = ",";
2739 }
2740 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS))
2741 {
2742 value_esc = DBdyn_escape_string(item->trends);
2743 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%strends='%s'", d, value_esc);
2744 zbx_free(value_esc);
2745 d = ",";
2746 }
2747 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS))
2748 {
2749 value_esc = DBdyn_escape_string(item_prototype->trapper_hosts);
2750 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%strapper_hosts='%s'", d, value_esc);
2751 zbx_free(value_esc);
2752 d = ",";
2753 }
2754 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_UNITS))
2755 {
2756 value_esc = DBdyn_escape_string(item->units);
2757 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sunits='%s'", d, value_esc);
2758 zbx_free(value_esc);
2759 d = ",";
2760 }
2761 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA))
2762 {
2763 value_esc = DBdyn_escape_string(item_prototype->formula);
2764 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sformula='%s'", d, value_esc);
2765 zbx_free(value_esc);
2766 d = ",";
2767 }
2768 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT))
2769 {
2770 value_esc = DBdyn_escape_string(item_prototype->logtimefmt);
2771 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%slogtimefmt='%s'", d, value_esc);
2772 zbx_free(value_esc);
2773 d = ",";
2774 }
2775 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID))
2776 {
2777 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%svaluemapid=%s",
2778 d, DBsql_id_ins(item_prototype->valuemapid));
2779 d = ",";
2780 }
2781 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS))
2782 {
2783 value_esc = DBdyn_escape_string(item->params);
2784 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sparams='%s'", d, value_esc);
2785 zbx_free(value_esc);
2786 d = ",";
2787 }
2788 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR))
2789 {
2790 value_esc = DBdyn_escape_string(item->ipmi_sensor);
2791 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sipmi_sensor='%s'", d, value_esc);
2792 zbx_free(value_esc);
2793 d = ",";
2794 }
2795 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY))
2796 {
2797 value_esc = DBdyn_escape_string(item_prototype->snmp_community);
2798 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmp_community='%s'", d, value_esc);
2799 zbx_free(value_esc);
2800 d = ",";
2801 }
2802 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID))
2803 {
2804 value_esc = DBdyn_escape_string(item->snmp_oid);
2805 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmp_oid='%s'", d, value_esc);
2806 zbx_free(value_esc);
2807 d = ",";
2808 }
2809 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PORT))
2810 {
2811 value_esc = DBdyn_escape_string(item_prototype->port);
2812 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sport='%s'", d, value_esc);
2813 zbx_free(value_esc);
2814 d = ",";
2815 }
2816 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME))
2817 {
2818 value_esc = DBdyn_escape_string(item_prototype->snmpv3_securityname);
2819 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_securityname='%s'", d, value_esc);
2820 zbx_free(value_esc);
2821 d = ",";
2822 }
2823 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL))
2824 {
2825 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_securitylevel=%d", d,
2826 (int)item_prototype->snmpv3_securitylevel);
2827 d = ",";
2828 }
2829 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL))
2830 {
2831 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_authprotocol=%d", d,
2832 (int)item_prototype->snmpv3_authprotocol);
2833 d = ",";
2834 }
2835 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE))
2836 {
2837 value_esc = DBdyn_escape_string(item_prototype->snmpv3_authpassphrase);
2838 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_authpassphrase='%s'", d, value_esc);
2839 zbx_free(value_esc);
2840 d = ",";
2841 }
2842 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL))
2843 {
2844 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_privprotocol=%d", d,
2845 (int)item_prototype->snmpv3_privprotocol);
2846 d = ",";
2847 }
2848 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE))
2849 {
2850 value_esc = DBdyn_escape_string(item_prototype->snmpv3_privpassphrase);
2851 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_privpassphrase='%s'", d, value_esc);
2852 zbx_free(value_esc);
2853 d = ",";
2854 }
2855 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE))
2856 {
2857 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sauthtype=%d", d, (int)item_prototype->authtype);
2858 d = ",";
2859 }
2860 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME))
2861 {
2862 value_esc = DBdyn_escape_string(item->username);
2863 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%susername='%s'", d, value_esc);
2864 zbx_free(value_esc);
2865 d = ",";
2866 }
2867 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD))
2868 {
2869 value_esc = DBdyn_escape_string(item->password);
2870 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%spassword='%s'", d, value_esc);
2871 zbx_free(value_esc);
2872 d = ",";
2873 }
2874 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY))
2875 {
2876 value_esc = DBdyn_escape_string(item_prototype->publickey);
2877 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%spublickey='%s'", d, value_esc);
2878 zbx_free(value_esc);
2879 d = ",";
2880 }
2881 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY))
2882 {
2883 value_esc = DBdyn_escape_string(item_prototype->privatekey);
2884 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sprivatekey='%s'", d, value_esc);
2885 zbx_free(value_esc);
2886 d = ",";
2887 }
2888 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION))
2889 {
2890 value_esc = DBdyn_escape_string(item->description);
2891 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sdescription='%s'", d, value_esc);
2892 zbx_free(value_esc);
2893 d = ",";
2894
2895 }
2896 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID))
2897 {
2898 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sinterfaceid=%s",
2899 d, DBsql_id_ins(item_prototype->interfaceid));
2900 d = ",";
2901 }
2902 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME))
2903 {
2904 value_esc = DBdyn_escape_string(item_prototype->snmpv3_contextname);
2905 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%ssnmpv3_contextname='%s'", d, value_esc);
2906 zbx_free(value_esc);
2907 d = ",";
2908 }
2909 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_JMX_ENDPOINT))
2910 {
2911 value_esc = DBdyn_escape_string(item->jmx_endpoint);
2912 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sjmx_endpoint='%s'", d, value_esc);
2913 zbx_free(value_esc);
2914 d = ",";
2915 }
2916 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_MASTER_ITEM))
2917 {
2918 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%smaster_itemid=%s",
2919 d, DBsql_id_ins(item->master_itemid));
2920 d = ",";
2921 }
2922 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TIMEOUT))
2923 {
2924 value_esc = DBdyn_escape_string(item->timeout);
2925 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%stimeout='%s'", d, value_esc);
2926 zbx_free(value_esc);
2927 d = ",";
2928 }
2929 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_URL))
2930 {
2931 value_esc = DBdyn_escape_string(item->url);
2932 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%surl='%s'", d, value_esc);
2933 zbx_free(value_esc);
2934 d = ",";
2935 }
2936 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_QUERY_FIELDS))
2937 {
2938 value_esc = DBdyn_escape_string(item->query_fields);
2939 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%squery_fields='%s'", d, value_esc);
2940 zbx_free(value_esc);
2941 d = ",";
2942 }
2943 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_POSTS))
2944 {
2945 value_esc = DBdyn_escape_string(item->posts);
2946 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sposts='%s'", d, value_esc);
2947 zbx_free(value_esc);
2948 d = ",";
2949 }
2950 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_STATUS_CODES))
2951 {
2952 value_esc = DBdyn_escape_string(item->status_codes);
2953 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sstatus_codes='%s'", d, value_esc);
2954 zbx_free(value_esc);
2955 d = ",";
2956 }
2957 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_FOLLOW_REDIRECTS))
2958 {
2959 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sfollow_redirects=%d", d,
2960 (int)item_prototype->follow_redirects);
2961 d = ",";
2962 }
2963 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_POST_TYPE))
2964 {
2965 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%spost_type=%d", d, (int)item_prototype->post_type);
2966 d = ",";
2967 }
2968 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HTTP_PROXY))
2969 {
2970 value_esc = DBdyn_escape_string(item->http_proxy);
2971 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%shttp_proxy='%s'", d, value_esc);
2972 zbx_free(value_esc);
2973 d = ",";
2974 }
2975 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HEADERS))
2976 {
2977 value_esc = DBdyn_escape_string(item->headers);
2978 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sheaders='%s'", d, value_esc);
2979 zbx_free(value_esc);
2980 d = ",";
2981 }
2982 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_RETRIEVE_MODE))
2983 {
2984 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sretrieve_mode=%d", d,
2985 (int)item_prototype->retrieve_mode);
2986 d = ",";
2987 }
2988 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_REQUEST_METHOD))
2989 {
2990 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%srequest_method=%d", d,
2991 (int)item_prototype->request_method);
2992 d = ",";
2993 }
2994 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_OUTPUT_FORMAT))
2995 {
2996 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%soutput_format=%d", d,
2997 (int)item_prototype->output_format);
2998 d = ",";
2999 }
3000 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SSL_CERT_FILE))
3001 {
3002 value_esc = DBdyn_escape_string(item->ssl_cert_file);
3003 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sssl_cert_file='%s'", d, value_esc);
3004 zbx_free(value_esc);
3005 d = ",";
3006 }
3007 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_FILE))
3008 {
3009 value_esc = DBdyn_escape_string(item->ssl_key_file);
3010 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sssl_key_file='%s'", d, value_esc);
3011 zbx_free(value_esc);
3012 d = ",";
3013 }
3014 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SSL_KEY_PASSWORD))
3015 {
3016 value_esc = DBdyn_escape_string(item->ssl_key_password);
3017 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sssl_key_password='%s'", d, value_esc);
3018 zbx_free(value_esc);
3019 d = ",";
3020 }
3021 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_PEER))
3022 {
3023 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sverify_peer=%d", d, (int)item_prototype->verify_peer);
3024 d = ",";
3025 }
3026 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VERIFY_HOST))
3027 {
3028 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sverify_host=%d", d, (int)item_prototype->verify_host);
3029 d = ",";
3030 }
3031 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_ALLOW_TRAPS))
3032 {
3033 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, "%sallow_traps=%d", d, (int)item_prototype->allow_traps);
3034 }
3035
3036 zbx_snprintf_alloc(sql, sql_alloc, sql_offset, " where itemid=" ZBX_FS_UI64 ";\n", item->itemid);
3037
3038 DBexecute_overflowed_sql(sql, sql_alloc, sql_offset);
3039 }
3040
3041 /******************************************************************************
3042 * *
3043 * Function: lld_item_discovery_prepare_update *
3044 * *
3045 * Purpose: prepare sql to update key in LLD item discovery *
3046 * *
3047 * Parameters: item_prototype - [IN] item prototype *
3048 * item - [IN] item to be updated *
3049 * sql - [IN/OUT] sql buffer pointer used for *
3050 * update operations *
3051 * sql_alloc - [IN/OUT] sql buffer already allocated *
3052 * memory *
3053 * sql_offset - [IN/OUT] offset for writing within sql *
3054 * buffer *
3055 * *
3056 ******************************************************************************/
lld_item_discovery_prepare_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_item_t * item,char ** sql,size_t * sql_alloc,size_t * sql_offset)3057 static void lld_item_discovery_prepare_update(const zbx_lld_item_prototype_t *item_prototype,
3058 const zbx_lld_item_t *item, char **sql, size_t *sql_alloc, size_t *sql_offset)
3059 {
3060 char *value_esc;
3061
3062 if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
3063 {
3064 value_esc = DBdyn_escape_string(item_prototype->key);
3065 zbx_snprintf_alloc(sql, sql_alloc, sql_offset,
3066 "update item_discovery"
3067 " set key_='%s'"
3068 " where itemid=" ZBX_FS_UI64 ";\n",
3069 value_esc, item->itemid);
3070 zbx_free(value_esc);
3071
3072 DBexecute_overflowed_sql(sql, sql_alloc, sql_offset);
3073 }
3074 }
3075
3076
3077 /******************************************************************************
3078 * *
3079 * Function: lld_items_save *
3080 * *
3081 * Parameters: hostid - [IN] parent host id *
3082 * item_prototypes - [IN] item prototypes *
3083 * items - [IN/OUT] items to save *
3084 * items_index - [IN] LLD item index *
3085 * host_locked - [IN/OUT] host record is locked *
3086 * *
3087 * Return value: SUCCEED - if items were successfully saved or saving was not *
3088 * necessary *
3089 * FAIL - items cannot be saved *
3090 * *
3091 ******************************************************************************/
lld_items_save(zbx_uint64_t hostid,const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items,zbx_hashset_t * items_index,int * host_locked)3092 static int lld_items_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items,
3093 zbx_hashset_t *items_index, int *host_locked)
3094 {
3095 const char *__function_name = "lld_items_save";
3096
3097 int ret = SUCCEED, i, new_items = 0, upd_items = 0;
3098 zbx_lld_item_t *item;
3099 zbx_uint64_t itemid, itemdiscoveryid;
3100 zbx_db_insert_t db_insert, db_insert_idiscovery;
3101 zbx_lld_item_index_t item_index_local;
3102 zbx_vector_uint64_t upd_keys, item_protoids;
3103 char *sql = NULL;
3104 size_t sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0;
3105 const zbx_lld_item_prototype_t *item_prototype;
3106
3107 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3108
3109 zbx_vector_uint64_create(&upd_keys);
3110 zbx_vector_uint64_create(&item_protoids);
3111
3112 if (0 == items->values_num)
3113 goto out;
3114
3115 for (i = 0; i < items->values_num; i++)
3116 {
3117 item = (zbx_lld_item_t *)items->values[i];
3118
3119 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3120 continue;
3121
3122 if (0 == item->itemid)
3123 {
3124 new_items++;
3125 }
3126 else if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE))
3127 {
3128 upd_items++;
3129 if(0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
3130 zbx_vector_uint64_append(&upd_keys, item->itemid);
3131 }
3132 }
3133
3134 if (0 == new_items && 0 == upd_items)
3135 goto out;
3136
3137 if (0 == *host_locked)
3138 {
3139 if (SUCCEED != DBlock_hostid(hostid))
3140 {
3141 /* the host was removed while processing lld rule */
3142 ret = FAIL;
3143 goto out;
3144 }
3145
3146 *host_locked = 1;
3147 }
3148
3149 for (i = 0; i < item_prototypes->values_num; i++)
3150 {
3151 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
3152 zbx_vector_uint64_append(&item_protoids, item_prototype->itemid);
3153 }
3154
3155 if (SUCCEED != DBlock_itemids(&item_protoids))
3156 {
3157 /* the item prototype was removed while processing lld rule */
3158 ret = FAIL;
3159 goto out;
3160 }
3161
3162 if (0 != upd_items)
3163 sql = (char*)zbx_malloc(NULL, sql_alloc);
3164
3165 if (0 != upd_keys.values_num)
3166 {
3167 sql_offset = 0;
3168
3169 zbx_vector_uint64_sort(&upd_keys, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3170
3171 #ifdef HAVE_MYSQL
3172 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update items set key_=concat('#',key_) where");
3173 #else
3174 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update items set key_='#'||key_ where");
3175 #endif
3176 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", upd_keys.values,
3177 upd_keys.values_num);
3178
3179 if (ZBX_DB_OK > DBexecute("%s", sql))
3180 {
3181 ret = FAIL;
3182 goto out;
3183 }
3184
3185 }
3186
3187 if (0 != new_items)
3188 {
3189 itemid = DBget_maxid_num("items", new_items);
3190 itemdiscoveryid = DBget_maxid_num("item_discovery", new_items);
3191
3192 zbx_db_insert_prepare(&db_insert, "items", "itemid", "name", "key_", "hostid", "type", "value_type",
3193 "delay", "history", "trends", "status", "trapper_hosts",
3194 "units", "formula", "logtimefmt", "valuemapid", "params",
3195 "ipmi_sensor", "snmp_community", "snmp_oid", "port", "snmpv3_securityname",
3196 "snmpv3_securitylevel", "snmpv3_authprotocol", "snmpv3_authpassphrase",
3197 "snmpv3_privprotocol", "snmpv3_privpassphrase", "authtype", "username", "password",
3198 "publickey", "privatekey", "description", "interfaceid", "flags", "snmpv3_contextname",
3199 "jmx_endpoint", "master_itemid", "timeout", "url", "query_fields", "posts",
3200 "status_codes", "follow_redirects", "post_type", "http_proxy", "headers",
3201 "retrieve_mode", "request_method", "output_format", "ssl_cert_file", "ssl_key_file",
3202 "ssl_key_password", "verify_peer", "verify_host", "allow_traps", NULL);
3203
3204 zbx_db_insert_prepare(&db_insert_idiscovery, "item_discovery", "itemdiscoveryid", "itemid",
3205 "parent_itemid", "key_", NULL);
3206 }
3207
3208 for (i = 0; i < items->values_num; i++)
3209 {
3210 item = (zbx_lld_item_t *)items->values[i];
3211
3212 /* dependent items based on item prototypes are saved within recursive lld_item_save calls while */
3213 /* saving master item */
3214 if (0 == item->master_itemid)
3215 {
3216 lld_item_save(hostid, item_prototypes, item, &itemid, &itemdiscoveryid, &db_insert,
3217 &db_insert_idiscovery);
3218 }
3219 else
3220 {
3221 item_index_local.parent_itemid = item->master_itemid;
3222 item_index_local.lld_row = (zbx_lld_row_t *)item->lld_row;
3223
3224 /* dependent item based on host item should be saved */
3225 if (NULL == zbx_hashset_search(items_index, &item_index_local))
3226 {
3227 lld_item_save(hostid, item_prototypes, item, &itemid, &itemdiscoveryid, &db_insert,
3228 &db_insert_idiscovery);
3229 }
3230 }
3231
3232 }
3233
3234 if (0 != new_items)
3235 {
3236 zbx_db_insert_execute(&db_insert);
3237 zbx_db_insert_clean(&db_insert);
3238
3239 zbx_db_insert_execute(&db_insert_idiscovery);
3240 zbx_db_insert_clean(&db_insert_idiscovery);
3241
3242 zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3243 }
3244
3245 if (0 != upd_items)
3246 {
3247 int index;
3248
3249 sql_offset = 0;
3250
3251 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3252
3253 for (i = 0; i < items->values_num; i++)
3254 {
3255 item = (zbx_lld_item_t *)items->values[i];
3256
3257 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) ||
3258 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE))
3259 {
3260 continue;
3261 }
3262
3263 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
3264 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3265 {
3266 THIS_SHOULD_NEVER_HAPPEN;
3267 continue;
3268 }
3269
3270 item_prototype = item_prototypes->values[index];
3271
3272 lld_item_prepare_update(item_prototype, item, &sql, &sql_alloc, &sql_offset);
3273 lld_item_discovery_prepare_update(item_prototype, item, &sql, &sql_alloc, &sql_offset);
3274 }
3275
3276 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3277 if (sql_offset > 16)
3278 DBexecute("%s", sql);
3279 }
3280 out:
3281 zbx_free(sql);
3282 zbx_vector_uint64_destroy(&item_protoids);
3283 zbx_vector_uint64_destroy(&upd_keys);
3284 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3285
3286 return ret;
3287 }
3288
3289 /******************************************************************************
3290 * *
3291 * Function: lld_items_preproc_save *
3292 * *
3293 * Purpose: saves/updates/removes item preprocessing operations *
3294 * *
3295 * Parameters: hostid - [IN] parent host id *
3296 * items - [IN] items *
3297 * host_locked - [IN/OUT] host record is locked *
3298 * *
3299 ******************************************************************************/
lld_items_preproc_save(zbx_uint64_t hostid,zbx_vector_ptr_t * items,int * host_locked)3300 static int lld_items_preproc_save(zbx_uint64_t hostid, zbx_vector_ptr_t *items, int *host_locked)
3301 {
3302 const char *__function_name = "lld_items_preproc_save";
3303
3304 int ret = SUCCEED, i, j, new_preproc_num = 0, update_preproc_num = 0, delete_preproc_num = 0;
3305 zbx_lld_item_t *item;
3306 zbx_lld_item_preproc_t *preproc_op;
3307 zbx_vector_uint64_t deleteids;
3308 zbx_db_insert_t db_insert;
3309 char *sql = NULL;
3310 size_t sql_alloc = 0, sql_offset = 0;
3311
3312 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3313
3314 zbx_vector_uint64_create(&deleteids);
3315
3316 for (i = 0; i < items->values_num; i++)
3317 {
3318 item = (zbx_lld_item_t *)items->values[i];
3319
3320 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3321 continue;
3322
3323 for (j = 0; j < item->preproc_ops.values_num; j++)
3324 {
3325 preproc_op = (zbx_lld_item_preproc_t *)item->preproc_ops.values[j];
3326 if (0 == (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_DISCOVERED))
3327 {
3328 zbx_vector_uint64_append(&deleteids, preproc_op->item_preprocid);
3329 continue;
3330 }
3331
3332 if (0 == preproc_op->item_preprocid)
3333 {
3334 new_preproc_num++;
3335 continue;
3336 }
3337
3338 if (0 == (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE))
3339 continue;
3340
3341 update_preproc_num++;
3342 }
3343 }
3344
3345 if (0 == *host_locked && (0 != update_preproc_num || 0 != new_preproc_num || 0 != deleteids.values_num))
3346 {
3347 if (SUCCEED != DBlock_hostid(hostid))
3348 {
3349 /* the host was removed while processing lld rule */
3350 ret = FAIL;
3351 goto out;
3352 }
3353
3354 *host_locked = 1;
3355 }
3356
3357 if (0 != update_preproc_num)
3358 {
3359 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3360 }
3361
3362 if (0 != new_preproc_num)
3363 {
3364 zbx_db_insert_prepare(&db_insert, "item_preproc", "item_preprocid", "itemid", "step", "type", "params",
3365 NULL);
3366 }
3367
3368 for (i = 0; i < items->values_num; i++)
3369 {
3370 item = (zbx_lld_item_t *)items->values[i];
3371
3372 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3373 continue;
3374
3375 for (j = 0; j < item->preproc_ops.values_num; j++)
3376 {
3377 char delim = ' ';
3378
3379 preproc_op = (zbx_lld_item_preproc_t *)item->preproc_ops.values[j];
3380
3381 if (0 == preproc_op->item_preprocid)
3382 {
3383 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), item->itemid, preproc_op->step,
3384 preproc_op->type, preproc_op->params);
3385 continue;
3386 }
3387
3388 if (0 == (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE))
3389 continue;
3390
3391 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update item_preproc set");
3392
3393 if (0 != (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_TYPE))
3394 {
3395 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ctype=%d", delim, preproc_op->type);
3396 delim = ',';
3397 }
3398
3399 if (0 != (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_STEP))
3400 {
3401 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cstep=%d", delim, preproc_op->step);
3402 delim = ',';
3403 }
3404
3405 if (0 != (preproc_op->flags & ZBX_FLAG_LLD_ITEM_PREPROC_UPDATE_PARAMS))
3406 {
3407 char *params_esc;
3408
3409 params_esc = DBdyn_escape_string(preproc_op->params);
3410 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%cparams='%s'", delim, params_esc);
3411
3412 zbx_free(params_esc);
3413 }
3414
3415 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where item_preprocid=" ZBX_FS_UI64 ";\n",
3416 preproc_op->item_preprocid);
3417
3418 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3419 }
3420 }
3421
3422 if (0 != update_preproc_num)
3423 {
3424 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3425
3426 if (16 < sql_offset) /* in ORACLE always present begin..end; */
3427 DBexecute("%s", sql);
3428 }
3429
3430 if (0 != new_preproc_num)
3431 {
3432 zbx_db_insert_autoincrement(&db_insert, "item_preprocid");
3433 zbx_db_insert_execute(&db_insert);
3434 zbx_db_insert_clean(&db_insert);
3435 }
3436
3437 if (0 != deleteids.values_num)
3438 {
3439 sql_offset = 0;
3440 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "delete from item_preproc where");
3441 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "item_preprocid", deleteids.values,
3442 deleteids.values_num);
3443 DBexecute("%s", sql);
3444
3445 delete_preproc_num = deleteids.values_num;
3446 }
3447 out:
3448 zbx_free(sql);
3449 zbx_vector_uint64_destroy(&deleteids);
3450
3451 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() added:%d updated:%d removed:%d", __function_name, new_preproc_num,
3452 update_preproc_num, delete_preproc_num);
3453
3454 return ret;
3455 }
3456
3457 /******************************************************************************
3458 * *
3459 * Function: lld_applications_save *
3460 * *
3461 * Parameters: hostid - [IN] host id *
3462 * applications - [IN/OUT] applications to save *
3463 * application_prototypes - [IN] the application prototypes *
3464 * host_locked - [IN/OUT] host record is locked *
3465 * *
3466 ******************************************************************************/
lld_applications_save(zbx_uint64_t hostid,zbx_vector_ptr_t * applications,const zbx_vector_ptr_t * application_prototypes,int * host_locked)3467 static int lld_applications_save(zbx_uint64_t hostid, zbx_vector_ptr_t *applications,
3468 const zbx_vector_ptr_t *application_prototypes, int *host_locked)
3469 {
3470 const char *__function_name = "lld_applications_save";
3471 int ret = SUCCEED, i, new_applications = 0, new_discoveries = 0, index;
3472 zbx_lld_application_t *application;
3473 const zbx_lld_application_prototype_t *application_prototype;
3474 zbx_uint64_t applicationid, application_discoveryid;
3475 zbx_db_insert_t db_insert, db_insert_discovery;
3476 zbx_vector_uint64_t del_applicationids, del_discoveryids;
3477 char *sql_a = NULL, *sql_ad = NULL, *name;
3478 size_t sql_a_alloc = 0, sql_a_offset = 0, sql_ad_alloc = 0, sql_ad_offset = 0;
3479
3480 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3481
3482 if (0 == applications->values_num)
3483 goto out;
3484
3485 if (0 == *host_locked)
3486 {
3487 if (SUCCEED != DBlock_hostid(hostid))
3488 {
3489 /* the host was removed while processing lld rule */
3490 ret = FAIL;
3491 goto out;
3492 }
3493
3494 *host_locked = 1;
3495 }
3496
3497 zbx_vector_uint64_create(&del_applicationids);
3498 zbx_vector_uint64_create(&del_discoveryids);
3499
3500 /* Count new applications and application discoveries. */
3501 /* Note that an application might have been discovered by another lld rule. */
3502 /* In this case the discovered items will be linked to this application and */
3503 /* new application discovery record, linking the prototype to this */
3504 /* application, will be created. */
3505 for (i = 0; i < applications->values_num; i++)
3506 {
3507 application = (zbx_lld_application_t *)applications->values[i];
3508
3509 if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_REMOVE))
3510 {
3511 zbx_vector_uint64_append(&del_applicationids, application->applicationid);
3512 continue;
3513 }
3514
3515 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3516 continue;
3517
3518 if (0 == application->applicationid)
3519 new_applications++;
3520
3521 if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY))
3522 new_discoveries++;
3523 }
3524
3525 /* insert new applications, application discoveries and prepare a list of applications to be removed */
3526
3527 if (0 != new_applications)
3528 {
3529 applicationid = DBget_maxid_num("applications", new_applications);
3530 zbx_db_insert_prepare(&db_insert, "applications", "applicationid", "hostid", "name", "flags", NULL);
3531 }
3532
3533 if (0 != new_discoveries)
3534 {
3535 application_discoveryid = DBget_maxid_num("application_discovery", new_discoveries);
3536 zbx_db_insert_prepare(&db_insert_discovery, "application_discovery", "application_discoveryid",
3537 "applicationid", "application_prototypeid", "name", NULL);
3538 }
3539
3540 for (i = 0; i < applications->values_num; i++)
3541 {
3542 application = (zbx_lld_application_t *)applications->values[i];
3543
3544 if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY))
3545 {
3546 zbx_vector_uint64_append(&del_discoveryids, application->application_discoveryid);
3547 continue;
3548 }
3549
3550 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3551 continue;
3552
3553 if (FAIL == (index = zbx_vector_ptr_search(application_prototypes,
3554 &application->application_prototypeid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3555 {
3556 THIS_SHOULD_NEVER_HAPPEN;
3557 continue;
3558 }
3559
3560 application_prototype = (zbx_lld_application_prototype_t *)application_prototypes->values[index];
3561
3562 if (0 == application->applicationid)
3563 {
3564 application->applicationid = applicationid++;
3565 zbx_db_insert_add_values(&db_insert, application->applicationid, hostid, application->name,
3566 ZBX_FLAG_DISCOVERY_CREATED);
3567 }
3568
3569 if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
3570 {
3571 if (NULL == sql_a)
3572 DBbegin_multiple_update(&sql_a, &sql_a_alloc, &sql_a_offset);
3573 if (NULL == sql_ad)
3574 DBbegin_multiple_update(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
3575
3576 name = DBdyn_escape_string(application->name);
3577 zbx_snprintf_alloc(&sql_a, &sql_a_alloc, &sql_a_offset,
3578 "update applications set name='%s'"
3579 " where applicationid=" ZBX_FS_UI64 ";\n",
3580 name, application->applicationid);
3581 zbx_free(name);
3582
3583 name = DBdyn_escape_string(application_prototype->name);
3584 zbx_snprintf_alloc(&sql_ad, &sql_ad_alloc, &sql_ad_offset,
3585 "update application_discovery set name='%s'"
3586 " where application_discoveryid=" ZBX_FS_UI64 ";\n",
3587 name, application->application_discoveryid);
3588 zbx_free(name);
3589
3590 DBexecute_overflowed_sql(&sql_a, &sql_a_alloc, &sql_a_offset);
3591 DBexecute_overflowed_sql(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
3592
3593 continue;
3594 }
3595
3596 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY))
3597 continue;
3598
3599 application->application_discoveryid = application_discoveryid++;
3600 zbx_db_insert_add_values(&db_insert_discovery, application->application_discoveryid,
3601 application->applicationid, application->application_prototypeid,
3602 application_prototype->name);
3603 }
3604
3605 if (NULL != sql_a)
3606 {
3607 DBend_multiple_update(&sql_a, &sql_a_alloc, &sql_a_offset);
3608
3609 if (16 < sql_a_offset) /* in ORACLE always present begin..end; */
3610 DBexecute("%s", sql_a);
3611 }
3612
3613 if (NULL != sql_ad)
3614 {
3615 DBend_multiple_update(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
3616
3617 if (16 < sql_ad_offset)
3618 DBexecute("%s", sql_ad);
3619 }
3620
3621 if (0 != del_applicationids.values_num)
3622 {
3623 sql_a_offset = 0;
3624
3625 zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "delete from applications where");
3626 DBadd_condition_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "applicationid", del_applicationids.values,
3627 del_applicationids.values_num);
3628 zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, ";\n");
3629
3630 DBexecute("%s", sql_a);
3631 }
3632
3633 if (0 != del_discoveryids.values_num)
3634 {
3635 sql_ad_offset = 0;
3636
3637 zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "delete from application_discovery where");
3638 DBadd_condition_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "application_discoveryid",
3639 del_discoveryids.values, del_discoveryids.values_num);
3640 zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, ";\n");
3641
3642 DBexecute("%s", sql_ad);
3643 }
3644
3645 zbx_free(sql_a);
3646 zbx_free(sql_ad);
3647
3648 if (0 != new_applications)
3649 {
3650 zbx_db_insert_execute(&db_insert);
3651 zbx_db_insert_clean(&db_insert);
3652
3653 zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3654 }
3655
3656 if (0 != new_discoveries)
3657 {
3658 zbx_db_insert_execute(&db_insert_discovery);
3659 zbx_db_insert_clean(&db_insert_discovery);
3660 }
3661
3662 zbx_vector_uint64_destroy(&del_discoveryids);
3663 zbx_vector_uint64_destroy(&del_applicationids);
3664 out:
3665 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3666
3667 return ret;
3668 }
3669
3670 /******************************************************************************
3671 * *
3672 * Function: lld_item_application_validate *
3673 * *
3674 * Purpose: validates undiscovered item-application link to determine if it *
3675 * should be removed *
3676 * *
3677 * Parameters: items_application - [IN] an item-application link to validate *
3678 * items - [IN] the related items *
3679 * *
3680 * Return value: SUCCEED - item-application link should not be removed *
3681 * FAIL - item-application link should be removed *
3682 * *
3683 * Comments: Undiscovered item-application link must be removed if item was *
3684 * discovered. *
3685 * *
3686 ******************************************************************************/
lld_item_application_validate(const zbx_lld_item_application_t * item_application,const zbx_vector_ptr_t * items)3687 static int lld_item_application_validate(const zbx_lld_item_application_t *item_application,
3688 const zbx_vector_ptr_t *items)
3689 {
3690 int index;
3691
3692 if (FAIL == (index = zbx_vector_ptr_bsearch(items, &item_application->item_ref.itemid,
3693 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3694 {
3695 THIS_SHOULD_NEVER_HAPPEN;
3696 return FAIL;
3697 }
3698
3699 return 0 != (((zbx_lld_item_t *)items->values[index])->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) ? FAIL : SUCCEED;
3700 }
3701
3702 /******************************************************************************
3703 * *
3704 * Function: lld_items_applications_save *
3705 * *
3706 * Parameters: items_applications - [IN] item-application links *
3707 * *
3708 ******************************************************************************/
lld_items_applications_save(zbx_hashset_t * items_applications,const zbx_vector_ptr_t * items)3709 static void lld_items_applications_save(zbx_hashset_t *items_applications, const zbx_vector_ptr_t *items)
3710 {
3711 const char *__function_name = "lld_items_applications_save";
3712 zbx_hashset_iter_t iter;
3713 zbx_lld_item_application_t *item_application;
3714 zbx_vector_uint64_t del_itemappids;
3715 int new_item_applications = 0;
3716 zbx_uint64_t itemappid, applicationid, itemid;
3717 zbx_db_insert_t db_insert;
3718
3719 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3720
3721 if (0 == items_applications->num_data)
3722 goto out;
3723
3724 zbx_vector_uint64_create(&del_itemappids);
3725
3726 /* count new item-application links */
3727 zbx_hashset_iter_reset(items_applications, &iter);
3728
3729 while (NULL != (item_application = (zbx_lld_item_application_t *)zbx_hashset_iter_next(&iter)))
3730 {
3731 if (0 == item_application->itemappid)
3732 new_item_applications++;
3733 }
3734
3735 if (0 != new_item_applications)
3736 {
3737 itemappid = DBget_maxid_num("items_applications", new_item_applications);
3738 zbx_db_insert_prepare(&db_insert, "items_applications", "itemappid", "applicationid", "itemid", NULL);
3739 }
3740
3741 zbx_hashset_iter_reset(items_applications, &iter);
3742
3743 while (NULL != (item_application = (zbx_lld_item_application_t *)zbx_hashset_iter_next(&iter)))
3744 {
3745 if (0 != item_application->itemappid)
3746 {
3747 /* add for removal the old links that aren't discovered and can be removed */
3748 if (0 == (item_application->flags & ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED) &&
3749 FAIL == lld_item_application_validate(item_application, items))
3750 {
3751 zbx_vector_uint64_append(&del_itemappids, item_application->itemappid);
3752 }
3753
3754 continue;
3755 }
3756
3757 if (0 == (applicationid = item_application->application_ref.applicationid))
3758 applicationid = item_application->application_ref.application->applicationid;
3759
3760 if (0 == (itemid = item_application->item_ref.itemid))
3761 itemid = item_application->item_ref.item->itemid;
3762
3763 item_application->itemappid = itemappid++;
3764 zbx_db_insert_add_values(&db_insert, item_application->itemappid, applicationid, itemid);
3765 }
3766
3767 if (0 != new_item_applications)
3768 {
3769 zbx_db_insert_execute(&db_insert);
3770 zbx_db_insert_clean(&db_insert);
3771 }
3772
3773 /* remove deprecated links */
3774 if (0 != del_itemappids.values_num)
3775 {
3776 char *sql = NULL;
3777 size_t sql_alloc = 0, sql_offset = 0;
3778
3779 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from items_applications where");
3780 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemappid", del_itemappids.values,
3781 del_itemappids.values_num);
3782
3783 DBexecute("%s", sql);
3784
3785 zbx_free(sql);
3786 }
3787
3788 zbx_vector_uint64_destroy(&del_itemappids);
3789 out:
3790 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3791 }
3792
3793 /******************************************************************************
3794 * *
3795 * Function: lld_remove_lost_items *
3796 * *
3797 * Purpose: updates item_discovery.lastcheck and item_discovery.ts_delete *
3798 * fields; removes lost resources *
3799 * *
3800 ******************************************************************************/
lld_remove_lost_items(const zbx_vector_ptr_t * items,int lifetime,int lastcheck)3801 static void lld_remove_lost_items(const zbx_vector_ptr_t *items, int lifetime, int lastcheck)
3802 {
3803 const char *__function_name = "lld_remove_lost_items";
3804 char *sql = NULL;
3805 size_t sql_alloc = 0, sql_offset = 0;
3806 zbx_lld_item_t *item;
3807 zbx_vector_uint64_t del_itemids, lc_itemids, ts_itemids;
3808 zbx_vector_uint64_pair_t discovery_itemts;
3809 int i;
3810
3811 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3812
3813 if (0 == items->values_num)
3814 goto out;
3815
3816 zbx_vector_uint64_create(&del_itemids);
3817 zbx_vector_uint64_create(&lc_itemids);
3818 zbx_vector_uint64_create(&ts_itemids);
3819 zbx_vector_uint64_pair_create(&discovery_itemts);
3820
3821 for (i = 0; i < items->values_num; i++)
3822 {
3823 item = (zbx_lld_item_t *)items->values[i];
3824
3825 if (0 == item->itemid)
3826 continue;
3827
3828 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3829 {
3830 int ts_delete = lld_end_of_life(item->lastcheck, lifetime);
3831
3832 if (lastcheck > ts_delete)
3833 {
3834 zbx_vector_uint64_append(&del_itemids, item->itemid);
3835 }
3836 else if (item->ts_delete != ts_delete)
3837 {
3838 zbx_uint64_pair_t itemts;
3839
3840 itemts.first = item->itemid;
3841 itemts.second = ts_delete;
3842 zbx_vector_uint64_pair_append(&discovery_itemts, itemts);
3843 }
3844 }
3845 else
3846 {
3847 zbx_vector_uint64_append(&lc_itemids, item->itemid);
3848 if (0 != item->ts_delete)
3849 zbx_vector_uint64_append(&ts_itemids, item->itemid);
3850 }
3851 }
3852
3853 if (0 == discovery_itemts.values_num && 0 == lc_itemids.values_num && 0 == ts_itemids.values_num &&
3854 0 == del_itemids.values_num)
3855 {
3856 goto clean;
3857 }
3858
3859 /* update item discovery table */
3860
3861 DBbegin();
3862
3863 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3864
3865 for (i = 0; i < discovery_itemts.values_num; i++)
3866 {
3867 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3868 "update item_discovery"
3869 " set ts_delete=%d"
3870 " where itemid=" ZBX_FS_UI64 ";\n",
3871 (int)discovery_itemts.values[i].second, discovery_itemts.values[i].first);
3872
3873 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3874 }
3875
3876 if (0 != lc_itemids.values_num)
3877 {
3878 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update item_discovery set lastcheck=%d where",
3879 lastcheck);
3880 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
3881 lc_itemids.values, lc_itemids.values_num);
3882 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3883
3884 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3885 }
3886
3887 if (0 != ts_itemids.values_num)
3888 {
3889 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update item_discovery set ts_delete=0 where");
3890 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
3891 ts_itemids.values, ts_itemids.values_num);
3892 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
3893
3894 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
3895 }
3896
3897 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3898
3899 if (16 < sql_offset) /* in ORACLE always present begin..end; */
3900 DBexecute("%s", sql);
3901
3902 zbx_free(sql);
3903
3904 /* remove 'lost' items */
3905 if (0 != del_itemids.values_num)
3906 {
3907 zbx_vector_uint64_sort(&del_itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3908 DBdelete_items(&del_itemids);
3909 }
3910
3911 DBcommit();
3912 clean:
3913 zbx_vector_uint64_pair_destroy(&discovery_itemts);
3914 zbx_vector_uint64_destroy(&ts_itemids);
3915 zbx_vector_uint64_destroy(&lc_itemids);
3916 zbx_vector_uint64_destroy(&del_itemids);
3917 out:
3918 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3919 }
3920
3921 /******************************************************************************
3922 * *
3923 * Function: lld_remove_lost_applications *
3924 * *
3925 * Purpose: updates application_discovery lastcheck and ts_delete fields, *
3926 * removes lost resources *
3927 * *
3928 ******************************************************************************/
lld_remove_lost_applications(zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * applications,int lifetime,int lastcheck)3929 static void lld_remove_lost_applications(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *applications,
3930 int lifetime, int lastcheck)
3931 {
3932 const char *__function_name = "lld_remove_lost_applications";
3933 DB_RESULT result;
3934 DB_ROW row;
3935 char *sql = NULL;
3936 size_t sql_alloc = 0, sql_offset = 0;
3937 zbx_vector_uint64_t del_applicationids, del_discoveryids, ts_discoveryids, lc_discoveryids;
3938 zbx_vector_uint64_pair_t discovery_applicationts;
3939 int i, index;
3940 const zbx_lld_application_t *application;
3941 zbx_uint64_t applicationid;
3942
3943 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3944
3945 if (0 == applications->values_num)
3946 goto out;
3947
3948 zbx_vector_uint64_create(&del_applicationids);
3949 zbx_vector_uint64_create(&del_discoveryids);
3950 zbx_vector_uint64_create(&ts_discoveryids);
3951 zbx_vector_uint64_create(&lc_discoveryids);
3952 zbx_vector_uint64_pair_create(&discovery_applicationts);
3953
3954 /* prepare application discovery update vector */
3955 for (i = 0; i < applications->values_num; i++)
3956 {
3957 application = (const zbx_lld_application_t *)applications->values[i];
3958
3959 if (0 == application->applicationid)
3960 continue;
3961
3962 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3963 {
3964 int ts_delete = lld_end_of_life(application->lastcheck, lifetime);
3965
3966 if (lastcheck > ts_delete)
3967 {
3968 zbx_vector_uint64_append(&del_applicationids, application->applicationid);
3969 zbx_vector_uint64_append(&del_discoveryids, application->application_discoveryid);
3970 }
3971 else if (application->ts_delete != ts_delete)
3972 {
3973 zbx_uint64_pair_t applicationts;
3974
3975 applicationts.first = application->application_discoveryid;
3976 applicationts.second = ts_delete;
3977 zbx_vector_uint64_pair_append(&discovery_applicationts, applicationts);
3978 }
3979 }
3980 else
3981 {
3982 zbx_vector_uint64_append(&lc_discoveryids, application->application_discoveryid);
3983 if (0 != application->ts_delete)
3984 zbx_vector_uint64_append(&ts_discoveryids, application->application_discoveryid);
3985 }
3986 }
3987
3988 /* check if the applications are really 'lost' (not discovered by other discovery rules) */
3989 if (0 != del_applicationids.values_num)
3990 {
3991 zbx_vector_uint64_sort(&del_applicationids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3992
3993 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3994 "select ad.applicationid from application_discovery ad,application_prototype ap"
3995 " where ad.application_prototypeid=ap.application_prototypeid"
3996 " and ap.itemid<>" ZBX_FS_UI64
3997 " and",
3998 lld_ruleid);
3999 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ad.applicationid", del_applicationids.values,
4000 del_applicationids.values_num);
4001 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by ad.applicationid desc");
4002
4003 result = DBselect("%s", sql);
4004
4005 sql_offset = 0;
4006
4007 while (NULL != (row = DBfetch(result)))
4008 {
4009 ZBX_STR2UINT64(applicationid, row[0]);
4010
4011 if (FAIL != (index = zbx_vector_uint64_bsearch(&del_applicationids, applicationid,
4012 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
4013 {
4014 zbx_vector_uint64_remove(&del_applicationids, index);
4015 }
4016 }
4017
4018 DBfree_result(result);
4019 }
4020
4021 if (0 == discovery_applicationts.values_num && 0 == del_applicationids.values_num &&
4022 0 == del_discoveryids.values_num && 0 == ts_discoveryids.values_num &&
4023 0 == lc_discoveryids.values_num)
4024 {
4025 goto clean;
4026 }
4027
4028 /* remove lost applications and update application discovery table */
4029
4030 DBbegin();
4031
4032 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
4033
4034 for (i = 0; i < discovery_applicationts.values_num; i++)
4035 {
4036 zbx_uint64_pair_t *applicationts = &(discovery_applicationts.values[i]);
4037
4038 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4039 "update application_discovery"
4040 " set ts_delete=%d"
4041 " where application_discoveryid=" ZBX_FS_UI64 ";\n",
4042 (int)applicationts->second, applicationts->first);
4043
4044 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4045 }
4046
4047 if (0 != del_discoveryids.values_num)
4048 {
4049 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from application_discovery where");
4050 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
4051 del_discoveryids.values, del_discoveryids.values_num);
4052 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4053
4054 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4055 }
4056
4057 if (0 != ts_discoveryids.values_num)
4058 {
4059 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update application_discovery"
4060 " set ts_delete=0 where");
4061 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
4062 ts_discoveryids.values, ts_discoveryids.values_num);
4063 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4064
4065 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4066 }
4067
4068 if (0 != lc_discoveryids.values_num)
4069 {
4070 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update application_discovery"
4071 " set lastcheck=%d where", lastcheck);
4072 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
4073 lc_discoveryids.values, lc_discoveryids.values_num);
4074 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4075
4076 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4077 }
4078
4079 if (0 != del_applicationids.values_num)
4080 {
4081 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from applications where");
4082 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "applicationid", del_applicationids.values,
4083 del_applicationids.values_num);
4084 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
4085
4086 DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
4087 }
4088
4089 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
4090
4091 if (16 < sql_offset) /* in ORACLE always present begin..end; */
4092 DBexecute("%s", sql);
4093
4094 DBcommit();
4095 clean:
4096 zbx_free(sql);
4097
4098 zbx_vector_uint64_pair_destroy(&discovery_applicationts);
4099 zbx_vector_uint64_destroy(&lc_discoveryids);
4100 zbx_vector_uint64_destroy(&ts_discoveryids);
4101 zbx_vector_uint64_destroy(&del_discoveryids);
4102 zbx_vector_uint64_destroy(&del_applicationids);
4103 out:
4104 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4105 }
4106
lld_item_links_populate(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * lld_rows,zbx_hashset_t * items_index)4107 static void lld_item_links_populate(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *lld_rows,
4108 zbx_hashset_t *items_index)
4109 {
4110 int i, j;
4111 zbx_lld_item_prototype_t *item_prototype;
4112 zbx_lld_item_index_t *item_index, item_index_local;
4113 zbx_lld_item_link_t *item_link;
4114
4115 for (i = 0; i < item_prototypes->values_num; i++)
4116 {
4117 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
4118 item_index_local.parent_itemid = item_prototype->itemid;
4119
4120 for (j = 0; j < lld_rows->values_num; j++)
4121 {
4122 item_index_local.lld_row = (zbx_lld_row_t *)lld_rows->values[j];
4123
4124 if (NULL == (item_index = (zbx_lld_item_index_t *)zbx_hashset_search(items_index, &item_index_local)))
4125 continue;
4126
4127 if (0 == (item_index->item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
4128 continue;
4129
4130 item_link = (zbx_lld_item_link_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_link_t));
4131
4132 item_link->parent_itemid = item_index->item->parent_itemid;
4133 item_link->itemid = item_index->item->itemid;
4134
4135 zbx_vector_ptr_append(&item_index_local.lld_row->item_links, item_link);
4136 }
4137 }
4138 }
4139
lld_item_links_sort(zbx_vector_ptr_t * lld_rows)4140 void lld_item_links_sort(zbx_vector_ptr_t *lld_rows)
4141 {
4142 int i;
4143
4144 for (i = 0; i < lld_rows->values_num; i++)
4145 {
4146 zbx_lld_row_t *lld_row = (zbx_lld_row_t *)lld_rows->values[i];
4147
4148 zbx_vector_ptr_sort(&lld_row->item_links, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4149 }
4150 }
4151
4152 /******************************************************************************
4153 * *
4154 * Function: lld_application_prototypes_get *
4155 * *
4156 * Purpose: gets the discovery rule application prototypes from database *
4157 * *
4158 * Parameters: lld_ruleid - [IN] the discovery rule id *
4159 * application_prototypes - [OUT] the applications prototypes *
4160 * defined for the discovery rule, *
4161 * sorted by prototype id *
4162 * *
4163 ******************************************************************************/
lld_application_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * application_prototypes)4164 static void lld_application_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *application_prototypes)
4165 {
4166 const char *__function_name = "lld_application_prototypes_get";
4167 DB_RESULT result;
4168 DB_ROW row;
4169 zbx_lld_application_prototype_t *application_prototype;
4170
4171 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4172
4173 result = DBselect(
4174 "select application_prototypeid,name"
4175 " from application_prototype"
4176 " where itemid=" ZBX_FS_UI64,
4177 lld_ruleid);
4178
4179 while (NULL != (row = DBfetch(result)))
4180 {
4181 application_prototype = (zbx_lld_application_prototype_t *)zbx_malloc(NULL,
4182 sizeof(zbx_lld_application_prototype_t));
4183
4184 ZBX_STR2UINT64(application_prototype->application_prototypeid, row[0]);
4185 application_prototype->itemid = lld_ruleid;
4186 application_prototype->name = zbx_strdup(NULL, row[1]);
4187
4188 zbx_vector_ptr_append(application_prototypes, application_prototype);
4189 }
4190 DBfree_result(result);
4191
4192 zbx_vector_ptr_sort(application_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4193
4194 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __function_name, application_prototypes->values_num);
4195 }
4196
4197 /******************************************************************************
4198 * *
4199 * Function: lld_item_application_prototypes_get *
4200 * *
4201 * Purpose: gets the discovery rule item-application link prototypes from *
4202 * database *
4203 * *
4204 * Parameters: item_prototypes - [IN/OUT] item prototypes *
4205 * application_prototypes - [IN] the application prototypes *
4206 * defined for the discovery rule *
4207 * *
4208 ******************************************************************************/
lld_item_application_prototypes_get(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * application_prototypes)4209 static void lld_item_application_prototypes_get(const zbx_vector_ptr_t *item_prototypes,
4210 const zbx_vector_ptr_t *application_prototypes)
4211 {
4212 const char *__function_name = "lld_item_application_prototypes_get";
4213 DB_RESULT result;
4214 DB_ROW row;
4215 int i, index;
4216 zbx_uint64_t application_prototypeid, itemid;
4217 zbx_vector_uint64_t item_prototypeids;
4218 char *sql = NULL;
4219 size_t sql_alloc = 0, sql_offset = 0;
4220 zbx_lld_item_application_ref_t *item_application_prototype;
4221 zbx_lld_item_prototype_t *item_prototype;
4222
4223 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4224
4225 zbx_vector_uint64_create(&item_prototypeids);
4226
4227 /* get item prototype links to application prototypes */
4228
4229 for (i = 0; i < item_prototypes->values_num; i++)
4230 {
4231 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
4232
4233 zbx_vector_uint64_append(&item_prototypeids, item_prototype->itemid);
4234 }
4235
4236 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4237 "select application_prototypeid,itemid"
4238 " from item_application_prototype"
4239 " where");
4240
4241 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
4242 item_prototypeids.values, item_prototypeids.values_num);
4243
4244 result = DBselect("%s", sql);
4245
4246 while (NULL != (row = DBfetch(result)))
4247 {
4248 ZBX_STR2UINT64(application_prototypeid, row[0]);
4249
4250 if (FAIL == (index = zbx_vector_ptr_search(application_prototypes, &application_prototypeid,
4251 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4252 {
4253 THIS_SHOULD_NEVER_HAPPEN;
4254 continue;
4255 }
4256
4257 item_application_prototype = (zbx_lld_item_application_ref_t *)zbx_malloc(NULL,
4258 sizeof(zbx_lld_item_application_ref_t));
4259
4260 item_application_prototype->application_prototype = (zbx_lld_application_prototype_t *)application_prototypes->values[index];
4261 item_application_prototype->applicationid = 0;
4262
4263 ZBX_STR2UINT64(itemid, row[1]);
4264 index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4265 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
4266
4267 zbx_vector_ptr_append(&item_prototype->applications, item_application_prototype);
4268 }
4269 DBfree_result(result);
4270
4271 /* get item prototype links to real applications */
4272
4273 sql_offset = 0;
4274 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4275 "select applicationid,itemid"
4276 " from items_applications"
4277 " where");
4278
4279 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
4280 item_prototypeids.values, item_prototypeids.values_num);
4281
4282 result = DBselect("%s", sql);
4283
4284 while (NULL != (row = DBfetch(result)))
4285 {
4286 item_application_prototype = (zbx_lld_item_application_ref_t *)zbx_malloc(NULL,
4287 sizeof(zbx_lld_item_application_ref_t));
4288
4289 item_application_prototype->application_prototype = NULL;
4290 ZBX_STR2UINT64(item_application_prototype->applicationid, row[0]);
4291
4292 ZBX_STR2UINT64(itemid, row[1]);
4293 index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4294 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
4295
4296 zbx_vector_ptr_append(&item_prototype->applications, item_application_prototype);
4297 }
4298 DBfree_result(result);
4299
4300 zbx_free(sql);
4301 zbx_vector_uint64_destroy(&item_prototypeids);
4302
4303 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4304 }
4305
4306 /******************************************************************************
4307 * *
4308 * Function: lld_applications_get *
4309 * *
4310 * Purpose: gets applications previously discovered by the discovery rule *
4311 * *
4312 * Parameters: lld_ruleid - [IN] the discovery rule id *
4313 * applications - [OUT] the applications *
4314 * *
4315 ******************************************************************************/
lld_applications_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * applications)4316 static void lld_applications_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *applications)
4317 {
4318 const char *__function_name = "lld_applications_get";
4319 DB_RESULT result;
4320 DB_ROW row;
4321 zbx_lld_application_t *application;
4322
4323 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4324
4325 result = DBselect(
4326 "select a.applicationid,a.name,ap.application_prototypeid,ad.lastcheck,ad.ts_delete,ad.name,"
4327 "ad.application_discoveryid"
4328 " from applications a,application_discovery ad,application_prototype ap"
4329 " where ap.itemid=" ZBX_FS_UI64
4330 " and ad.application_prototypeid=ap.application_prototypeid"
4331 " and a.applicationid=ad.applicationid",
4332 lld_ruleid);
4333
4334 while (NULL != (row = DBfetch(result)))
4335 {
4336 application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
4337
4338 ZBX_STR2UINT64(application->applicationid, row[0]);
4339 ZBX_STR2UINT64(application->application_prototypeid, row[2]);
4340 ZBX_STR2UINT64(application->application_discoveryid, row[6]);
4341 application->name = zbx_strdup(NULL, row[1]);
4342 application->lastcheck = atoi(row[3]);
4343 application->ts_delete = atoi(row[4]);
4344 application->name_proto = zbx_strdup(NULL, row[5]);
4345 application->name_orig = NULL;
4346 application->flags = ZBX_FLAG_LLD_APPLICATION_UNSET;
4347 application->lld_row = NULL;
4348
4349 zbx_vector_ptr_append(applications, application);
4350 }
4351 DBfree_result(result);
4352
4353 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d applications", __function_name, applications->values_num);
4354 }
4355
4356 /******************************************************************************
4357 * *
4358 * Function: lld_application_make *
4359 * *
4360 * Purpose: create a new application or mark an existing application as *
4361 * discovered based on prototype and lld row *
4362 * *
4363 * Parameters: application_prototype - [IN] the application prototype *
4364 * lld_row - [IN] the lld row *
4365 * applications - [IN/OUT] the applications *
4366 * applications_index - [IN/OUT] the application index by *
4367 * prototype id and lld row *
4368 * *
4369 ******************************************************************************/
lld_application_make(const zbx_lld_application_prototype_t * application_prototype,const zbx_lld_row_t * lld_row,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index)4370 static void lld_application_make(const zbx_lld_application_prototype_t *application_prototype,
4371 const zbx_lld_row_t *lld_row, zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index)
4372 {
4373 const char *__function_name = "lld_application_make";
4374 zbx_lld_application_t *application;
4375 zbx_lld_application_index_t *application_index, application_index_local;
4376 struct zbx_json_parse *jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
4377 char *buffer = NULL;
4378
4379 zabbix_log(LOG_LEVEL_DEBUG, "In %s(), proto %s", __function_name, application_prototype->name);
4380
4381 application_index_local.application_prototypeid = application_prototype->application_prototypeid;
4382 application_index_local.lld_row = lld_row;
4383
4384 if (NULL == (application_index = (zbx_lld_application_index_t *)zbx_hashset_search(applications_index, &application_index_local)))
4385 {
4386 application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
4387 application->applicationid = 0;
4388 application->application_prototypeid = application_prototype->application_prototypeid;
4389 application->application_discoveryid = 0;
4390 application->ts_delete = 0;
4391
4392 application->name = zbx_strdup(NULL, application_prototype->name);
4393 substitute_lld_macros(&application->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
4394 zbx_lrtrim(application->name, ZBX_WHITESPACE);
4395
4396 application->name_proto = zbx_strdup(NULL, application_prototype->name);
4397 application->name_orig = NULL;
4398 application->flags = ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY;
4399 application->lld_row = lld_row;
4400
4401 zbx_vector_ptr_append(applications, application);
4402
4403 application_index_local.application = application;
4404 zbx_hashset_insert(applications_index, &application_index_local, sizeof(zbx_lld_application_index_t));
4405
4406 zabbix_log(LOG_LEVEL_TRACE, "%s(): created new application, proto %s, name %s", __function_name,
4407 application_prototype->name, application->name);
4408 }
4409 else
4410 {
4411 application = application_index->application;
4412
4413 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
4414 {
4415 buffer = zbx_strdup(NULL, application_prototype->name);
4416 substitute_lld_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
4417 zbx_lrtrim(buffer, ZBX_WHITESPACE);
4418
4419 if (0 != strcmp(application->name, buffer))
4420 {
4421 application->name_orig = application->name;
4422 application->name = buffer;
4423 application->flags |= ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME;
4424 zabbix_log(LOG_LEVEL_TRACE, "%s(): updated application name to %s", __function_name,
4425 application->name);
4426 }
4427 else
4428 zbx_free(buffer);
4429 }
4430 }
4431
4432 application->flags |= ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4433
4434 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4435 }
4436
4437 /******************************************************************************
4438 * *
4439 * Function: lld_applications_make *
4440 * *
4441 * Purpose: makes new applications and marks old applications as discovered *
4442 * based on application prototypes and lld rows *
4443 * *
4444 * Parameters: application_prototypes - [IN] the application prototypes *
4445 * lld_rows - [IN] the lld rows *
4446 * applications - [IN/OUT] the applications *
4447 * applications_index - [OUT] the application index by *
4448 * prototype id and lld row *
4449 * *
4450 ******************************************************************************/
lld_applications_make(const zbx_vector_ptr_t * application_prototypes,const zbx_vector_ptr_t * lld_rows,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index)4451 static void lld_applications_make(const zbx_vector_ptr_t *application_prototypes,
4452 const zbx_vector_ptr_t *lld_rows, zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index)
4453 {
4454 const char *__function_name = "lld_applications_make";
4455 int i, j;
4456 zbx_lld_application_t *application;
4457 zbx_lld_row_t *lld_row;
4458 zbx_lld_application_index_t application_index_local;
4459 char *buffer = NULL;
4460
4461 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4462
4463 /* index existing applications */
4464
4465 for (i = 0; i < applications->values_num; i++)
4466 {
4467 application = (zbx_lld_application_t *)applications->values[i];
4468
4469 for (j = 0; j < lld_rows->values_num; j++)
4470 {
4471 lld_row = (zbx_lld_row_t *)lld_rows->values[j];
4472
4473 buffer = zbx_strdup(buffer, application->name_proto);
4474 substitute_lld_macros(&buffer, &lld_row->jp_row, ZBX_MACRO_ANY, NULL, 0);
4475 zbx_lrtrim(buffer, ZBX_WHITESPACE);
4476
4477 if (0 == strcmp(application->name, buffer))
4478 {
4479 application_index_local.application_prototypeid = application->application_prototypeid;
4480 application_index_local.lld_row = lld_row;
4481 application_index_local.application = application;
4482 zbx_hashset_insert(applications_index, &application_index_local,
4483 sizeof(application_index_local));
4484
4485 application->lld_row = lld_row;
4486 }
4487 }
4488 }
4489
4490 zbx_free(buffer);
4491
4492 /* make the applications */
4493 for (i = 0; i < application_prototypes->values_num; i++)
4494 {
4495 for (j = 0; j < lld_rows->values_num; j++)
4496 {
4497 lld_application_make((zbx_lld_application_prototype_t *)application_prototypes->values[i],
4498 (zbx_lld_row_t *)lld_rows->values[j], applications, applications_index);
4499 }
4500 }
4501
4502 zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4503
4504 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d applications", __function_name, applications->values_num);
4505 }
4506
4507 /******************************************************************************
4508 * *
4509 * Function: lld_applications_validate *
4510 * *
4511 * Purpose: validates the discovered and renamed applications *
4512 * *
4513 * Parameters: hostid - [IN] host id *
4514 * lld_ruleid - [IN] the discovery rule id *
4515 * applications - [IN/OUT] the applications *
4516 * applications_index - [OUT] the application index by *
4517 * prototype id and lld row *
4518 * error - [IN/OUT] the lld error message *
4519 * *
4520 ******************************************************************************/
lld_applications_validate(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index,char ** error)4521 static void lld_applications_validate(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *applications,
4522 zbx_hashset_t *applications_index, char **error)
4523 {
4524 const char *__function_name = "lld_applications_validate";
4525 int i, j, index;
4526 DB_RESULT result;
4527 DB_ROW row;
4528 zbx_lld_application_t *application, *new_application, application_local;
4529 char *sql = NULL;
4530 size_t sql_alloc = 0, sql_offset = 0;
4531 zbx_vector_str_t names_new, names_old;
4532 zbx_lld_application_index_t *application_index, application_index_local;
4533
4534 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4535
4536 if (0 == applications->values_num)
4537 goto out;
4538
4539 zbx_vector_str_create(&names_new);
4540 zbx_vector_str_create(&names_old);
4541
4542 /* check for conflicting application names in the discovered applications */
4543
4544 for (i = 0; i < applications->values_num; i++)
4545 {
4546 application = (zbx_lld_application_t *)applications->values[i];
4547
4548 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
4549 continue;
4550
4551 if (0 != application->applicationid && 0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
4552 continue;
4553
4554 /* iterate in reverse order so existing applications would have more priority */
4555 /* than new applications which have 0 applicationid and therefore are located */
4556 /* at the beginning of applications vector which is sorted by applicationid */
4557 for (j = applications->values_num - 1; j > i; j--)
4558 {
4559 zbx_lld_application_t *application_compare = (zbx_lld_application_t *)applications->values[j];
4560
4561 if (0 != strcmp(application->name, application_compare->name))
4562 continue;
4563
4564 /* Applications with matching names are validated depending on their prototypes. */
4565 /* If they are discovered by different prototypes we must fail with appropriate */
4566 /* lld error. */
4567 /* Otherwise we 'merge' application by updating index of the validated */
4568 /* validated application to point at the application with the same name. */
4569 /* In both cases the validated application is flagged as non-discovered. */
4570 application->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
4571
4572 /* fail if application has different prototype */
4573 if (application->application_prototypeid != application_compare->application_prototypeid)
4574 {
4575 *error = zbx_strdcatf(*error, "Cannot %s application:"
4576 " application with the same name \"%s\" already exists.\n",
4577 (0 != application->applicationid ? "update" : "create"),
4578 application->name);
4579
4580 break;
4581 }
4582
4583 /* update application index to use the matching application */
4584
4585 application_index_local.application_prototypeid = application->application_prototypeid;
4586 application_index_local.lld_row = application->lld_row;
4587
4588 if (NULL == (application_index = (zbx_lld_application_index_t *)zbx_hashset_search(applications_index,
4589 &application_index_local)))
4590 {
4591 THIS_SHOULD_NEVER_HAPPEN;
4592 break;
4593 }
4594
4595 application_index->application = application_compare;
4596 break;
4597 }
4598
4599 /* Prepare name lists to resolve naming conflicts with applications */
4600 /* discovered by other discovery rules: */
4601 /* names_new - to check if discovered/renamed application names */
4602 /* don't match existing applications discovered by */
4603 /* other discovery rules */
4604 /* names_old - to check if renamed applications were also */
4605 /* discovered by other discovery rules */
4606 if (i == j)
4607 {
4608 zbx_vector_str_append(&names_new, application->name);
4609
4610 if (NULL != application->name_orig)
4611 zbx_vector_str_append(&names_old, application->name_orig);
4612 }
4613 }
4614
4615 /* validate new/renamed application names against applications discovered */
4616 /* by other discovery rules */
4617
4618 if (0 != names_new.values_num)
4619 {
4620 zbx_vector_str_sort(&names_new, ZBX_DEFAULT_STR_COMPARE_FUNC);
4621
4622 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4623 "select applicationid,name,flags"
4624 " from applications"
4625 " where hostid=" ZBX_FS_UI64
4626 " and",
4627 hostid);
4628 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
4629 (const char **)names_new.values, names_new.values_num);
4630
4631 result = DBselect("%s", sql);
4632
4633 application_local.flags = ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4634
4635 while (NULL != (row = DBfetch(result)))
4636 {
4637 application_local.name = row[1];
4638
4639 if (FAIL == (index = zbx_vector_ptr_search(applications, &application_local,
4640 lld_application_compare_name)))
4641 {
4642 THIS_SHOULD_NEVER_HAPPEN;
4643 continue;
4644 }
4645
4646 application = (zbx_lld_application_t *)applications->values[index];
4647
4648 /* only discovered applications can be 'shared' between discovery rules */
4649 if (ZBX_FLAG_DISCOVERY_CREATED != atoi(row[2]))
4650 {
4651 /* conflicting application name, reset discovery flags */
4652 application->flags = ZBX_FLAG_LLD_APPLICATION_UNSET;
4653
4654 *error = zbx_strdcatf(*error, "Cannot create application:"
4655 " non-discovered application"
4656 " with the same name \"%s\" already exists.\n",
4657 application->name);
4658
4659 continue;
4660 }
4661
4662 if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
4663 {
4664 /* During discovery process the application was renamed to an */
4665 /* application already discovered by another discovery rule. */
4666 /* In this case we must delete the old application and relink */
4667 /* its items to the application we have found. */
4668
4669 /* create a pseudo application to remove the renamed application */
4670
4671 new_application = (zbx_lld_application_t *)zbx_malloc(NULL,
4672 sizeof(zbx_lld_application_t));
4673
4674 memset(new_application, 0, sizeof(zbx_lld_application_t));
4675 new_application->applicationid = application->applicationid;
4676 new_application->flags = ZBX_FLAG_LLD_APPLICATION_REMOVE;
4677
4678 zbx_vector_ptr_append(applications, new_application);
4679
4680 /* update application flags so that instead of renaming it a new */
4681 /* discovery record is created */
4682
4683 application->application_discoveryid = 0;
4684 application->flags &= ~ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME;
4685 application->flags |= ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY;
4686 }
4687
4688 /* reuse application created by another discovery rule */
4689 ZBX_STR2UINT64(application->applicationid, row[0]);
4690 }
4691 DBfree_result(result);
4692 }
4693
4694 /* if an application shared with other discovery rule has been renamed we must */
4695 /* create a new application with the new name instead of renaming the old one */
4696
4697 if (0 != names_old.values_num)
4698 {
4699 sql_offset = 0;
4700
4701 zbx_vector_str_sort(&names_old, ZBX_DEFAULT_STR_COMPARE_FUNC);
4702
4703 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4704 "select a.name"
4705 " from applications a,application_discovery ad,application_prototype ap"
4706 " where a.applicationid=ad.applicationid"
4707 " and ad.application_prototypeid=ap.application_prototypeid"
4708 " and a.hostid=" ZBX_FS_UI64
4709 " and ap.itemid<>" ZBX_FS_UI64
4710 " and",
4711 hostid, lld_ruleid);
4712 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "a.name",
4713 (const char **)names_old.values, names_old.values_num);
4714
4715 result = DBselect("%s", sql);
4716
4717 application_local.flags = ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4718
4719 while (NULL != (row = DBfetch(result)))
4720 {
4721 application_local.name_orig = row[0];
4722
4723 if (FAIL == (index = zbx_vector_ptr_search(applications, &application_local,
4724 lld_application_compare_name_orig)))
4725 {
4726 THIS_SHOULD_NEVER_HAPPEN;
4727 continue;
4728 }
4729
4730 application = (zbx_lld_application_t *)applications->values[index];
4731
4732 /* add a pseudo application to remove the application discovery record */
4733 /* of the shared application and current discovery rule */
4734 new_application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
4735 memset(new_application, 0, sizeof(zbx_lld_application_t));
4736 new_application->applicationid = application->applicationid;
4737 new_application->application_prototypeid = application->application_prototypeid;
4738 new_application->application_discoveryid = application->application_discoveryid;
4739 new_application->flags = ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY;
4740 zbx_vector_ptr_append(applications, new_application);
4741
4742 /* reset applicationid, application_discoveryid and flags */
4743 /* so a new application is created instead of renaming the shared one */
4744 application->applicationid = 0;
4745 application->application_discoveryid = 0;
4746 application->flags = ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY |
4747 ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
4748 }
4749 DBfree_result(result);
4750 }
4751
4752 zbx_vector_str_destroy(&names_old);
4753 zbx_vector_str_destroy(&names_new);
4754
4755 zbx_free(sql);
4756
4757 zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4758 out:
4759 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4760 }
4761
4762 /******************************************************************************
4763 * *
4764 * Function: lld_items_applications_get *
4765 * *
4766 * Purpose: gets item-application links for the lld rule *
4767 * *
4768 * Parameters: lld_rule - [IN] the lld rule *
4769 * items_applications - [OUT] the item-application links *
4770 * *
4771 ******************************************************************************/
lld_items_applications_get(zbx_uint64_t lld_ruleid,zbx_hashset_t * items_applications)4772 static void lld_items_applications_get(zbx_uint64_t lld_ruleid, zbx_hashset_t *items_applications)
4773 {
4774 const char *__function_name = "lld_items_applications_get";
4775 DB_RESULT result;
4776 DB_ROW row;
4777 zbx_lld_item_application_t item_application;
4778
4779 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4780
4781 result = DBselect(
4782 "select ia.itemappid,ia.itemid,ia.applicationid"
4783 " from items_applications ia,item_discovery id1,item_discovery id2"
4784 " where id1.itemid=ia.itemid"
4785 " and id1.parent_itemid=id2.itemid"
4786 " and id2.parent_itemid=" ZBX_FS_UI64,
4787 lld_ruleid);
4788
4789 item_application.application_ref.application = NULL;
4790 item_application.item_ref.item = NULL;
4791
4792 while (NULL != (row = DBfetch(result)))
4793 {
4794 ZBX_STR2UINT64(item_application.itemappid, row[0]);
4795 ZBX_STR2UINT64(item_application.item_ref.itemid, row[1]);
4796 ZBX_STR2UINT64(item_application.application_ref.applicationid, row[2]);
4797 item_application.flags = ZBX_FLAG_LLD_ITEM_APPLICATION_UNSET;
4798
4799 zbx_hashset_insert(items_applications, &item_application, sizeof(zbx_lld_item_application_t));
4800 }
4801 DBfree_result(result);
4802
4803 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d links", __function_name, items_applications->num_data);
4804 }
4805
4806 /******************************************************************************
4807 * *
4808 * Function: lld_items_applications_make *
4809 * *
4810 * Purpose: makes new item-application links and marks existing links as *
4811 * discovered based on item_prototypes applications links *
4812 * *
4813 * Parameters: item_prototypes - [IN] the item prototypes *
4814 * items - [IN] the items *
4815 * applications_index - [IN] the application index by *
4816 * prototype id and lld row *
4817 * items_applications - [IN/OUT] the item-application links *
4818 * *
4819 ******************************************************************************/
lld_items_applications_make(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * items,zbx_hashset_t * applications_index,zbx_hashset_t * items_applications)4820 static void lld_items_applications_make(const zbx_vector_ptr_t *item_prototypes, const zbx_vector_ptr_t *items,
4821 zbx_hashset_t *applications_index, zbx_hashset_t *items_applications)
4822 {
4823 const char *__function_name = "lld_items_applications_make";
4824 int i, j, index;
4825 zbx_lld_item_application_t *item_application, item_application_local;
4826 zbx_lld_application_t *application;
4827 zbx_lld_item_prototype_t *item_prototype;
4828 zbx_lld_item_t *item;
4829 zbx_lld_item_application_ref_t *itemapp_prototype;
4830 zbx_lld_application_index_t *application_index, application_index_local;
4831
4832 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4833
4834 item_application_local.itemappid = 0;
4835 item_application_local.flags = ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED;
4836
4837 for (i = 0; i < items->values_num; i++)
4838 {
4839 item = (zbx_lld_item_t *)items->values[i];
4840
4841 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
4842 continue;
4843
4844 /* if item is discovered its prototype must be in item_prototypes vector */
4845 index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
4846 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4847 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
4848
4849 application_index_local.lld_row = item->lld_row;
4850
4851 if (0 == (item_application_local.item_ref.itemid = item->itemid))
4852 item_application_local.item_ref.item = item;
4853 else
4854 item_application_local.item_ref.item = NULL;
4855
4856 for (j = 0; j < item_prototype->applications.values_num; j++)
4857 {
4858 itemapp_prototype = (zbx_lld_item_application_ref_t *)item_prototype->applications.values[j];
4859
4860 if (NULL != itemapp_prototype->application_prototype)
4861 {
4862 application_index_local.application_prototypeid =
4863 itemapp_prototype->application_prototype->application_prototypeid;
4864
4865 if (NULL == (application_index = (zbx_lld_application_index_t *)zbx_hashset_search(applications_index,
4866 &application_index_local)))
4867 {
4868 continue;
4869 }
4870
4871 application = application_index->application;
4872
4873 if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
4874 continue;
4875
4876 if (0 == (item_application_local.application_ref.applicationid =
4877 application->applicationid))
4878 {
4879 item_application_local.application_ref.application = application;
4880 }
4881 else
4882 item_application_local.application_ref.application = NULL;
4883 }
4884 else
4885 {
4886 item_application_local.application_ref.application = NULL;
4887 item_application_local.application_ref.applicationid = itemapp_prototype->applicationid;
4888 }
4889
4890 if (NULL == (item_application = (zbx_lld_item_application_t *)zbx_hashset_search(items_applications,
4891 &item_application_local)))
4892 {
4893 item_application = (zbx_lld_item_application_t *)zbx_hashset_insert(items_applications, &item_application_local,
4894 sizeof(zbx_lld_item_application_t));
4895 }
4896
4897 item_application->flags = ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED;
4898 }
4899 }
4900
4901 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d links", __function_name, items_applications->num_data);
4902 }
4903
4904 /******************************************************************************
4905 * *
4906 * Function: lld_item_prototypes_get *
4907 * *
4908 * Purpose: load discovery rule item prototypes *
4909 * *
4910 * Parameters: lld_ruleid - [IN] the discovery rule id *
4911 * item_prototypes - [OUT] the item prototypes *
4912 * *
4913 ******************************************************************************/
lld_item_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * item_prototypes)4914 static void lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *item_prototypes)
4915 {
4916 const char *__function_name = "lld_item_prototypes_get";
4917 DB_RESULT result;
4918 DB_ROW row;
4919 zbx_lld_item_prototype_t *item_prototype;
4920 zbx_lld_item_preproc_t *preproc_op;
4921 zbx_uint64_t itemid;
4922 int index, i;
4923
4924 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4925
4926 result = DBselect(
4927 "select i.itemid,i.name,i.key_,i.type,i.value_type,i.delay,"
4928 "i.history,i.trends,i.status,i.trapper_hosts,i.units,i.formula,"
4929 "i.logtimefmt,i.valuemapid,i.params,i.ipmi_sensor,i.snmp_community,i.snmp_oid,"
4930 "i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,i.snmpv3_authprotocol,"
4931 "i.snmpv3_authpassphrase,i.snmpv3_privprotocol,i.snmpv3_privpassphrase,i.authtype,"
4932 "i.username,i.password,i.publickey,i.privatekey,i.description,i.interfaceid,"
4933 "i.snmpv3_contextname,i.jmx_endpoint,i.master_itemid,i.timeout,i.url,i.query_fields,"
4934 "i.posts,i.status_codes,i.follow_redirects,i.post_type,i.http_proxy,i.headers,"
4935 "i.retrieve_mode,i.request_method,i.output_format,i.ssl_cert_file,i.ssl_key_file,"
4936 "i.ssl_key_password,i.verify_peer,i.verify_host,i.allow_traps"
4937 " from items i,item_discovery id"
4938 " where i.itemid=id.itemid"
4939 " and id.parent_itemid=" ZBX_FS_UI64,
4940 lld_ruleid);
4941
4942 while (NULL != (row = DBfetch(result)))
4943 {
4944 item_prototype = (zbx_lld_item_prototype_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_prototype_t));
4945
4946 ZBX_STR2UINT64(item_prototype->itemid, row[0]);
4947 item_prototype->name = zbx_strdup(NULL, row[1]);
4948 item_prototype->key = zbx_strdup(NULL, row[2]);
4949 ZBX_STR2UCHAR(item_prototype->type, row[3]);
4950 ZBX_STR2UCHAR(item_prototype->value_type, row[4]);
4951 item_prototype->delay = zbx_strdup(NULL, row[5]);
4952 item_prototype->history = zbx_strdup(NULL, row[6]);
4953 item_prototype->trends = zbx_strdup(NULL, row[7]);
4954 ZBX_STR2UCHAR(item_prototype->status, row[8]);
4955 item_prototype->trapper_hosts = zbx_strdup(NULL, row[9]);
4956 item_prototype->units = zbx_strdup(NULL, row[10]);
4957 item_prototype->formula = zbx_strdup(NULL, row[11]);
4958 item_prototype->logtimefmt = zbx_strdup(NULL, row[12]);
4959 ZBX_DBROW2UINT64(item_prototype->valuemapid, row[13]);
4960 item_prototype->params = zbx_strdup(NULL, row[14]);
4961 item_prototype->ipmi_sensor = zbx_strdup(NULL, row[15]);
4962 item_prototype->snmp_community = zbx_strdup(NULL, row[16]);
4963 item_prototype->snmp_oid = zbx_strdup(NULL, row[17]);
4964 item_prototype->port = zbx_strdup(NULL, row[18]);
4965 item_prototype->snmpv3_securityname = zbx_strdup(NULL, row[19]);
4966 ZBX_STR2UCHAR(item_prototype->snmpv3_securitylevel, row[20]);
4967 ZBX_STR2UCHAR(item_prototype->snmpv3_authprotocol, row[21]);
4968 item_prototype->snmpv3_authpassphrase = zbx_strdup(NULL, row[22]);
4969 ZBX_STR2UCHAR(item_prototype->snmpv3_privprotocol, row[23]);
4970 item_prototype->snmpv3_privpassphrase = zbx_strdup(NULL, row[24]);
4971 ZBX_STR2UCHAR(item_prototype->authtype, row[25]);
4972 item_prototype->username = zbx_strdup(NULL, row[26]);
4973 item_prototype->password = zbx_strdup(NULL, row[27]);
4974 item_prototype->publickey = zbx_strdup(NULL, row[28]);
4975 item_prototype->privatekey = zbx_strdup(NULL, row[29]);
4976 item_prototype->description = zbx_strdup(NULL, row[30]);
4977 ZBX_DBROW2UINT64(item_prototype->interfaceid, row[31]);
4978 item_prototype->snmpv3_contextname = zbx_strdup(NULL, row[32]);
4979 item_prototype->jmx_endpoint = zbx_strdup(NULL, row[33]);
4980 ZBX_DBROW2UINT64(item_prototype->master_itemid, row[34]);
4981
4982 item_prototype->timeout = zbx_strdup(NULL, row[35]);
4983 item_prototype->url = zbx_strdup(NULL, row[36]);
4984 item_prototype->query_fields = zbx_strdup(NULL, row[37]);
4985 item_prototype->posts = zbx_strdup(NULL, row[38]);
4986 item_prototype->status_codes = zbx_strdup(NULL, row[39]);
4987 ZBX_STR2UCHAR(item_prototype->follow_redirects, row[40]);
4988 ZBX_STR2UCHAR(item_prototype->post_type, row[41]);
4989 item_prototype->http_proxy = zbx_strdup(NULL, row[42]);
4990 item_prototype->headers = zbx_strdup(NULL, row[43]);
4991 ZBX_STR2UCHAR(item_prototype->retrieve_mode, row[44]);
4992 ZBX_STR2UCHAR(item_prototype->request_method, row[45]);
4993 ZBX_STR2UCHAR(item_prototype->output_format, row[46]);
4994 item_prototype->ssl_cert_file = zbx_strdup(NULL, row[47]);
4995 item_prototype->ssl_key_file = zbx_strdup(NULL, row[48]);
4996 item_prototype->ssl_key_password = zbx_strdup(NULL, row[49]);
4997 ZBX_STR2UCHAR(item_prototype->verify_peer, row[50]);
4998 ZBX_STR2UCHAR(item_prototype->verify_host, row[51]);
4999 ZBX_STR2UCHAR(item_prototype->allow_traps, row[52]);
5000
5001 zbx_vector_ptr_create(&item_prototype->lld_rows);
5002 zbx_vector_ptr_create(&item_prototype->applications);
5003 zbx_vector_ptr_create(&item_prototype->preproc_ops);
5004
5005 zbx_vector_ptr_append(item_prototypes, item_prototype);
5006 }
5007 DBfree_result(result);
5008
5009 zbx_vector_ptr_sort(item_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
5010
5011 if (0 == item_prototypes->values_num)
5012 goto out;
5013
5014 /* get item prototype preprocessing options */
5015
5016 result = DBselect(
5017 "select ip.itemid,ip.step,ip.type,ip.params from item_preproc ip,item_discovery id"
5018 " where ip.itemid=id.itemid"
5019 " and id.parent_itemid=" ZBX_FS_UI64,
5020 lld_ruleid);
5021
5022 while (NULL != (row = DBfetch(result)))
5023 {
5024 ZBX_STR2UINT64(itemid, row[0]);
5025
5026 if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &itemid,
5027 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
5028 {
5029 THIS_SHOULD_NEVER_HAPPEN;
5030 continue;
5031 }
5032
5033 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
5034
5035 preproc_op = (zbx_lld_item_preproc_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_preproc_t));
5036 preproc_op->step = atoi(row[1]);
5037 preproc_op->type = atoi(row[2]);
5038 preproc_op->params = zbx_strdup(NULL, row[3]);
5039 zbx_vector_ptr_append(&item_prototype->preproc_ops, preproc_op);
5040 }
5041 DBfree_result(result);
5042
5043 for (i = 0; i < item_prototypes->values_num; i++)
5044 {
5045 item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
5046 zbx_vector_ptr_sort(&item_prototype->preproc_ops, lld_item_preproc_sort_by_step);
5047 }
5048
5049 out:
5050 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __function_name, item_prototypes->values_num);
5051 }
5052
5053 /******************************************************************************
5054 * *
5055 * Function: lld_link_dependent_items *
5056 * *
5057 * Purpose: create dependent item index in master item data *
5058 * *
5059 * Parameters: items - [IN/OUT] the lld items *
5060 * items_index - [IN] lld item index *
5061 * *
5062 ******************************************************************************/
lld_link_dependent_items(zbx_vector_ptr_t * items,zbx_hashset_t * items_index)5063 static void lld_link_dependent_items(zbx_vector_ptr_t *items, zbx_hashset_t *items_index)
5064 {
5065 const char *__function_name = "lld_link_dependent_items";
5066 zbx_lld_item_t *item, *master;
5067 zbx_lld_item_index_t *item_index, item_index_local;
5068 int i;
5069
5070 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
5071
5072 for (i = items->values_num - 1; i >= 0; i--)
5073 {
5074 item = (zbx_lld_item_t *)items->values[i];
5075 /* only discovered dependent items should be linked */
5076 if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED) || 0 == item->master_itemid)
5077 continue;
5078
5079 item_index_local.parent_itemid = item->master_itemid;
5080 item_index_local.lld_row = (zbx_lld_row_t *)item->lld_row;
5081
5082 if (NULL != (item_index = (zbx_lld_item_index_t *)zbx_hashset_search(items_index, &item_index_local)))
5083 {
5084 master = item_index->item;
5085 zbx_vector_ptr_append(&master->dependent_items, item);
5086 }
5087 }
5088
5089 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5090 }
5091
5092 /******************************************************************************
5093 * *
5094 * Function: lld_update_items *
5095 * *
5096 * Purpose: add or update discovered items *
5097 * *
5098 * Return value: SUCCEED - if items were successfully added/updated or *
5099 * adding/updating was not necessary *
5100 * FAIL - items cannot be added/updated *
5101 * *
5102 ******************************************************************************/
lld_update_items(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * lld_rows,char ** error,int lifetime,int lastcheck)5103 int lld_update_items(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *lld_rows, char **error,
5104 int lifetime, int lastcheck)
5105 {
5106 const char *__function_name = "lld_update_items";
5107
5108 zbx_vector_ptr_t applications, application_prototypes, items, item_prototypes, item_dependencies;
5109 zbx_hashset_t applications_index, items_index, items_applications;
5110 int ret = SUCCEED, host_record_is_locked = 0;
5111
5112 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
5113
5114 zbx_vector_ptr_create(&item_prototypes);
5115
5116 lld_item_prototypes_get(lld_ruleid, &item_prototypes);
5117
5118 if (0 == item_prototypes.values_num)
5119 goto out;
5120
5121 zbx_vector_ptr_create(&application_prototypes);
5122
5123 lld_application_prototypes_get(lld_ruleid, &application_prototypes);
5124
5125 zbx_vector_ptr_create(&applications);
5126 zbx_hashset_create(&applications_index, application_prototypes.values_num * lld_rows->values_num,
5127 lld_application_index_hash_func, lld_application_index_compare_func);
5128
5129 zbx_vector_ptr_create(&items);
5130 zbx_hashset_create(&items_index, item_prototypes.values_num * lld_rows->values_num, lld_item_index_hash_func,
5131 lld_item_index_compare_func);
5132
5133 zbx_hashset_create(&items_applications, 100, lld_item_application_hash_func, lld_item_application_compare_func);
5134
5135 lld_applications_get(lld_ruleid, &applications);
5136 lld_applications_make(&application_prototypes, lld_rows, &applications, &applications_index);
5137 lld_applications_validate(hostid, lld_ruleid, &applications, &applications_index, error);
5138
5139 lld_item_application_prototypes_get(&item_prototypes, &application_prototypes);
5140
5141 lld_items_get(&item_prototypes, &items);
5142 lld_items_make(&item_prototypes, lld_rows, &items, &items_index, error);
5143 lld_items_preproc_make(&item_prototypes, &items, error);
5144
5145 lld_link_dependent_items(&items, &items_index);
5146
5147 zbx_vector_ptr_create(&item_dependencies);
5148 lld_item_dependencies_get(&item_prototypes, &item_dependencies);
5149
5150 lld_items_validate(hostid, &items, &item_prototypes, &item_dependencies, error);
5151
5152 lld_items_applications_get(lld_ruleid, &items_applications);
5153 lld_items_applications_make(&item_prototypes, &items, &applications_index, &items_applications);
5154
5155 DBbegin();
5156
5157 if (SUCCEED == lld_items_save(hostid, &item_prototypes, &items, &items_index, &host_record_is_locked) &&
5158 SUCCEED == lld_items_preproc_save(hostid, &items, &host_record_is_locked) &&
5159 SUCCEED == lld_applications_save(hostid, &applications, &application_prototypes,
5160 &host_record_is_locked))
5161 {
5162 lld_items_applications_save(&items_applications, &items);
5163
5164 if (ZBX_DB_OK != DBcommit())
5165 {
5166 ret = FAIL;
5167 goto clean;
5168 }
5169 }
5170 else
5171 {
5172 ret = FAIL;
5173 DBrollback();
5174 goto clean;
5175 }
5176
5177 lld_item_links_populate(&item_prototypes, lld_rows, &items_index);
5178 lld_remove_lost_items(&items, lifetime, lastcheck);
5179 lld_remove_lost_applications(lld_ruleid, &applications, lifetime, lastcheck);
5180 clean:
5181 zbx_hashset_destroy(&items_applications);
5182 zbx_hashset_destroy(&items_index);
5183
5184 zbx_vector_ptr_clear_ext(&item_dependencies, zbx_ptr_free);
5185 zbx_vector_ptr_destroy(&item_dependencies);
5186
5187 zbx_vector_ptr_clear_ext(&items, (zbx_clean_func_t)lld_item_free);
5188 zbx_vector_ptr_destroy(&items);
5189
5190 zbx_hashset_destroy(&applications_index);
5191
5192 zbx_vector_ptr_clear_ext(&applications, (zbx_clean_func_t)lld_application_free);
5193 zbx_vector_ptr_destroy(&applications);
5194
5195 zbx_vector_ptr_clear_ext(&application_prototypes, (zbx_clean_func_t)lld_application_prototype_free);
5196 zbx_vector_ptr_destroy(&application_prototypes);
5197
5198 zbx_vector_ptr_clear_ext(&item_prototypes, (zbx_clean_func_t)lld_item_prototype_free);
5199 out:
5200 zbx_vector_ptr_destroy(&item_prototypes);
5201
5202 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5203
5204 return ret;
5205 }
5206