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