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