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