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, &regexp_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, &regexp_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', &param1, &param2);
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(&param1, &lld_row->jp_row, lld_macro_paths, flags1, NULL, 0);
2689 		substitute_lld_macros(&param2, &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, &params_alloc, &params_offset, param1);
2695 		zbx_chrcpy_alloc(sub_params, &params_alloc, &params_offset, '\n');
2696 		zbx_strcpy_alloc(sub_params, &params_alloc, &params_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