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 
26 typedef struct
27 {
28 	zbx_uint64_t		itemid;
29 	zbx_uint64_t		valuemapid;
30 	zbx_uint64_t		interfaceid;
31 	char			*name;
32 	char			*key;
33 	char			*delay_flex;
34 	char			*trapper_hosts;
35 	char			*units;
36 	char			*formula;
37 	char			*logtimefmt;
38 	char			*params;
39 	char			*ipmi_sensor;
40 	char			*snmp_community;
41 	char			*snmp_oid;
42 	char			*snmpv3_securityname;
43 	char			*snmpv3_authpassphrase;
44 	char			*snmpv3_privpassphrase;
45 	char			*snmpv3_contextname;
46 	char			*username;
47 	char			*password;
48 	char			*publickey;
49 	char			*privatekey;
50 	char			*description;
51 	char			*port;
52 	int			delay;
53 	int			history;
54 	int			trends;
55 	unsigned char		type;
56 	unsigned char		value_type;
57 	unsigned char		data_type;
58 	unsigned char		status;
59 	unsigned char		multiplier;
60 	unsigned char		delta;
61 	unsigned char		snmpv3_securitylevel;
62 	unsigned char		snmpv3_authprotocol;
63 	unsigned char		snmpv3_privprotocol;
64 	unsigned char		authtype;
65 	zbx_vector_ptr_t	lld_rows;
66 	zbx_vector_ptr_t	applications;
67 }
68 zbx_lld_item_prototype_t;
69 
70 typedef struct
71 {
72 	zbx_uint64_t		itemid;
73 	zbx_uint64_t		parent_itemid;
74 #define ZBX_FLAG_LLD_ITEM_UNSET				__UINT64_C(0x0000000000000000)
75 #define ZBX_FLAG_LLD_ITEM_DISCOVERED			__UINT64_C(0x0000000000000001)
76 #define ZBX_FLAG_LLD_ITEM_UPDATE_NAME			__UINT64_C(0x0000000000000002)
77 #define ZBX_FLAG_LLD_ITEM_UPDATE_KEY			__UINT64_C(0x0000000000000004)
78 #define ZBX_FLAG_LLD_ITEM_UPDATE_TYPE			__UINT64_C(0x0000000000000008)
79 #define ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE		__UINT64_C(0x0000000000000010)
80 #define ZBX_FLAG_LLD_ITEM_UPDATE_DATA_TYPE		__UINT64_C(0x0000000000000020)
81 #define ZBX_FLAG_LLD_ITEM_UPDATE_DELAY			__UINT64_C(0x0000000000000040)
82 #define ZBX_FLAG_LLD_ITEM_UPDATE_DELAY_FLEX		__UINT64_C(0x0000000000000080)
83 #define ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY		__UINT64_C(0x0000000000000100)
84 #define ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS			__UINT64_C(0x0000000000000200)
85 #define ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS		__UINT64_C(0x0000000000000400)
86 #define ZBX_FLAG_LLD_ITEM_UPDATE_UNITS			__UINT64_C(0x0000000000000800)
87 #define ZBX_FLAG_LLD_ITEM_UPDATE_MULTIPLIER		__UINT64_C(0x0000000000001000)
88 #define ZBX_FLAG_LLD_ITEM_UPDATE_DELTA			__UINT64_C(0x0000000000002000)
89 #define ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA		__UINT64_C(0x0000000000004000)
90 #define ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT		__UINT64_C(0x0000000000008000)
91 #define ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID		__UINT64_C(0x0000000000010000)
92 #define ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS			__UINT64_C(0x0000000000020000)
93 #define ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR		__UINT64_C(0x0000000000040000)
94 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY		__UINT64_C(0x0000000000080000)
95 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID		__UINT64_C(0x0000000000100000)
96 #define ZBX_FLAG_LLD_ITEM_UPDATE_PORT			__UINT64_C(0x0000000000200000)
97 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME	__UINT64_C(0x0000000000400000)
98 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL	__UINT64_C(0x0000000000800000)
99 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL	__UINT64_C(0x0000000001000000)
100 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE	__UINT64_C(0x0000000002000000)
101 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL	__UINT64_C(0x0000000004000000)
102 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE	__UINT64_C(0x0000000008000000)
103 #define ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE		__UINT64_C(0x0000000010000000)
104 #define ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME		__UINT64_C(0x0000000020000000)
105 #define ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD		__UINT64_C(0x0000000040000000)
106 #define ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY		__UINT64_C(0x0000000080000000)
107 #define ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY		__UINT64_C(0x0000000100000000)
108 #define ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION		__UINT64_C(0x0000000200000000)
109 #define ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID		__UINT64_C(0x0000000400000000)
110 #define ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME	__UINT64_C(0x0000000800000000)
111 #define ZBX_FLAG_LLD_ITEM_UPDATE										\
112 		(ZBX_FLAG_LLD_ITEM_UPDATE_NAME | ZBX_FLAG_LLD_ITEM_UPDATE_KEY | ZBX_FLAG_LLD_ITEM_UPDATE_TYPE |	\
113 		ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE | ZBX_FLAG_LLD_ITEM_UPDATE_DATA_TYPE |			\
114 		ZBX_FLAG_LLD_ITEM_UPDATE_DELAY | ZBX_FLAG_LLD_ITEM_UPDATE_DELAY_FLEX |				\
115 		ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY | ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS |				\
116 		ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS | ZBX_FLAG_LLD_ITEM_UPDATE_UNITS |			\
117 		ZBX_FLAG_LLD_ITEM_UPDATE_MULTIPLIER | ZBX_FLAG_LLD_ITEM_UPDATE_DELTA |				\
118 		ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA | ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT |			\
119 		ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID | ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS |				\
120 		ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR | ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY |		\
121 		ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID | ZBX_FLAG_LLD_ITEM_UPDATE_PORT |				\
122 		ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME | ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL |	\
123 		ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL | ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE |	\
124 		ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL | ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE |	\
125 		ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE | ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME |				\
126 		ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD | ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY |			\
127 		ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY | ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION |			\
128 		ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID | ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME)
129 	zbx_uint64_t		flags;
130 	char			*key_proto;
131 	char			*name;
132 	char			*name_proto;
133 	char			*key;
134 	char			*key_orig;
135 	char			*units;
136 	char			*units_orig;
137 	char			*params;
138 	char			*params_orig;
139 	char			*ipmi_sensor;
140 	char			*ipmi_sensor_orig;
141 	char			*snmp_oid;
142 	char			*snmp_oid_orig;
143 	char			*description;
144 	char			*description_orig;
145 	int			lastcheck;
146 	int			ts_delete;
147 	const zbx_lld_row_t	*lld_row;
148 }
149 zbx_lld_item_t;
150 
151 /* item index by prototype (parent) id and lld row */
152 typedef struct
153 {
154 	zbx_uint64_t	parent_itemid;
155 	zbx_lld_row_t	*lld_row;
156 	zbx_lld_item_t	*item;
157 }
158 zbx_lld_item_index_t;
159 
160 typedef struct
161 {
162 	zbx_uint64_t	application_prototypeid;
163 	zbx_uint64_t	itemid;
164 	char		*name;
165 }
166 zbx_lld_application_prototype_t;
167 
168 typedef struct
169 {
170 	zbx_uint64_t		applicationid;
171 	zbx_uint64_t		application_prototypeid;
172 	zbx_uint64_t		application_discoveryid;
173 	int			lastcheck;
174 	int			ts_delete;
175 #define ZBX_FLAG_LLD_APPLICATION_UNSET			__UINT64_C(0x0000000000000000)
176 #define ZBX_FLAG_LLD_APPLICATION_DISCOVERED		__UINT64_C(0x0000000000000001)
177 #define ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME		__UINT64_C(0x0000000000000002)
178 #define ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY		__UINT64_C(0x0000000100000000)
179 #define ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY	__UINT64_C(0x0000000200000000)
180 #define ZBX_FLAG_LLD_APPLICATION_REMOVE			__UINT64_C(0x0000000400000000)
181 	zbx_uint64_t		flags;
182 	char			*name;
183 	char			*name_proto;
184 	char			*name_orig;
185 	const zbx_lld_row_t	*lld_row;
186 }
187 zbx_lld_application_t;
188 
189 /* reference to an item either by its id (existing items) or structure (new items) */
190 typedef struct
191 {
192 	zbx_uint64_t	itemid;
193 	zbx_lld_item_t	*item;
194 }
195 zbx_lld_item_ref_t;
196 
197 /* reference to an application either by its id (existing applications) or structure (new applications) */
198 typedef struct
199 {
200 	zbx_uint64_t		applicationid;
201 	zbx_lld_application_t	*application;
202 }
203 zbx_lld_application_ref_t;
204 
205 /* item prototype-application link reference by application id (existing applications) */
206 /* or application prototype structure (application prototypes)                         */
207 typedef struct
208 {
209 	zbx_lld_application_prototype_t	*application_prototype;
210 	zbx_uint64_t			applicationid;
211 }
212 zbx_lld_item_application_ref_t;
213 
214 /* item-application link */
215 typedef struct
216 {
217 	zbx_uint64_t			itemappid;
218 	zbx_lld_item_ref_t		item_ref;
219 	zbx_lld_application_ref_t	application_ref;
220 #define ZBX_FLAG_LLD_ITEM_APPLICATION_UNSET		__UINT64_C(0x0000000000000000)
221 #define ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED	__UINT64_C(0x0000000000000001)
222 	zbx_uint64_t			flags;
223 }
224 zbx_lld_item_application_t;
225 
226 /* application index by prototypeid and lld row */
227 typedef struct
228 {
229 	zbx_uint64_t		application_prototypeid;
230 	const zbx_lld_row_t	*lld_row;
231 	zbx_lld_application_t	*application;
232 }
233 zbx_lld_application_index_t;
234 
235 /* items index hashset support functions */
lld_item_index_hash_func(const void * data)236 static zbx_hash_t	lld_item_index_hash_func(const void *data)
237 {
238 	zbx_lld_item_index_t	*item_index = (zbx_lld_item_index_t *)data;
239 	zbx_hash_t		hash;
240 
241 	hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&item_index->parent_itemid,
242 			sizeof(item_index->parent_itemid), ZBX_DEFAULT_HASH_SEED);
243 	return ZBX_DEFAULT_PTR_HASH_ALGO(&item_index->lld_row, sizeof(item_index->lld_row), hash);
244 }
245 
lld_item_index_compare_func(const void * d1,const void * d2)246 static int	lld_item_index_compare_func(const void *d1, const void *d2)
247 {
248 	zbx_lld_item_index_t	*i1 = (zbx_lld_item_index_t *)d1;
249 	zbx_lld_item_index_t	*i2 = (zbx_lld_item_index_t *)d2;
250 
251 	ZBX_RETURN_IF_NOT_EQUAL(i1->parent_itemid, i2->parent_itemid);
252 	ZBX_RETURN_IF_NOT_EQUAL(i1->lld_row, i2->lld_row);
253 
254 	return 0;
255 }
256 
257 /* application index hashset support functions */
lld_application_index_hash_func(const void * data)258 static zbx_hash_t	lld_application_index_hash_func(const void *data)
259 {
260 	zbx_lld_application_index_t	*application_index = (zbx_lld_application_index_t *)data;
261 	zbx_hash_t			hash;
262 
263 	hash = ZBX_DEFAULT_UINT64_HASH_ALGO(&application_index->application_prototypeid,
264 			sizeof(application_index->application_prototypeid), ZBX_DEFAULT_HASH_SEED);
265 	return ZBX_DEFAULT_PTR_HASH_ALGO(&application_index->lld_row, sizeof(application_index->lld_row), hash);
266 }
267 
lld_application_index_compare_func(const void * d1,const void * d2)268 static int	lld_application_index_compare_func(const void *d1, const void *d2)
269 {
270 	zbx_lld_application_index_t	*i1 = (zbx_lld_application_index_t *)d1;
271 	zbx_lld_application_index_t	*i2 = (zbx_lld_application_index_t *)d2;
272 
273 	ZBX_RETURN_IF_NOT_EQUAL(i1->application_prototypeid, i2->application_prototypeid);
274 	ZBX_RETURN_IF_NOT_EQUAL(i1->lld_row, i2->lld_row);
275 
276 	return 0;
277 }
278 
279 /* comparison function for discovered application lookup by name */
lld_application_compare_name(const void * d1,const void * d2)280 static int	lld_application_compare_name(const void *d1, const void *d2)
281 {
282 	const zbx_lld_application_t	*a1 = *(zbx_lld_application_t **)d1;
283 	const zbx_lld_application_t	*a2 = *(zbx_lld_application_t **)d2;
284 
285 	if (0 == (a1->flags & a2->flags))
286 		return -1;
287 
288 	if (NULL == a1->name || NULL == a2->name)
289 		return -1;
290 
291 	return strcmp(a1->name, a2->name);
292 }
293 
294 /* comparison function for discovered application lookup by original name name */
lld_application_compare_name_orig(const void * d1,const void * d2)295 static int	lld_application_compare_name_orig(const void *d1, const void *d2)
296 {
297 	const zbx_lld_application_t	*a1 = *(zbx_lld_application_t **)d1;
298 	const zbx_lld_application_t	*a2 = *(zbx_lld_application_t **)d2;
299 
300 	if (0 == (a1->flags & a2->flags))
301 		return -1;
302 
303 	if (NULL == a1->name_orig || NULL == a2->name_orig)
304 		return -1;
305 
306 	return strcmp(a1->name_orig, a2->name_orig);
307 }
308 
309 /* string pointer hashset (used to check for duplicate item keys) support functions */
lld_items_keys_hash_func(const void * data)310 static zbx_hash_t	lld_items_keys_hash_func(const void *data)
311 {
312 	return ZBX_DEFAULT_STRING_HASH_FUNC(*(char **)data);
313 }
314 
lld_items_keys_compare_func(const void * d1,const void * d2)315 static int	lld_items_keys_compare_func(const void *d1, const void *d2)
316 {
317 	return ZBX_DEFAULT_STR_COMPARE_FUNC(d1, d2);
318 }
319 
320 /* items - applications hashset support */
lld_item_application_hash_func(const void * data)321 static zbx_hash_t	lld_item_application_hash_func(const void *data)
322 {
323 	const zbx_lld_item_application_t	*item_application = data;
324 	zbx_hash_t				hash;
325 
326 	hash = ZBX_DEFAULT_HASH_ALGO(&item_application->item_ref, sizeof(item_application->item_ref),
327 			ZBX_DEFAULT_HASH_SEED);
328 	return ZBX_DEFAULT_HASH_ALGO(&item_application->application_ref, sizeof(item_application->application_ref),
329 			hash);
330 }
331 
lld_item_application_compare_func(const void * d1,const void * d2)332 static int	lld_item_application_compare_func(const void *d1, const void *d2)
333 {
334 	const zbx_lld_item_application_t	*ia1 = (zbx_lld_item_application_t *)d1;
335 	const zbx_lld_item_application_t	*ia2 = (zbx_lld_item_application_t *)d2;
336 
337 	ZBX_RETURN_IF_NOT_EQUAL(ia1->item_ref.itemid, ia2->item_ref.itemid);
338 	ZBX_RETURN_IF_NOT_EQUAL(ia1->item_ref.item, ia2->item_ref.item);
339 	ZBX_RETURN_IF_NOT_EQUAL(ia1->application_ref.applicationid, ia2->application_ref.applicationid);
340 	ZBX_RETURN_IF_NOT_EQUAL(ia1->application_ref.application, ia2->application_ref.application);
341 
342 	return 0;
343 }
344 
lld_application_prototype_free(zbx_lld_application_prototype_t * application_prototype)345 static void	lld_application_prototype_free(zbx_lld_application_prototype_t *application_prototype)
346 {
347 	zbx_free(application_prototype->name);
348 	zbx_free(application_prototype);
349 }
350 
lld_application_free(zbx_lld_application_t * application)351 static void	lld_application_free(zbx_lld_application_t *application)
352 {
353 	zbx_free(application->name_orig);
354 	zbx_free(application->name_proto);
355 	zbx_free(application->name);
356 	zbx_free(application);
357 }
358 
lld_item_prototype_free(zbx_lld_item_prototype_t * item_prototype)359 static void	lld_item_prototype_free(zbx_lld_item_prototype_t *item_prototype)
360 {
361 	zbx_free(item_prototype->name);
362 	zbx_free(item_prototype->key);
363 	zbx_free(item_prototype->delay_flex);
364 	zbx_free(item_prototype->trapper_hosts);
365 	zbx_free(item_prototype->units);
366 	zbx_free(item_prototype->formula);
367 	zbx_free(item_prototype->logtimefmt);
368 	zbx_free(item_prototype->params);
369 	zbx_free(item_prototype->ipmi_sensor);
370 	zbx_free(item_prototype->snmp_community);
371 	zbx_free(item_prototype->snmp_oid);
372 	zbx_free(item_prototype->snmpv3_securityname);
373 	zbx_free(item_prototype->snmpv3_authpassphrase);
374 	zbx_free(item_prototype->snmpv3_privpassphrase);
375 	zbx_free(item_prototype->snmpv3_contextname);
376 	zbx_free(item_prototype->username);
377 	zbx_free(item_prototype->password);
378 	zbx_free(item_prototype->publickey);
379 	zbx_free(item_prototype->privatekey);
380 	zbx_free(item_prototype->description);
381 	zbx_free(item_prototype->port);
382 
383 	zbx_vector_ptr_destroy(&item_prototype->lld_rows);
384 
385 	zbx_vector_ptr_clear_ext(&item_prototype->applications, zbx_default_mem_free_func);
386 	zbx_vector_ptr_destroy(&item_prototype->applications);
387 
388 	zbx_free(item_prototype);
389 }
390 
lld_item_free(zbx_lld_item_t * item)391 static void	lld_item_free(zbx_lld_item_t *item)
392 {
393 	zbx_free(item->key_proto);
394 	zbx_free(item->name);
395 	zbx_free(item->name_proto);
396 	zbx_free(item->key);
397 	zbx_free(item->key_orig);
398 	zbx_free(item->units);
399 	zbx_free(item->units_orig);
400 	zbx_free(item->params);
401 	zbx_free(item->params_orig);
402 	zbx_free(item->ipmi_sensor);
403 	zbx_free(item->ipmi_sensor_orig);
404 	zbx_free(item->snmp_oid);
405 	zbx_free(item->snmp_oid_orig);
406 	zbx_free(item->description);
407 	zbx_free(item->description_orig);
408 	zbx_free(item);
409 }
410 
411 /******************************************************************************
412  *                                                                            *
413  * Function: lld_items_get                                                    *
414  *                                                                            *
415  * Purpose: retrieves existing items for the specified item prototypes        *
416  *                                                                            *
417  * Parameters: item_prototypes - [IN] item prototypes                         *
418  *             items           - [OUT] list of items                          *
419  *                                                                            *
420  ******************************************************************************/
lld_items_get(const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items)421 static void	lld_items_get(const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items)
422 {
423 	const char		*__function_name = "lld_items_get";
424 
425 	DB_RESULT		result;
426 	DB_ROW			row;
427 	zbx_lld_item_t		*item;
428 	zbx_uint64_t		db_valuemapid, db_interfaceid;
429 	zbx_vector_uint64_t	parent_itemids;
430 	int			i;
431 	char			*sql = NULL;
432 	size_t			sql_alloc = 0, sql_offset = 0;
433 
434 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
435 
436 	zbx_vector_uint64_create(&parent_itemids);
437 	zbx_vector_uint64_reserve(&parent_itemids, item_prototypes->values_num);
438 
439 	for (i = 0; i < item_prototypes->values_num; i++)
440 	{
441 		const zbx_lld_item_prototype_t	*item_prototype;
442 
443 		item_prototype = (const zbx_lld_item_prototype_t *)item_prototypes->values[i];
444 
445 		zbx_vector_uint64_append(&parent_itemids, item_prototype->itemid);
446 	}
447 
448 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
449 			"select id.itemid,id.key_,id.lastcheck,id.ts_delete,i.name,i.key_,i.type,i.value_type,"
450 				"i.data_type,i.delay,i.delay_flex,i.history,i.trends,i.trapper_hosts,i.units,"
451 				"i.multiplier,i.delta,i.formula,i.logtimefmt,i.valuemapid,i.params,i.ipmi_sensor,"
452 				"i.snmp_community,i.snmp_oid,i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,"
453 				"i.snmpv3_authprotocol,i.snmpv3_authpassphrase,i.snmpv3_privprotocol,"
454 				"i.snmpv3_privpassphrase,i.authtype,i.username,i.password,i.publickey,i.privatekey,"
455 				"i.description,i.interfaceid,i.snmpv3_contextname,id.parent_itemid"
456 			" from item_discovery id"
457 				" join items i"
458 					" on id.itemid=i.itemid"
459 			" where");
460 
461 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "id.parent_itemid", parent_itemids.values,
462 			parent_itemids.values_num);
463 
464 	zbx_vector_uint64_destroy(&parent_itemids);
465 
466 	result = DBselect("%s", sql);
467 
468 	zbx_free(sql);
469 
470 	while (NULL != (row = DBfetch(result)))
471 	{
472 		zbx_uint64_t			parent_itemid;
473 		int				index;
474 		zbx_lld_item_prototype_t	*item_prototype;
475 
476 		ZBX_STR2UINT64(parent_itemid, row[39]);
477 
478 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &parent_itemid,
479 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
480 		{
481 			THIS_SHOULD_NEVER_HAPPEN;
482 			continue;
483 		}
484 
485 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
486 
487 		item = zbx_malloc(NULL, sizeof(zbx_lld_item_t));
488 
489 		ZBX_STR2UINT64(item->itemid, row[0]);
490 		item->parent_itemid = parent_itemid;
491 		item->key_proto = zbx_strdup(NULL, row[1]);
492 		item->lastcheck = atoi(row[2]);
493 		item->ts_delete = atoi(row[3]);
494 		item->name = zbx_strdup(NULL, row[4]);
495 		item->name_proto = NULL;
496 		item->key = zbx_strdup(NULL, row[5]);
497 		item->key_orig = NULL;
498 		item->flags = ZBX_FLAG_LLD_ITEM_UNSET;
499 
500 		if ((unsigned char)atoi(row[6]) != item_prototype->type)
501 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TYPE;
502 
503 		if ((unsigned char)atoi(row[7]) != item_prototype->value_type)
504 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE;
505 
506 		if ((unsigned char)atoi(row[8]) != item_prototype->data_type)
507 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DATA_TYPE;
508 
509 		if (atoi(row[9]) != item_prototype->delay)
510 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DELAY;
511 
512 		if (0 != strcmp(row[10], item_prototype->delay_flex))
513 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DELAY_FLEX;
514 
515 		if (atoi(row[11]) != item_prototype->history)
516 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY;
517 
518 		if (atoi(row[12]) != item_prototype->trends)
519 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS;
520 
521 		if (0 != strcmp(row[13], item_prototype->trapper_hosts))
522 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS;
523 
524 		item->units = zbx_strdup(NULL, row[14]);
525 		item->units_orig = NULL;
526 
527 		if ((unsigned char)atoi(row[15]) != item_prototype->multiplier)
528 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_MULTIPLIER;
529 
530 		if ((unsigned char)atoi(row[16]) != item_prototype->delta)
531 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DELTA;
532 
533 		if (0 != strcmp(row[17], item_prototype->formula))
534 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA;
535 
536 		if (0 != strcmp(row[18], item_prototype->logtimefmt))
537 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT;
538 
539 		ZBX_DBROW2UINT64(db_valuemapid, row[19]);
540 		if (db_valuemapid != item_prototype->valuemapid)
541 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID;
542 
543 		item->params = zbx_strdup(NULL, row[20]);
544 		item->params_orig = NULL;
545 
546 		item->ipmi_sensor = zbx_strdup(NULL, row[21]);
547 		item->ipmi_sensor_orig = NULL;
548 
549 		if (0 != strcmp(row[22], item_prototype->snmp_community))
550 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY;
551 
552 		item->snmp_oid = zbx_strdup(NULL, row[23]);
553 		item->snmp_oid_orig = NULL;
554 
555 		if (0 != strcmp(row[24], item_prototype->port))
556 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PORT;
557 
558 		if (0 != strcmp(row[25], item_prototype->snmpv3_securityname))
559 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME;
560 
561 		if ((unsigned char)atoi(row[26]) != item_prototype->snmpv3_securitylevel)
562 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL;
563 
564 		if ((unsigned char)atoi(row[27]) != item_prototype->snmpv3_authprotocol)
565 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL;
566 
567 		if (0 != strcmp(row[28], item_prototype->snmpv3_authpassphrase))
568 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE;
569 
570 		if ((unsigned char)atoi(row[29]) != item_prototype->snmpv3_privprotocol)
571 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL;
572 
573 		if (0 != strcmp(row[30], item_prototype->snmpv3_privpassphrase))
574 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE;
575 
576 		if ((unsigned char)atoi(row[31]) != item_prototype->authtype)
577 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE;
578 
579 		if (0 != strcmp(row[32], item_prototype->username))
580 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME;
581 
582 		if (0 != strcmp(row[33], item_prototype->password))
583 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD;
584 
585 		if (0 != strcmp(row[34], item_prototype->publickey))
586 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY;
587 
588 		if (0 != strcmp(row[35], item_prototype->privatekey))
589 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY;
590 
591 		item->description = zbx_strdup(NULL, row[36]);
592 		item->description_orig = NULL;
593 
594 		ZBX_DBROW2UINT64(db_interfaceid, row[37]);
595 		if (db_interfaceid != item_prototype->interfaceid)
596 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID;
597 
598 		if (0 != strcmp(row[38], item_prototype->snmpv3_contextname))
599 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME;
600 
601 		item->lld_row = NULL;
602 
603 		zbx_vector_ptr_append(items, item);
604 	}
605 	DBfree_result(result);
606 
607 	zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
608 
609 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
610 }
611 
612 /******************************************************************************
613  *                                                                            *
614  * Function: lld_validate_item_field                                          *
615  *                                                                            *
616  ******************************************************************************/
lld_validate_item_field(zbx_lld_item_t * item,char ** field,char ** field_orig,zbx_uint64_t flag,size_t field_len,char ** error)617 static void	lld_validate_item_field(zbx_lld_item_t *item, char **field, char **field_orig, zbx_uint64_t flag,
618 		size_t field_len, char **error)
619 {
620 	if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
621 		return;
622 
623 	/* only new items or items with changed data will be validated */
624 	if (0 != item->itemid && 0 == (item->flags & flag))
625 		return;
626 
627 	if (SUCCEED != zbx_is_utf8(*field))
628 	{
629 		zbx_replace_invalid_utf8(*field);
630 		*error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" has invalid UTF-8 sequence.\n",
631 				(0 != item->itemid ? "update" : "create"), *field);
632 	}
633 	else if (zbx_strlen_utf8(*field) > field_len)
634 	{
635 		*error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" is too long.\n",
636 				(0 != item->itemid ? "update" : "create"), *field);
637 	}
638 	else if (ZBX_FLAG_LLD_ITEM_UPDATE_NAME == flag && '\0' == **field)
639 	{
640 		*error = zbx_strdcatf(*error, "Cannot %s item: name is empty.\n",
641 				(0 != item->itemid ? "update" : "create"));
642 	}
643 	else
644 		return;
645 
646 	if (0 != item->itemid)
647 		lld_field_str_rollback(field, field_orig, &item->flags, flag);
648 	else
649 		item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
650 }
651 
652 /******************************************************************************
653  *                                                                            *
654  * Function: lld_items_validate                                               *
655  *                                                                            *
656  * Parameters: items - [IN] list of items; must be sorted by itemid           *
657  *                                                                            *
658  ******************************************************************************/
lld_items_validate(zbx_uint64_t hostid,zbx_vector_ptr_t * items,char ** error)659 static void	lld_items_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *items, char **error)
660 {
661 	const char		*__function_name = "lld_items_validate";
662 
663 	DB_RESULT		result;
664 	DB_ROW			row;
665 	int			i;
666 	zbx_lld_item_t		*item;
667 	zbx_vector_uint64_t	itemids;
668 	zbx_vector_str_t	keys;
669 	zbx_hashset_t		items_keys;
670 
671 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
672 
673 	zbx_vector_uint64_create(&itemids);
674 	zbx_vector_str_create(&keys);		/* list of item keys */
675 
676 	/* check an item name validity */
677 	for (i = 0; i < items->values_num; i++)
678 	{
679 		item = (zbx_lld_item_t *)items->values[i];
680 
681 		lld_validate_item_field(item, &item->name, &item->name_proto,
682 				ZBX_FLAG_LLD_ITEM_UPDATE_NAME, ITEM_NAME_LEN, error);
683 		lld_validate_item_field(item, &item->key, &item->key_orig,
684 				ZBX_FLAG_LLD_ITEM_UPDATE_KEY, ITEM_KEY_LEN, error);
685 		lld_validate_item_field(item, &item->units, &item->units_orig,
686 				ZBX_FLAG_LLD_ITEM_UPDATE_UNITS, ITEM_UNITS_LEN, error);
687 		lld_validate_item_field(item, &item->params, &item->params_orig,
688 				ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS, ITEM_PARAM_LEN, error);
689 		lld_validate_item_field(item, &item->ipmi_sensor, &item->ipmi_sensor_orig,
690 				ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR, ITEM_IPMI_SENSOR_LEN, error);
691 		lld_validate_item_field(item, &item->snmp_oid, &item->snmp_oid_orig,
692 				ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID, ITEM_SNMP_OID_LEN, error);
693 		lld_validate_item_field(item, &item->description, &item->description_orig,
694 				ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION, ITEM_DESCRIPTION_LEN, error);
695 	}
696 
697 	/* check duplicated item keys */
698 
699 	zbx_hashset_create(&items_keys, items->values_num, lld_items_keys_hash_func, lld_items_keys_compare_func);
700 
701 	/* add 'good' (existing, discovered and not updated) keys to the hashset */
702 	for (i = 0; i < items->values_num; i++)
703 	{
704 		item = (zbx_lld_item_t *)items->values[i];
705 
706 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
707 			continue;
708 
709 		/* skip new or updated item keys */
710 		if (0 == item->itemid || 0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
711 			continue;
712 
713 		zbx_hashset_insert(&items_keys, &item->key, sizeof(char *));
714 	}
715 
716 	/* check new and updated keys for duplicated keys in discovered items */
717 	for (i = 0; i < items->values_num; i++)
718 	{
719 		item = (zbx_lld_item_t *)items->values[i];
720 
721 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
722 			continue;
723 
724 		/* only new items or items with changed key will be validated */
725 		if (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
726 			continue;
727 
728 		if (NULL != zbx_hashset_search(&items_keys, &item->key))
729 		{
730 			*error = zbx_strdcatf(*error, "Cannot %s item:"
731 						" item with the same key \"%s\" already exists.\n",
732 						(0 != item->itemid ? "update" : "create"), item->key);
733 
734 			if (0 != item->itemid)
735 			{
736 				lld_field_str_rollback(&item->key, &item->key_orig, &item->flags,
737 						ZBX_FLAG_LLD_ITEM_UPDATE_KEY);
738 			}
739 			else
740 				item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
741 		}
742 		else
743 			zbx_hashset_insert(&items_keys, &item->key, sizeof(char *));
744 	}
745 
746 	zbx_hashset_destroy(&items_keys);
747 
748 	/* check duplicated keys in DB */
749 
750 	for (i = 0; i < items->values_num; i++)
751 	{
752 		item = (zbx_lld_item_t *)items->values[i];
753 
754 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
755 			continue;
756 
757 		if (0 != item->itemid)
758 			zbx_vector_uint64_append(&itemids, item->itemid);
759 
760 		if (0 != item->itemid && 0 == (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
761 			continue;
762 
763 		zbx_vector_str_append(&keys, item->key);
764 	}
765 
766 	if (0 != keys.values_num)
767 	{
768 		char	*sql = NULL;
769 		size_t	sql_alloc = 256, sql_offset = 0;
770 
771 		sql = zbx_malloc(sql, sql_alloc);
772 
773 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
774 				"select key_"
775 				" from items"
776 				" where hostid=" ZBX_FS_UI64
777 					" and",
778 				hostid);
779 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "key_",
780 				(const char **)keys.values, keys.values_num);
781 
782 		if (0 != itemids.values_num)
783 		{
784 			zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
785 			zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
786 			DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
787 					itemids.values, itemids.values_num);
788 		}
789 
790 		result = DBselect("%s", sql);
791 
792 		while (NULL != (row = DBfetch(result)))
793 		{
794 			for (i = 0; i < items->values_num; i++)
795 			{
796 				item = (zbx_lld_item_t *)items->values[i];
797 
798 				if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
799 					continue;
800 
801 				if (0 == strcmp(item->key, row[0]))
802 				{
803 					*error = zbx_strdcatf(*error, "Cannot %s item:"
804 							" item with the same key \"%s\" already exists.\n",
805 							(0 != item->itemid ? "update" : "create"), item->key);
806 
807 					if (0 != item->itemid)
808 					{
809 						lld_field_str_rollback(&item->key, &item->key_orig, &item->flags,
810 								ZBX_FLAG_LLD_ITEM_UPDATE_KEY);
811 					}
812 					else
813 						item->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
814 
815 					continue;
816 				}
817 			}
818 		}
819 		DBfree_result(result);
820 
821 		zbx_free(sql);
822 	}
823 
824 	zbx_vector_str_destroy(&keys);
825 	zbx_vector_uint64_destroy(&itemids);
826 
827 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
828 }
829 
830 /******************************************************************************
831  *                                                                            *
832  * Function: substitute_formula_macros                                        *
833  *                                                                            *
834  * Purpose: substitutes lld macros in calculated item formula expression      *
835  *                                                                            *
836  * Parameters: data          - [IN/OUT] the expression                        *
837  *             jp_row        - [IN] the lld data row                          *
838  *             error         - [IN] pointer to string for reporting errors    *
839  *             max_error_len - [IN] size of 'error' string                    *
840  *                                                                            *
841  ******************************************************************************/
substitute_formula_macros(char ** data,const struct zbx_json_parse * jp_row,char * error,size_t max_error_len)842 static int	substitute_formula_macros(char **data, const struct zbx_json_parse *jp_row,
843 		char *error, size_t max_error_len)
844 {
845 	const char	*__function_name = "substitute_formula_macros";
846 
847 	char		*exp, *tmp, *e, *p, *param = NULL;
848 	size_t		exp_alloc = 128, exp_offset = 0, tmp_alloc = 128, tmp_offset = 0, f_pos, par_l, par_r, sep_pos;
849 	int		ret = FAIL;
850 
851 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
852 
853 	exp = zbx_malloc(NULL, exp_alloc);
854 	tmp = zbx_malloc(NULL, tmp_alloc);
855 
856 	for (e = *data; SUCCEED == zbx_function_find(e, &f_pos, &par_l, &par_r, error, max_error_len); e += par_r + 1)
857 	{
858 		/* substitute LLD macros in the part of the string preceding function parameters */
859 
860 		zbx_strncpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e, par_l + 1);
861 		if (SUCCEED != substitute_discovery_macros(&tmp, jp_row, ZBX_MACRO_NUMERIC, error, max_error_len))
862 			goto out;
863 
864 		tmp_offset = strlen(tmp);
865 		zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, tmp, tmp_offset);
866 
867 		tmp_alloc = tmp_offset + 1;
868 		tmp_offset = 0;
869 
870 		/* substitute LLD macros in function parameters */
871 
872 		for (p = e + par_l + 1; p < e + par_r; p += sep_pos + 1)
873 		{
874 			size_t	param_pos, param_len;
875 			int	quoted;
876 
877 			e[par_r] = '\0';
878 			zbx_function_param_parse(p, &param_pos, &param_len, &sep_pos);
879 			e[par_r] = ')';
880 
881 			/* copy what was before the parameter */
882 			zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, p, param_pos);
883 
884 			/* prepare the parameter (macro substitutions and quoting) */
885 
886 			zbx_free(param);
887 			param = zbx_function_param_unquote_dyn(p + param_pos, param_len, &quoted);
888 
889 			if (p == e + par_l + 1)
890 			{
891 				char	*key = NULL, *host = NULL;
892 
893 				if (SUCCEED != parse_host_key(param, &host, &key) ||
894 						SUCCEED != substitute_key_macros(&key, NULL, NULL, jp_row,
895 								MACRO_TYPE_ITEM_KEY, NULL, 0))
896 				{
897 					zbx_snprintf(error, max_error_len, "Invalid first parameter \"%s\"", param);
898 					zbx_free(host);
899 					zbx_free(key);
900 					goto out;
901 				}
902 
903 				zbx_free(param);
904 				if (NULL != host)
905 				{
906 					param = zbx_dsprintf(NULL, "%s:%s", host, key);
907 					zbx_free(host);
908 					zbx_free(key);
909 				}
910 				else
911 					param = key;
912 			}
913 			else
914 				substitute_discovery_macros(&param, jp_row, ZBX_MACRO_ANY, NULL, 0);
915 
916 			if (SUCCEED != zbx_function_param_quote(&param, quoted))
917 			{
918 				zbx_snprintf(error, max_error_len, "Cannot quote parameter \"%s\"", param);
919 				goto out;
920 			}
921 
922 			/* copy the parameter */
923 			zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, param);
924 
925 			/* copy what was after the parameter (including separator) */
926 			zbx_strncpy_alloc(&exp, &exp_alloc, &exp_offset, p + param_pos + param_len,
927 					sep_pos - param_pos - param_len + 1);
928 		}
929 	}
930 
931 	if (par_l > par_r)
932 		goto out;
933 
934 	/* substitute LLD macros in the remaining part */
935 
936 	zbx_strcpy_alloc(&tmp, &tmp_alloc, &tmp_offset, e);
937 	if (SUCCEED != substitute_discovery_macros(&tmp, jp_row, ZBX_MACRO_NUMERIC, error, max_error_len))
938 		goto out;
939 
940 	zbx_strcpy_alloc(&exp, &exp_alloc, &exp_offset, tmp);
941 
942 	ret = SUCCEED;
943 out:
944 	zbx_free(param);
945 	zbx_free(tmp);
946 
947 	if (SUCCEED == ret)
948 	{
949 		zbx_free(*data);
950 		*data = exp;
951 	}
952 	else
953 		zbx_free(exp);
954 
955 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
956 
957 	return ret;
958 }
959 
960 /******************************************************************************
961  *                                                                            *
962  * Function: lld_item_make                                                    *
963  *                                                                            *
964  * Purpose: creates a new item based on item prototype and lld data row       *
965  *                                                                            *
966  * Parameters: item_prototype - [IN] the item prototype                       *
967  *             lld_row        - [IN] the lld row                              *
968  *                                                                            *
969  * Returns: The created item or NULL if cannot create new item from prototype *
970  *                                                                            *
971  ******************************************************************************/
lld_item_make(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_row_t * lld_row,char ** error)972 static zbx_lld_item_t	*lld_item_make(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_row_t *lld_row,
973 		char **error)
974 {
975 	const char			*__function_name = "lld_item_make";
976 
977 	zbx_lld_item_t			*item;
978 	const struct zbx_json_parse	*jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
979 	char				err[MAX_STRING_LEN];
980 	int				ret;
981 
982 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
983 
984 	item = zbx_malloc(NULL, sizeof(zbx_lld_item_t));
985 
986 	item->itemid = 0;
987 	item->parent_itemid = item_prototype->itemid;
988 	item->lastcheck = 0;
989 	item->ts_delete = 0;
990 	item->key_proto = NULL;
991 
992 	item->name = zbx_strdup(NULL, item_prototype->name);
993 	item->name_proto = NULL;
994 	substitute_discovery_macros(&item->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
995 	zbx_lrtrim(item->name, ZBX_WHITESPACE);
996 
997 	item->key = zbx_strdup(NULL, item_prototype->key);
998 	item->key_orig = NULL;
999 	ret = substitute_key_macros(&item->key, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, err, sizeof(err));
1000 
1001 	item->units = zbx_strdup(NULL, item_prototype->units);
1002 	item->units_orig = NULL;
1003 	substitute_discovery_macros(&item->units, jp_row, ZBX_MACRO_ANY, NULL, 0);
1004 	zbx_lrtrim(item->units, ZBX_WHITESPACE);
1005 
1006 	item->params = zbx_strdup(NULL, item_prototype->params);
1007 	item->params_orig = NULL;
1008 
1009 	if (ITEM_TYPE_CALCULATED == item_prototype->type)
1010 	{
1011 		if (SUCCEED == ret)
1012 			ret = substitute_formula_macros(&item->params, jp_row, err, sizeof(err));
1013 	}
1014 	else
1015 		substitute_discovery_macros(&item->params, jp_row, ZBX_MACRO_ANY, NULL, 0);
1016 
1017 	zbx_lrtrim(item->params, ZBX_WHITESPACE);
1018 
1019 	item->ipmi_sensor = zbx_strdup(NULL, item_prototype->ipmi_sensor);
1020 	item->ipmi_sensor_orig = NULL;
1021 	substitute_discovery_macros(&item->ipmi_sensor, jp_row, ZBX_MACRO_ANY, NULL, 0);
1022 	/* zbx_lrtrim(item->ipmi_sensor, ZBX_WHITESPACE); is not missing here */
1023 
1024 	item->snmp_oid = zbx_strdup(NULL, item_prototype->snmp_oid);
1025 	item->snmp_oid_orig = NULL;
1026 	substitute_key_macros(&item->snmp_oid, NULL, NULL, jp_row, MACRO_TYPE_SNMP_OID, NULL, 0);
1027 	zbx_lrtrim(item->snmp_oid, ZBX_WHITESPACE);
1028 
1029 	item->description = zbx_strdup(NULL, item_prototype->description);
1030 	item->description_orig = NULL;
1031 	substitute_discovery_macros(&item->description, jp_row, ZBX_MACRO_ANY, NULL, 0);
1032 	zbx_lrtrim(item->description, ZBX_WHITESPACE);
1033 
1034 	item->flags = ZBX_FLAG_LLD_ITEM_DISCOVERED;
1035 	item->lld_row = lld_row;
1036 
1037 	if (SUCCEED != ret)
1038 	{
1039 		*error = zbx_strdcatf(*error, "Cannot create item: %s.\n", err);
1040 		lld_item_free(item);
1041 		item = NULL;
1042 	}
1043 
1044 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1045 
1046 	return item;
1047 }
1048 
1049 /******************************************************************************
1050  *                                                                            *
1051  * Function: lld_item_update                                                  *
1052  *                                                                            *
1053  * Purpose: updates an existing item based on item prototype and lld data row *
1054  *                                                                            *
1055  * Parameters: item_prototype - [IN] the item prototype                       *
1056  *             lld_row        - [IN] the lld row                              *
1057  *             item           - [IN] an existing item or NULL                 *
1058  *                                                                            *
1059  ******************************************************************************/
lld_item_update(const zbx_lld_item_prototype_t * item_prototype,const zbx_lld_row_t * lld_row,zbx_lld_item_t * item,char ** error)1060 static void	lld_item_update(const zbx_lld_item_prototype_t *item_prototype, const zbx_lld_row_t *lld_row,
1061 		zbx_lld_item_t *item, char **error)
1062 {
1063 	const char		*__function_name = "lld_item_update";
1064 
1065 	char			*buffer = NULL, err[MAX_STRING_LEN];
1066 	struct zbx_json_parse	*jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
1067 
1068 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1069 
1070 	buffer = zbx_strdup(buffer, item_prototype->name);
1071 	substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1072 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
1073 	if (0 != strcmp(item->name, buffer))
1074 	{
1075 		item->name_proto = item->name;
1076 		item->name = buffer;
1077 		buffer = NULL;
1078 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_NAME;
1079 	}
1080 
1081 	if (0 != strcmp(item->key_proto, item_prototype->key))
1082 	{
1083 		buffer = zbx_strdup(buffer, item_prototype->key);
1084 
1085 		if (SUCCEED == substitute_key_macros(&buffer, NULL, NULL, jp_row, MACRO_TYPE_ITEM_KEY, err,
1086 				sizeof(err)))
1087 		{
1088 			item->key_orig = item->key;
1089 			item->key = buffer;
1090 			buffer = NULL;
1091 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_KEY;
1092 		}
1093 		else
1094 			*error = zbx_strdcatf(*error, "Cannot update item: %s.\n", err);
1095 	}
1096 
1097 	buffer = zbx_strdup(buffer, item_prototype->units);
1098 	substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1099 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
1100 	if (0 != strcmp(item->units, buffer))
1101 	{
1102 		item->units_orig = item->units;
1103 		item->units = buffer;
1104 		buffer = NULL;
1105 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_UNITS;
1106 	}
1107 
1108 	buffer = zbx_strdup(buffer, item_prototype->params);
1109 
1110 	if (ITEM_TYPE_CALCULATED == item_prototype->type)
1111 	{
1112 		if (SUCCEED == substitute_formula_macros(&buffer, jp_row, err, sizeof(err)))
1113 		{
1114 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
1115 
1116 			if (0 != strcmp(item->params, buffer))
1117 			{
1118 				item->params_orig = item->params;
1119 				item->params = buffer;
1120 				buffer = NULL;
1121 				item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS;
1122 			}
1123 		}
1124 		else
1125 			*error = zbx_strdcatf(*error, "Cannot update item: %s.\n", err);
1126 	}
1127 	else
1128 	{
1129 		substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1130 		zbx_lrtrim(buffer, ZBX_WHITESPACE);
1131 
1132 		if (0 != strcmp(item->params, buffer))
1133 		{
1134 			item->params_orig = item->params;
1135 			item->params = buffer;
1136 			buffer = NULL;
1137 			item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS;
1138 		}
1139 	}
1140 
1141 	buffer = zbx_strdup(buffer, item_prototype->ipmi_sensor);
1142 	substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1143 	/* zbx_lrtrim(buffer, ZBX_WHITESPACE); is not missing here */
1144 	if (0 != strcmp(item->ipmi_sensor, buffer))
1145 	{
1146 		item->ipmi_sensor_orig = item->ipmi_sensor;
1147 		item->ipmi_sensor = buffer;
1148 		buffer = NULL;
1149 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR;
1150 	}
1151 
1152 	buffer = zbx_strdup(buffer, item_prototype->snmp_oid);
1153 	substitute_key_macros(&buffer, NULL, NULL, jp_row, MACRO_TYPE_SNMP_OID, NULL, 0);
1154 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
1155 	if (0 != strcmp(item->snmp_oid, buffer))
1156 	{
1157 		item->snmp_oid_orig = item->snmp_oid;
1158 		item->snmp_oid = buffer;
1159 		buffer = NULL;
1160 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID;
1161 	}
1162 
1163 	buffer = zbx_strdup(buffer, item_prototype->description);
1164 	substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
1165 	zbx_lrtrim(buffer, ZBX_WHITESPACE);
1166 	if (0 != strcmp(item->description, buffer))
1167 	{
1168 		item->description_orig = item->description;
1169 		item->description = buffer;
1170 		buffer = NULL;
1171 		item->flags |= ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION;
1172 	}
1173 
1174 	item->flags |= ZBX_FLAG_LLD_ITEM_DISCOVERED;
1175 	item->lld_row = lld_row;
1176 
1177 	zbx_free(buffer);
1178 
1179 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1180 }
1181 
1182 /******************************************************************************
1183  *                                                                            *
1184  * Function: lld_items_make                                                   *
1185  *                                                                            *
1186  * Purpose: updates existing items and creates new ones based on item         *
1187  *          item prototypes and lld data                                      *
1188  *                                                                            *
1189  * Parameters: item_prototypes - [IN] the item prototypes                     *
1190  *             lld_rows        - [IN] the lld data rows                       *
1191  *             items           - [IN/OUT] sorted list of items                *
1192  *             items_index     - [OUT] index of items based on prototype ids  *
1193  *                                     and lld rows. Used to quckly find an   *
1194  *                                     item by prototype and lld_row.         *
1195  *                                                                            *
1196  ******************************************************************************/
lld_items_make(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * lld_rows,zbx_vector_ptr_t * items,zbx_hashset_t * items_index,char ** error)1197 static void	lld_items_make(const zbx_vector_ptr_t *item_prototypes, const zbx_vector_ptr_t *lld_rows,
1198 		zbx_vector_ptr_t *items, zbx_hashset_t *items_index, char **error)
1199 {
1200 	const char			*__function_name = "lld_items_make";
1201 	int				i, j, index;
1202 	zbx_lld_item_prototype_t	*item_prototype;
1203 	zbx_lld_item_t			*item;
1204 	zbx_lld_row_t			*lld_row;
1205 	zbx_lld_item_index_t		*item_index, item_index_local;
1206 	char				*buffer = NULL;
1207 
1208 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1209 
1210 	/* create the items index */
1211 	for (i = 0; i < item_prototypes->values_num; i++)
1212 	{
1213 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
1214 
1215 		for (j = 0; j < lld_rows->values_num; j++)
1216 			zbx_vector_ptr_append(&item_prototype->lld_rows, lld_rows->values[j]);
1217 	}
1218 
1219 	/* Iterate in reverse order because usually the items are created in the same order as     */
1220 	/* incoming lld rows. Iterating in reverse optimizes lld_row removal from item prototypes. */
1221 	for (i = items->values_num - 1; i >= 0; i--)
1222 	{
1223 		item = (zbx_lld_item_t *)items->values[i];
1224 
1225 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
1226 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1227 		{
1228 			THIS_SHOULD_NEVER_HAPPEN;
1229 			continue;
1230 		}
1231 
1232 		item_prototype = item_prototypes->values[index];
1233 
1234 		for (j = item_prototype->lld_rows.values_num - 1; j >= 0; j--)
1235 		{
1236 			lld_row = (zbx_lld_row_t *)item_prototype->lld_rows.values[j];
1237 
1238 			buffer = zbx_strdup(buffer, item->key_proto);
1239 
1240 			if (SUCCEED != substitute_key_macros(&buffer, NULL, NULL, &lld_row->jp_row, MACRO_TYPE_ITEM_KEY,
1241 					NULL, 0))
1242 			{
1243 				continue;
1244 			}
1245 
1246 			if (0 == strcmp(item->key, buffer))
1247 			{
1248 				item_index_local.parent_itemid = item->parent_itemid;
1249 				item_index_local.lld_row = lld_row;
1250 				item_index_local.item = item;
1251 				zbx_hashset_insert(items_index, &item_index_local, sizeof(item_index_local));
1252 
1253 				zbx_vector_ptr_remove_noorder(&item_prototype->lld_rows, j);
1254 				break;
1255 			}
1256 		}
1257 	}
1258 
1259 	zbx_free(buffer);
1260 
1261 	/* update/create discovered items */
1262 	for (i = 0; i < item_prototypes->values_num; i++)
1263 	{
1264 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
1265 		item_index_local.parent_itemid = item_prototype->itemid;
1266 
1267 		for (j = 0; j < lld_rows->values_num; j++)
1268 		{
1269 			item_index_local.lld_row = (zbx_lld_row_t *)lld_rows->values[j];
1270 
1271 			if (NULL == (item_index = zbx_hashset_search(items_index, &item_index_local)))
1272 			{
1273 				if (NULL != (item = lld_item_make(item_prototype, item_index_local.lld_row, error)))
1274 				{
1275 					/* add the created item to items vector and update index */
1276 					zbx_vector_ptr_append(items, item);
1277 					item_index_local.item = item;
1278 					zbx_hashset_insert(items_index, &item_index_local, sizeof(item_index_local));
1279 				}
1280 			}
1281 			else
1282 				lld_item_update(item_prototype, item_index_local.lld_row, item_index->item, error);
1283 		}
1284 	}
1285 
1286 	zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1287 
1288 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d items", __function_name, items->values_num);
1289 }
1290 
1291 /******************************************************************************
1292  *                                                                            *
1293  * Function: lld_items_save                                                   *
1294  *                                                                            *
1295  * Parameters: hostid          - [IN] parent host id                          *
1296  *             item_prototypes - [IN] item prototypes                         *
1297  *             items           - [IN/OUT] items to save                       *
1298  *             host_locked     - [IN/OUT] host record is locked               *
1299  *                                                                            *
1300  * Return value: SUCCEED - if items were successfully saved or saving was not *
1301  *                         necessary                                          *
1302  *               FAIL    - items cannot be saved                              *
1303  *                                                                            *
1304  ******************************************************************************/
lld_items_save(zbx_uint64_t hostid,const zbx_vector_ptr_t * item_prototypes,zbx_vector_ptr_t * items,int * host_locked)1305 static int	lld_items_save(zbx_uint64_t hostid, const zbx_vector_ptr_t *item_prototypes, zbx_vector_ptr_t *items,
1306 		int *host_locked)
1307 {
1308 	const char			*__function_name = "lld_items_save";
1309 
1310 	int				ret = SUCCEED, index, i, new_items = 0, upd_items = 0;
1311 	zbx_lld_item_t			*item;
1312 	const zbx_lld_item_prototype_t	*item_prototype;
1313 	zbx_uint64_t			itemid = 0, itemdiscoveryid = 0;
1314 	char				*sql = NULL, *value_esc;
1315 	size_t				sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0;
1316 	zbx_db_insert_t			db_insert, db_insert_idiscovery;
1317 
1318 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1319 
1320 	if (0 == items->values_num)
1321 		goto out;
1322 
1323 	for (i = 0; i < items->values_num; i++)
1324 	{
1325 		item = (zbx_lld_item_t *)items->values[i];
1326 
1327 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1328 			continue;
1329 
1330 		if (0 == item->itemid)
1331 			new_items++;
1332 		else if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE))
1333 			upd_items++;
1334 	}
1335 
1336 	if (0 == new_items && 0 == upd_items)
1337 		goto out;
1338 
1339 	if (0 == *host_locked)
1340 	{
1341 		if (SUCCEED != DBlock_hostid(hostid))
1342 		{
1343 			/* the host was removed while processing lld rule */
1344 			ret = FAIL;
1345 			goto out;
1346 		}
1347 
1348 		*host_locked = 1;
1349 	}
1350 
1351 	if (0 != new_items)
1352 	{
1353 		itemid = DBget_maxid_num("items", new_items);
1354 		itemdiscoveryid = DBget_maxid_num("item_discovery", new_items);
1355 
1356 		zbx_db_insert_prepare(&db_insert, "items", "itemid", "name", "key_", "hostid", "type", "value_type",
1357 				"data_type", "delay", "delay_flex", "history", "trends", "status", "trapper_hosts",
1358 				"units", "multiplier", "delta", "formula", "logtimefmt", "valuemapid", "params",
1359 				"ipmi_sensor", "snmp_community", "snmp_oid", "port", "snmpv3_securityname",
1360 				"snmpv3_securitylevel", "snmpv3_authprotocol", "snmpv3_authpassphrase",
1361 				"snmpv3_privprotocol", "snmpv3_privpassphrase", "authtype", "username", "password",
1362 				"publickey", "privatekey", "description", "interfaceid", "flags", "snmpv3_contextname",
1363 				NULL);
1364 
1365 		zbx_db_insert_prepare(&db_insert_idiscovery, "item_discovery", "itemdiscoveryid", "itemid",
1366 				"parent_itemid", "key_", NULL);
1367 	}
1368 
1369 	if (0 != upd_items)
1370 	{
1371 		sql = zbx_malloc(sql, sql_alloc);
1372 		DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1373 	}
1374 
1375 	for (i = 0; i < items->values_num; i++)
1376 	{
1377 		item = (zbx_lld_item_t *)items->values[i];
1378 
1379 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1380 			continue;
1381 
1382 		if (FAIL == (index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
1383 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1384 		{
1385 			THIS_SHOULD_NEVER_HAPPEN;
1386 			continue;
1387 		}
1388 
1389 		item_prototype = item_prototypes->values[index];
1390 
1391 		if (0 == item->itemid)
1392 		{
1393 			item->itemid = itemid++;
1394 
1395 			zbx_db_insert_add_values(&db_insert, item->itemid, item->name, item->key, hostid,
1396 					(int)item_prototype->type, (int)item_prototype->value_type,
1397 					(int)item_prototype->data_type, item_prototype->delay,
1398 					item_prototype->delay_flex, item_prototype->history, item_prototype->trends,
1399 					(int)item_prototype->status, item_prototype->trapper_hosts, item->units,
1400 					(int)item_prototype->multiplier, (int)item_prototype->delta,
1401 					item_prototype->formula, item_prototype->logtimefmt, item_prototype->valuemapid,
1402 					item->params, item->ipmi_sensor, item_prototype->snmp_community, item->snmp_oid,
1403 					item_prototype->port, item_prototype->snmpv3_securityname,
1404 					(int)item_prototype->snmpv3_securitylevel,
1405 					(int)item_prototype->snmpv3_authprotocol, item_prototype->snmpv3_authpassphrase,
1406 					(int)item_prototype->snmpv3_privprotocol, item_prototype->snmpv3_privpassphrase,
1407 					(int)item_prototype->authtype, item_prototype->username,
1408 					item_prototype->password, item_prototype->publickey, item_prototype->privatekey,
1409 					item->description, item_prototype->interfaceid, (int)ZBX_FLAG_DISCOVERY_CREATED,
1410 					item_prototype->snmpv3_contextname);
1411 
1412 			zbx_db_insert_add_values(&db_insert_idiscovery, itemdiscoveryid++, item->itemid,
1413 					item->parent_itemid, item_prototype->key);
1414 		}
1415 		else
1416 		{
1417 			if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE))
1418 			{
1419 				const char	*d = "";
1420 
1421 				zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update items set ");
1422 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_NAME))
1423 				{
1424 					value_esc = DBdyn_escape_string(item->name);
1425 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", value_esc);
1426 					zbx_free(value_esc);
1427 					d = ",";
1428 				}
1429 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1430 				{
1431 					value_esc = DBdyn_escape_string(item->key);
1432 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%skey_='%s'", d, value_esc);
1433 					zbx_free(value_esc);
1434 					d = ",";
1435 				}
1436 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TYPE))
1437 				{
1438 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%stype=%d", d,
1439 							(int)item_prototype->type);
1440 					d = ",";
1441 				}
1442 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VALUE_TYPE))
1443 				{
1444 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%svalue_type=%d",
1445 							d, (int)item_prototype->value_type);
1446 					d = ",";
1447 				}
1448 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DATA_TYPE))
1449 				{
1450 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdata_type=%d",
1451 							d, (int)item_prototype->data_type);
1452 					d = ",";
1453 				}
1454 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DELAY))
1455 				{
1456 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdelay=%d", d,
1457 							item_prototype->delay);
1458 					d = ",";
1459 				}
1460 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DELAY_FLEX))
1461 				{
1462 					value_esc = DBdyn_escape_string(item_prototype->delay_flex);
1463 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdelay_flex='%s'",
1464 							d, value_esc);
1465 					zbx_free(value_esc);
1466 					d = ",";
1467 				}
1468 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_HISTORY))
1469 				{
1470 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%shistory=%d",
1471 							d, item_prototype->history);
1472 					d = ",";
1473 				}
1474 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TRENDS))
1475 				{
1476 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%strends=%d", d,
1477 							item_prototype->trends);
1478 					d = ",";
1479 				}
1480 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_TRAPPER_HOSTS))
1481 				{
1482 					value_esc = DBdyn_escape_string(item_prototype->trapper_hosts);
1483 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%strapper_hosts='%s'",
1484 							d, value_esc);
1485 					zbx_free(value_esc);
1486 					d = ",";
1487 				}
1488 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_UNITS))
1489 				{
1490 					value_esc = DBdyn_escape_string(item->units);
1491 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sunits='%s'",
1492 							d, value_esc);
1493 					zbx_free(value_esc);
1494 					d = ",";
1495 				}
1496 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_MULTIPLIER))
1497 				{
1498 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%smultiplier=%d",
1499 							d, (int)item_prototype->multiplier);
1500 					d = ",";
1501 				}
1502 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DELTA))
1503 				{
1504 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdelta=%d",
1505 							d, (int)item_prototype->delta);
1506 					d = ",";
1507 				}
1508 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_FORMULA))
1509 				{
1510 					value_esc = DBdyn_escape_string(item_prototype->formula);
1511 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sformula='%s'",
1512 							d, value_esc);
1513 					zbx_free(value_esc);
1514 					d = ",";
1515 				}
1516 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_LOGTIMEFMT))
1517 				{
1518 					value_esc = DBdyn_escape_string(item_prototype->logtimefmt);
1519 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%slogtimefmt='%s'",
1520 							d, value_esc);
1521 					zbx_free(value_esc);
1522 					d = ",";
1523 				}
1524 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_VALUEMAPID))
1525 				{
1526 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%svaluemapid=%s",
1527 							d, DBsql_id_ins(item_prototype->valuemapid));
1528 					d = ",";
1529 				}
1530 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PARAMS))
1531 				{
1532 					value_esc = DBdyn_escape_string(item->params);
1533 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sparams='%s'",
1534 							d, value_esc);
1535 					zbx_free(value_esc);
1536 					d = ",";
1537 				}
1538 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_IPMI_SENSOR))
1539 				{
1540 					value_esc = DBdyn_escape_string(item->ipmi_sensor);
1541 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sipmi_sensor='%s'",
1542 							d, value_esc);
1543 					zbx_free(value_esc);
1544 					d = ",";
1545 				}
1546 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_COMMUNITY))
1547 				{
1548 					value_esc = DBdyn_escape_string(item_prototype->snmp_community);
1549 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ssnmp_community='%s'",
1550 							d, value_esc);
1551 					zbx_free(value_esc);
1552 					d = ",";
1553 				}
1554 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMP_OID))
1555 				{
1556 					value_esc = DBdyn_escape_string(item->snmp_oid);
1557 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ssnmp_oid='%s'",
1558 							d, value_esc);
1559 					zbx_free(value_esc);
1560 					d = ",";
1561 				}
1562 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PORT))
1563 				{
1564 					value_esc = DBdyn_escape_string(item_prototype->port);
1565 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sport='%s'",
1566 							d, value_esc);
1567 					zbx_free(value_esc);
1568 					d = ",";
1569 				}
1570 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYNAME))
1571 				{
1572 					value_esc = DBdyn_escape_string(item_prototype->snmpv3_securityname);
1573 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1574 							"%ssnmpv3_securityname='%s'", d, value_esc);
1575 					zbx_free(value_esc);
1576 					d = ",";
1577 				}
1578 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_SECURITYLEVEL))
1579 				{
1580 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1581 							"%ssnmpv3_securitylevel=%d", d,
1582 							(int)item_prototype->snmpv3_securitylevel);
1583 					d = ",";
1584 				}
1585 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPROTOCOL))
1586 				{
1587 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1588 							"%ssnmpv3_authprotocol=%d", d,
1589 							(int)item_prototype->snmpv3_authprotocol);
1590 					d = ",";
1591 				}
1592 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_AUTHPASSPHRASE))
1593 				{
1594 					value_esc = DBdyn_escape_string(item_prototype->snmpv3_authpassphrase);
1595 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1596 							"%ssnmpv3_authpassphrase='%s'", d, value_esc);
1597 					zbx_free(value_esc);
1598 					d = ",";
1599 				}
1600 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPROTOCOL))
1601 				{
1602 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1603 							"%ssnmpv3_privprotocol=%d", d,
1604 							(int)item_prototype->snmpv3_privprotocol);
1605 					d = ",";
1606 				}
1607 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_PRIVPASSPHRASE))
1608 				{
1609 					value_esc = DBdyn_escape_string(item_prototype->snmpv3_privpassphrase);
1610 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1611 							"%ssnmpv3_privpassphrase='%s'", d, value_esc);
1612 					zbx_free(value_esc);
1613 					d = ",";
1614 				}
1615 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_AUTHTYPE))
1616 				{
1617 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sauthtype=%d",
1618 							d, (int)item_prototype->authtype);
1619 					d = ",";
1620 				}
1621 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_USERNAME))
1622 				{
1623 					value_esc = DBdyn_escape_string(item_prototype->username);
1624 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%susername='%s'",
1625 							d, value_esc);
1626 					zbx_free(value_esc);
1627 					d = ",";
1628 				}
1629 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PASSWORD))
1630 				{
1631 					value_esc = DBdyn_escape_string(item_prototype->password);
1632 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spassword='%s'",
1633 							d, value_esc);
1634 					zbx_free(value_esc);
1635 					d = ",";
1636 				}
1637 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PUBLICKEY))
1638 				{
1639 					value_esc = DBdyn_escape_string(item_prototype->publickey);
1640 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spublickey='%s'",
1641 							d, value_esc);
1642 					zbx_free(value_esc);
1643 					d = ",";
1644 				}
1645 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_PRIVATEKEY))
1646 				{
1647 					value_esc = DBdyn_escape_string(item_prototype->privatekey);
1648 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sprivatekey='%s'",
1649 							d, value_esc);
1650 					zbx_free(value_esc);
1651 					d = ",";
1652 				}
1653 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_DESCRIPTION))
1654 				{
1655 					value_esc = DBdyn_escape_string(item->description);
1656 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdescription='%s'",
1657 							d, value_esc);
1658 					zbx_free(value_esc);
1659 					d = ",";
1660 
1661 				}
1662 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_INTERFACEID))
1663 				{
1664 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sinterfaceid=%s",
1665 							d, DBsql_id_ins(item_prototype->interfaceid));
1666 					d = ",";
1667 				}
1668 				if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_SNMPV3_CONTEXTNAME))
1669 				{
1670 					value_esc = DBdyn_escape_string(item_prototype->snmpv3_contextname);
1671 					zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1672 							"%ssnmpv3_contextname='%s'", d, value_esc);
1673 					zbx_free(value_esc);
1674 				}
1675 
1676 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where itemid=" ZBX_FS_UI64 ";\n",
1677 						item->itemid);
1678 			}
1679 
1680 			if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
1681 			{
1682 				value_esc = DBdyn_escape_string(item_prototype->key);
1683 				zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1684 						"update item_discovery"
1685 						" set key_='%s'"
1686 						" where itemid=" ZBX_FS_UI64 ";\n",
1687 						value_esc, item->itemid);
1688 				zbx_free(value_esc);
1689 			}
1690 		}
1691 
1692 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
1693 	}
1694 
1695 	if (0 != upd_items)
1696 	{
1697 		DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1698 		DBexecute("%s", sql);
1699 		zbx_free(sql);
1700 	}
1701 
1702 	if (0 != new_items)
1703 	{
1704 		zbx_db_insert_execute(&db_insert);
1705 		zbx_db_insert_clean(&db_insert);
1706 
1707 		zbx_db_insert_execute(&db_insert_idiscovery);
1708 		zbx_db_insert_clean(&db_insert_idiscovery);
1709 
1710 		zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1711 	}
1712 out:
1713 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1714 
1715 	return ret;
1716 }
1717 
1718 /******************************************************************************
1719  *                                                                            *
1720  * Function: lld_applications_save                                            *
1721  *                                                                            *
1722  * Parameters: hostid                 - [IN] host id                          *
1723  *             applications           - [IN/OUT] applications to save         *
1724  *             application_prototypes - [IN] the application prototypes       *
1725  *             host_locked            - [IN/OUT] host record is locked        *
1726  *                                                                            *
1727  ******************************************************************************/
lld_applications_save(zbx_uint64_t hostid,zbx_vector_ptr_t * applications,const zbx_vector_ptr_t * application_prototypes,int * host_locked)1728 static int	lld_applications_save(zbx_uint64_t hostid, zbx_vector_ptr_t *applications,
1729 		const zbx_vector_ptr_t *application_prototypes, int *host_locked)
1730 {
1731 	const char				*__function_name = "lld_applications_save";
1732 	int					ret = SUCCEED, i, new_applications = 0, new_discoveries = 0, index;
1733 	zbx_lld_application_t			*application;
1734 	const zbx_lld_application_prototype_t	*application_prototype;
1735 	zbx_uint64_t				applicationid, application_discoveryid;
1736 	zbx_db_insert_t				db_insert, db_insert_discovery;
1737 	zbx_vector_uint64_t			del_applicationids, del_discoveryids;
1738 	char					*sql_a = NULL, *sql_ad = NULL, *name;
1739 	size_t					sql_a_alloc = 0, sql_a_offset = 0, sql_ad_alloc = 0, sql_ad_offset = 0;
1740 
1741 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1742 
1743 	if (0 == applications->values_num)
1744 		goto out;
1745 
1746 	if (0 == *host_locked)
1747 	{
1748 		if (SUCCEED != DBlock_hostid(hostid))
1749 		{
1750 			/* the host was removed while processing lld rule */
1751 			ret = FAIL;
1752 			goto out;
1753 		}
1754 
1755 		*host_locked = 1;
1756 	}
1757 
1758 	zbx_vector_uint64_create(&del_applicationids);
1759 	zbx_vector_uint64_create(&del_discoveryids);
1760 
1761 	/* Count new applications and application discoveries.                      */
1762 	/* Note that an application might have been discovered by another lld rule. */
1763 	/* In this case the discovered items will be linked to this application and */
1764 	/* new application discovery record, linking the prototype to this          */
1765 	/* application, will be created.                                            */
1766 	for (i = 0; i < applications->values_num; i++)
1767 	{
1768 		application = (zbx_lld_application_t *)applications->values[i];
1769 
1770 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_REMOVE))
1771 		{
1772 			zbx_vector_uint64_append(&del_applicationids, application->applicationid);
1773 			continue;
1774 		}
1775 
1776 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
1777 			continue;
1778 
1779 		if (0 == application->applicationid)
1780 			new_applications++;
1781 
1782 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY))
1783 			new_discoveries++;
1784 	}
1785 
1786 	/* insert new applications, application discoveries and prepare a list of applications to be removed */
1787 
1788 	if (0 != new_applications)
1789 	{
1790 		applicationid = DBget_maxid_num("applications", new_applications);
1791 		zbx_db_insert_prepare(&db_insert, "applications", "applicationid", "hostid", "name", "flags", NULL);
1792 	}
1793 
1794 	if (0 != new_discoveries)
1795 	{
1796 		application_discoveryid = DBget_maxid_num("application_discovery", new_discoveries);
1797 		zbx_db_insert_prepare(&db_insert_discovery, "application_discovery", "application_discoveryid",
1798 				"applicationid", "application_prototypeid", "name", NULL);
1799 	}
1800 
1801 	for (i = 0; i < applications->values_num; i++)
1802 	{
1803 		DBexecute_overflowed_sql(&sql_a, &sql_a_alloc, &sql_a_offset);
1804 		DBexecute_overflowed_sql(&sql_ad, &sql_ad_alloc, &sql_ad_offset);
1805 
1806 		application = (zbx_lld_application_t *)applications->values[i];
1807 
1808 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY))
1809 		{
1810 			zbx_vector_uint64_append(&del_discoveryids, application->application_discoveryid);
1811 			continue;
1812 		}
1813 
1814 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
1815 			continue;
1816 
1817 		if (FAIL == (index = zbx_vector_ptr_search(application_prototypes,
1818 				&application->application_prototypeid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1819 		{
1820 			THIS_SHOULD_NEVER_HAPPEN;
1821 			continue;
1822 		}
1823 
1824 		application_prototype = (zbx_lld_application_prototype_t *)application_prototypes->values[index];
1825 
1826 		if (0 == application->applicationid)
1827 		{
1828 			application->applicationid = applicationid++;
1829 			zbx_db_insert_add_values(&db_insert, application->applicationid, hostid, application->name,
1830 					ZBX_FLAG_DISCOVERY_CREATED);
1831 		}
1832 
1833 		if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
1834 		{
1835 			name = DBdyn_escape_string(application->name);
1836 			zbx_snprintf_alloc(&sql_a, &sql_a_alloc, &sql_a_offset,
1837 					"update applications set name='%s'"
1838 					" where applicationid=" ZBX_FS_UI64 ";\n",
1839 					name, application->applicationid);
1840 			zbx_free(name);
1841 
1842 			name = DBdyn_escape_string(application_prototype->name);
1843 			zbx_snprintf_alloc(&sql_ad, &sql_ad_alloc, &sql_ad_offset,
1844 					"update application_discovery set name='%s'"
1845 					" where application_discoveryid=" ZBX_FS_UI64 ";\n",
1846 					name, application->application_discoveryid);
1847 			zbx_free(name);
1848 			continue;
1849 		}
1850 
1851 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY))
1852 			continue;
1853 
1854 		application->application_discoveryid = application_discoveryid++;
1855 		zbx_db_insert_add_values(&db_insert_discovery, application->application_discoveryid,
1856 				application->applicationid, application->application_prototypeid,
1857 				application_prototype->name);
1858 	}
1859 
1860 	if (0 != del_applicationids.values_num)
1861 	{
1862 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "delete from applications where");
1863 		DBadd_condition_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "applicationid", del_applicationids.values,
1864 				del_applicationids.values_num);
1865 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, ";\n");
1866 	}
1867 
1868 	if (0 != del_discoveryids.values_num)
1869 	{
1870 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "delete from application_discovery where");
1871 		DBadd_condition_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, "application_discoveryid",
1872 				del_discoveryids.values, del_discoveryids.values_num);
1873 		zbx_strcpy_alloc(&sql_a, &sql_a_alloc, &sql_a_offset, ";\n");
1874 	}
1875 
1876 	if (NULL != sql_a)
1877 	{
1878 		DBexecute("%s", sql_a);
1879 		zbx_free(sql_a);
1880 	}
1881 
1882 	if (NULL != sql_ad)
1883 	{
1884 		DBexecute("%s", sql_ad);
1885 		zbx_free(sql_ad);
1886 	}
1887 
1888 	if (0 != new_applications)
1889 	{
1890 		zbx_db_insert_execute(&db_insert);
1891 		zbx_db_insert_clean(&db_insert);
1892 
1893 		zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
1894 	}
1895 
1896 	if (0 != new_discoveries)
1897 	{
1898 		zbx_db_insert_execute(&db_insert_discovery);
1899 		zbx_db_insert_clean(&db_insert_discovery);
1900 	}
1901 
1902 	zbx_vector_uint64_destroy(&del_discoveryids);
1903 	zbx_vector_uint64_destroy(&del_applicationids);
1904 out:
1905 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1906 
1907 	return ret;
1908 }
1909 
1910 /******************************************************************************
1911  *                                                                            *
1912  * Function: lld_item_application_validate                                    *
1913  *                                                                            *
1914  * Purpose: validates undiscovered item-application link to determine if it   *
1915  *          should be removed                                                 *
1916  *                                                                            *
1917  * Parameters: items_application - [IN] an item-application link to validate  *
1918  *             items             - [IN] the related items                     *
1919  *             applications      - [IN] the related applications              *
1920  *                                                                            *
1921  * Return value: SUCCEED - item-application link should not be removed        *
1922  *               FAIL    - item-application link should be removed            *
1923  *                                                                            *
1924  * Comments: Undiscovered item-application link must be removed if either the *
1925  *           application was not discovered or item was discovered.           *
1926  *           The only case when undiscovered item-application link is not     *
1927  *           removed is when we have valid application and undiscovered item. *
1928  *           In this case we leave item-application link untouched and it     *
1929  *           will 'expire' together with item.                                *
1930  *                                                                            *
1931  ******************************************************************************/
lld_item_application_validate(const zbx_lld_item_application_t * item_application,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * applications)1932 static int	lld_item_application_validate(const zbx_lld_item_application_t *item_application,
1933 		const zbx_vector_ptr_t *items, const zbx_vector_ptr_t *applications)
1934 {
1935 	const zbx_lld_application_t	*application;
1936 	const zbx_lld_item_t		*item;
1937 	int				index;
1938 
1939 	if (FAIL == (index = zbx_vector_ptr_bsearch(applications, &item_application->application_ref.applicationid,
1940 			ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1941 	{
1942 		/* Applications vector contains only discovered applications and  */
1943 		/* apparently the item was linked to a normal application.        */
1944 		/* Undiscovered item-application links to normal application must */
1945 		/* be removed if item has been also discovered - this means that  */
1946 		/* the item prototype - application link was removed by frontend. */
1947 		goto check_item;
1948 	}
1949 
1950 	application = (zbx_lld_application_t *)applications->values[index];
1951 
1952 	if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
1953 		return FAIL;
1954 
1955 check_item:
1956 	if (FAIL == (index = zbx_vector_ptr_bsearch(items, &item_application->item_ref.itemid,
1957 			ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
1958 	{
1959 		THIS_SHOULD_NEVER_HAPPEN;
1960 		return FAIL;
1961 	}
1962 
1963 	item = (zbx_lld_item_t *)items->values[index];
1964 
1965 	if (0 != (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
1966 		return FAIL;
1967 
1968 	return SUCCEED;
1969 }
1970 
1971 /******************************************************************************
1972  *                                                                            *
1973  * Function: lld_items_applications_save                                      *
1974  *                                                                            *
1975  * Parameters: items_applications - [IN] item-application links               *
1976  *                                                                            *
1977  ******************************************************************************/
lld_items_applications_save(zbx_hashset_t * items_applications,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * applications)1978 static void	lld_items_applications_save(zbx_hashset_t *items_applications, const zbx_vector_ptr_t *items,
1979 		const zbx_vector_ptr_t *applications)
1980 {
1981 	const char			*__function_name = "lld_items_applications_save";
1982 	zbx_hashset_iter_t		iter;
1983 	zbx_lld_item_application_t	*item_application;
1984 	zbx_vector_uint64_t		del_itemappids;
1985 	int				new_item_applications = 0;
1986 	zbx_uint64_t			itemappid, applicationid, itemid;
1987 	zbx_db_insert_t			db_insert;
1988 
1989 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1990 
1991 	if (0 == items_applications->num_data)
1992 		goto out;
1993 
1994 	zbx_vector_uint64_create(&del_itemappids);
1995 
1996 	/* count new item-application links */
1997 	zbx_hashset_iter_reset(items_applications, &iter);
1998 
1999 	while (NULL != (item_application = zbx_hashset_iter_next(&iter)))
2000 	{
2001 		if (0 == item_application->itemappid)
2002 			new_item_applications++;
2003 	}
2004 
2005 	if (0 != new_item_applications)
2006 	{
2007 		itemappid = DBget_maxid_num("items_applications", new_item_applications);
2008 		zbx_db_insert_prepare(&db_insert, "items_applications", "itemappid", "applicationid", "itemid", NULL);
2009 	}
2010 
2011 	zbx_hashset_iter_reset(items_applications, &iter);
2012 
2013 	while (NULL != (item_application = zbx_hashset_iter_next(&iter)))
2014 	{
2015 		if (0 != item_application->itemappid)
2016 		{
2017 			/* add for removal the old links that aren't discovered and can be removed */
2018 			if (0 == (item_application->flags & ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED) &&
2019 					FAIL == lld_item_application_validate(item_application, items, applications))
2020 			{
2021 				zbx_vector_uint64_append(&del_itemappids, item_application->itemappid);
2022 			}
2023 
2024 			continue;
2025 		}
2026 
2027 		if (0 == (applicationid = item_application->application_ref.applicationid))
2028 			applicationid = item_application->application_ref.application->applicationid;
2029 
2030 		if (0 == (itemid = item_application->item_ref.itemid))
2031 			itemid = item_application->item_ref.item->itemid;
2032 
2033 		item_application->itemappid = itemappid++;
2034 		zbx_db_insert_add_values(&db_insert, item_application->itemappid, applicationid, itemid);
2035 	}
2036 
2037 	if (0 != new_item_applications)
2038 	{
2039 		zbx_db_insert_execute(&db_insert);
2040 		zbx_db_insert_clean(&db_insert);
2041 	}
2042 
2043 	/* remove deprecated links */
2044 	if (0 != del_itemappids.values_num)
2045 	{
2046 		char	*sql = NULL;
2047 		size_t	sql_alloc = 0, sql_offset = 0;
2048 
2049 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from items_applications where");
2050 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemappid", del_itemappids.values,
2051 				del_itemappids.values_num);
2052 
2053 		DBexecute("%s", sql);
2054 
2055 		zbx_free(sql);
2056 	}
2057 
2058 	zbx_vector_uint64_destroy(&del_itemappids);
2059 out:
2060 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2061 }
2062 
2063 /******************************************************************************
2064  *                                                                            *
2065  * Function: lld_remove_lost_items                                            *
2066  *                                                                            *
2067  * Purpose: updates item_discovery.lastcheck and item_discovery.ts_delete     *
2068  *          fields; removes lost resources                                    *
2069  *                                                                            *
2070  ******************************************************************************/
lld_remove_lost_items(const zbx_vector_ptr_t * items,unsigned short lifetime,int lastcheck)2071 static void	lld_remove_lost_items(const zbx_vector_ptr_t *items, unsigned short lifetime, int lastcheck)
2072 {
2073 	const char			*__function_name = "lld_remove_lost_items";
2074 	char				*sql = NULL;
2075 	size_t				sql_alloc = 0, sql_offset = 0;
2076 	zbx_lld_item_t			*item;
2077 	zbx_vector_uint64_t		del_itemids, lc_itemids, ts_itemids;
2078 	zbx_vector_uint64_pair_t	discovery_itemts;
2079 	int				i, lifetime_sec;
2080 
2081 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2082 
2083 	if (0 == items->values_num)
2084 		goto out;
2085 
2086 	lifetime_sec = lifetime * SEC_PER_DAY;
2087 
2088 	zbx_vector_uint64_create(&del_itemids);
2089 	zbx_vector_uint64_create(&lc_itemids);
2090 	zbx_vector_uint64_create(&ts_itemids);
2091 	zbx_vector_uint64_pair_create(&discovery_itemts);
2092 
2093 	for (i = 0; i < items->values_num; i++)
2094 	{
2095 		item = (zbx_lld_item_t *)items->values[i];
2096 
2097 		if (0 == item->itemid)
2098 			continue;
2099 
2100 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
2101 		{
2102 			if (item->lastcheck < lastcheck - lifetime_sec)
2103 			{
2104 				zbx_vector_uint64_append(&del_itemids, item->itemid);
2105 			}
2106 			else if (item->ts_delete != item->lastcheck + lifetime_sec)
2107 			{
2108 				zbx_uint64_pair_t	itemts;
2109 
2110 				itemts.first = item->itemid;
2111 				itemts.second = item->lastcheck + lifetime_sec;
2112 				zbx_vector_uint64_pair_append(&discovery_itemts, itemts);
2113 			}
2114 		}
2115 		else
2116 		{
2117 			zbx_vector_uint64_append(&lc_itemids, item->itemid);
2118 			if (0 != item->ts_delete)
2119 				zbx_vector_uint64_append(&ts_itemids, item->itemid);
2120 		}
2121 	}
2122 
2123 	if (0 == discovery_itemts.values_num && 0 == lc_itemids.values_num && 0 == ts_itemids.values_num &&
2124 			0 == del_itemids.values_num)
2125 	{
2126 		goto clean;
2127 	}
2128 
2129 	/* update item discovery table */
2130 
2131 	DBbegin();
2132 
2133 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2134 
2135 	for (i = 0; i < discovery_itemts.values_num; i++)
2136 	{
2137 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2138 				"update item_discovery"
2139 				" set ts_delete=%d"
2140 				" where itemid=" ZBX_FS_UI64 ";\n",
2141 				(int)discovery_itemts.values[i].second, discovery_itemts.values[i].first);
2142 
2143 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
2144 	}
2145 
2146 	if (0 != lc_itemids.values_num)
2147 	{
2148 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update item_discovery set lastcheck=%d where",
2149 				lastcheck);
2150 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2151 				lc_itemids.values, lc_itemids.values_num);
2152 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2153 
2154 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
2155 	}
2156 
2157 	if (0 != ts_itemids.values_num)
2158 	{
2159 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update item_discovery set ts_delete=0 where");
2160 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2161 				ts_itemids.values, ts_itemids.values_num);
2162 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2163 	}
2164 
2165 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2166 
2167 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
2168 		DBexecute("%s", sql);
2169 
2170 	zbx_free(sql);
2171 
2172 	/* remove 'lost' items */
2173 	if (0 != del_itemids.values_num)
2174 	{
2175 		zbx_vector_uint64_sort(&del_itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2176 		DBdelete_items(&del_itemids);
2177 	}
2178 
2179 	DBcommit();
2180 clean:
2181 	zbx_vector_uint64_pair_destroy(&discovery_itemts);
2182 	zbx_vector_uint64_destroy(&ts_itemids);
2183 	zbx_vector_uint64_destroy(&lc_itemids);
2184 	zbx_vector_uint64_destroy(&del_itemids);
2185 out:
2186 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2187 }
2188 
2189 /******************************************************************************
2190  *                                                                            *
2191  * Function: lld_remove_lost_applications                                     *
2192  *                                                                            *
2193  * Purpose: updates application_discovery lastcheck and ts_delete fields,     *
2194  *          removes lost resources                                            *
2195  *                                                                            *
2196  ******************************************************************************/
lld_remove_lost_applications(zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * applications,unsigned short lifetime,int lastcheck)2197 static void	lld_remove_lost_applications(zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *applications,
2198 		unsigned short lifetime, int lastcheck)
2199 {
2200 	const char			*__function_name = "lld_remove_lost_applications";
2201 	DB_RESULT			result;
2202 	DB_ROW				row;
2203 	char				*sql = NULL;
2204 	size_t				sql_alloc = 0, sql_offset = 0;
2205 	zbx_vector_uint64_t		del_applicationids, del_discoveryids, ts_discoveryids, lc_discoveryids;
2206 	zbx_vector_uint64_pair_t	discovery_applicationts;
2207 	int				i, lifetime_sec, index;
2208 	const zbx_lld_application_t	*application;
2209 	zbx_uint64_t			applicationid;
2210 
2211 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2212 
2213 	if (0 == applications->values_num)
2214 		goto out;
2215 
2216 	lifetime_sec = lifetime * SEC_PER_DAY;
2217 
2218 	zbx_vector_uint64_create(&del_applicationids);
2219 	zbx_vector_uint64_create(&del_discoveryids);
2220 	zbx_vector_uint64_create(&ts_discoveryids);
2221 	zbx_vector_uint64_create(&lc_discoveryids);
2222 	zbx_vector_uint64_pair_create(&discovery_applicationts);
2223 
2224 	/* prepare application discovery update vector */
2225 	for (i = 0; i < applications->values_num; i++)
2226 	{
2227 		application = (const zbx_lld_application_t *)applications->values[i];
2228 
2229 		if (0 == application->applicationid)
2230 			continue;
2231 
2232 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
2233 		{
2234 			if (application->lastcheck < lastcheck - lifetime_sec)
2235 			{
2236 				zbx_vector_uint64_append(&del_applicationids, application->applicationid);
2237 				zbx_vector_uint64_append(&del_discoveryids, application->application_discoveryid);
2238 			}
2239 			else if (application->ts_delete != application->lastcheck + lifetime_sec)
2240 			{
2241 				zbx_uint64_pair_t	applicationts;
2242 
2243 				applicationts.first = application->application_discoveryid;
2244 				applicationts.second = application->lastcheck + lifetime_sec;
2245 				zbx_vector_uint64_pair_append(&discovery_applicationts, applicationts);
2246 			}
2247 		}
2248 		else
2249 		{
2250 			zbx_vector_uint64_append(&lc_discoveryids, application->application_discoveryid);
2251 			if (0 != application->ts_delete)
2252 				zbx_vector_uint64_append(&ts_discoveryids, application->application_discoveryid);
2253 		}
2254 	}
2255 
2256 	/* check if the applications are really 'lost' (not discovered by other discovery rules) */
2257 	if (0 != del_applicationids.values_num)
2258 	{
2259 		zbx_vector_uint64_sort(&del_applicationids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2260 
2261 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2262 				"select ad.applicationid from application_discovery ad,application_prototype ap"
2263 				" where ad.application_prototypeid=ap.application_prototypeid"
2264 					" and ap.itemid<>" ZBX_FS_UI64
2265 					" and",
2266 				lld_ruleid);
2267 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ad.applicationid", del_applicationids.values,
2268 				del_applicationids.values_num);
2269 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by ad.applicationid desc");
2270 
2271 		result = DBselect("%s", sql);
2272 
2273 		sql_offset = 0;
2274 
2275 		while (NULL != (row = DBfetch(result)))
2276 		{
2277 			ZBX_STR2UINT64(applicationid, row[0]);
2278 
2279 			if (FAIL != (index = zbx_vector_uint64_bsearch(&del_applicationids, applicationid,
2280 					ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2281 			{
2282 				zbx_vector_uint64_remove(&del_applicationids, index);
2283 			}
2284 		}
2285 
2286 		DBfree_result(result);
2287 	}
2288 
2289 	if (0 == discovery_applicationts.values_num && 0 == del_applicationids.values_num &&
2290 			0 == del_discoveryids.values_num && 0 == ts_discoveryids.values_num &&
2291 			0 == lc_discoveryids.values_num)
2292 	{
2293 		goto clean;
2294 	}
2295 
2296 	/* remove lost applications and update application discovery table */
2297 
2298 	DBbegin();
2299 
2300 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2301 
2302 	for (i = 0; i < discovery_applicationts.values_num; i++)
2303 	{
2304 		zbx_uint64_pair_t	*applicationts = &(discovery_applicationts.values[i]);
2305 
2306 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2307 				"update application_discovery"
2308 				" set ts_delete=%d"
2309 				" where application_discoveryid=" ZBX_FS_UI64 ";\n",
2310 				(int)applicationts->second, applicationts->first);
2311 
2312 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
2313 	}
2314 
2315 	if (0 != del_discoveryids.values_num)
2316 	{
2317 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from application_discovery where");
2318 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
2319 				del_discoveryids.values, del_discoveryids.values_num);
2320 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2321 
2322 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
2323 	}
2324 
2325 	if (0 != ts_discoveryids.values_num)
2326 	{
2327 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update application_discovery"
2328 				" set ts_delete=0 where");
2329 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
2330 				ts_discoveryids.values, ts_discoveryids.values_num);
2331 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2332 
2333 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
2334 	}
2335 
2336 	if (0 != lc_discoveryids.values_num)
2337 	{
2338 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update application_discovery"
2339 				" set lastcheck=%d where", lastcheck);
2340 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_discoveryid",
2341 				lc_discoveryids.values, lc_discoveryids.values_num);
2342 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2343 
2344 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
2345 	}
2346 
2347 	if (0 != del_applicationids.values_num)
2348 	{
2349 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from applications where");
2350 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "applicationid", del_applicationids.values,
2351 				del_applicationids.values_num);
2352 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
2353 	}
2354 
2355 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2356 
2357 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
2358 		DBexecute("%s", sql);
2359 
2360 	DBcommit();
2361 clean:
2362 	zbx_free(sql);
2363 
2364 	zbx_vector_uint64_pair_destroy(&discovery_applicationts);
2365 	zbx_vector_uint64_destroy(&lc_discoveryids);
2366 	zbx_vector_uint64_destroy(&ts_discoveryids);
2367 	zbx_vector_uint64_destroy(&del_discoveryids);
2368 	zbx_vector_uint64_destroy(&del_applicationids);
2369 out:
2370 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2371 }
2372 
lld_item_links_populate(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * lld_rows,zbx_hashset_t * items_index)2373 static void	lld_item_links_populate(const zbx_vector_ptr_t *item_prototypes, const zbx_vector_ptr_t *lld_rows,
2374 		zbx_hashset_t *items_index)
2375 {
2376 	int				i, j;
2377 	zbx_lld_item_prototype_t	*item_prototype;
2378 	zbx_lld_item_index_t		*item_index, item_index_local;
2379 	zbx_lld_item_link_t		*item_link;
2380 
2381 	for (i = 0; i < item_prototypes->values_num; i++)
2382 	{
2383 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
2384 		item_index_local.parent_itemid = item_prototype->itemid;
2385 
2386 		for (j = 0; j < lld_rows->values_num; j++)
2387 		{
2388 			item_index_local.lld_row = (zbx_lld_row_t *)lld_rows->values[j];
2389 
2390 			if (NULL == (item_index = zbx_hashset_search(items_index, &item_index_local)))
2391 				continue;
2392 
2393 			if (0 == (item_index->item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
2394 				continue;
2395 
2396 			item_link = (zbx_lld_item_link_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_link_t));
2397 
2398 			item_link->parent_itemid = item_index->item->parent_itemid;
2399 			item_link->itemid = item_index->item->itemid;
2400 
2401 			zbx_vector_ptr_append(&item_index_local.lld_row->item_links, item_link);
2402 		}
2403 	}
2404 }
2405 
lld_item_links_sort(zbx_vector_ptr_t * lld_rows)2406 void	lld_item_links_sort(zbx_vector_ptr_t *lld_rows)
2407 {
2408 	int	i;
2409 
2410 	for (i = 0; i < lld_rows->values_num; i++)
2411 	{
2412 		zbx_lld_row_t	*lld_row = (zbx_lld_row_t *)lld_rows->values[i];
2413 
2414 		zbx_vector_ptr_sort(&lld_row->item_links, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2415 	}
2416 }
2417 
2418 /******************************************************************************
2419  *                                                                            *
2420  * Function: lld_application_prototypes_get                                   *
2421  *                                                                            *
2422  * Purpose: gets the discovery rule application prototypes from database      *
2423  *                                                                            *
2424  * Parameters: lld_ruleid             - [IN] the discovery rule id            *
2425  *             application_prototypes - [OUT] the applications prototypes     *
2426  *                                            defined for the discovery rule, *
2427  *                                            sorted by prototype id          *
2428  *                                                                            *
2429  ******************************************************************************/
lld_application_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * application_prototypes)2430 static void	lld_application_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *application_prototypes)
2431 {
2432 	const char			*__function_name = "lld_application_prototypes_get";
2433 	DB_RESULT			result;
2434 	DB_ROW				row;
2435 	zbx_lld_application_prototype_t	*application_prototype;
2436 
2437 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2438 
2439 	result = DBselect(
2440 			"select application_prototypeid,name"
2441 			" from application_prototype"
2442 			" where itemid=" ZBX_FS_UI64,
2443 			lld_ruleid);
2444 
2445 	while (NULL != (row = DBfetch(result)))
2446 	{
2447 		application_prototype = (zbx_lld_application_prototype_t *)zbx_malloc(NULL,
2448 				sizeof(zbx_lld_application_prototype_t));
2449 
2450 		ZBX_STR2UINT64(application_prototype->application_prototypeid, row[0]);
2451 		application_prototype->itemid = lld_ruleid;
2452 		application_prototype->name = zbx_strdup(NULL, row[1]);
2453 
2454 		zbx_vector_ptr_append(application_prototypes, application_prototype);
2455 	}
2456 	DBfree_result(result);
2457 
2458 	zbx_vector_ptr_sort(application_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2459 
2460 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __function_name, application_prototypes->values_num);
2461 }
2462 
2463 /******************************************************************************
2464  *                                                                            *
2465  * Function: lld_item_application_prototypes_get                              *
2466  *                                                                            *
2467  * Purpose: gets the discovery rule item-application link prototypes from     *
2468  *          database                                                          *
2469  *                                                                            *
2470  * Parameters: item_prototypes        - [IN/OUT] item prototypes              *
2471  *             application_prototypes - [IN] the application prototypes       *
2472  *                                           defined for the discovery rule   *
2473  *                                                                            *
2474  ******************************************************************************/
lld_item_application_prototypes_get(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * application_prototypes)2475 static void	lld_item_application_prototypes_get(const zbx_vector_ptr_t *item_prototypes,
2476 		const zbx_vector_ptr_t *application_prototypes)
2477 {
2478 	const char			*__function_name = "lld_item_application_prototypes_get";
2479 	DB_RESULT			result;
2480 	DB_ROW				row;
2481 	int				i, index;
2482 	zbx_uint64_t			application_prototypeid, itemid;
2483 	zbx_vector_uint64_t		item_prototypeids;
2484 	char				*sql = NULL;
2485 	size_t				sql_alloc = 0, sql_offset = 0;
2486 	zbx_lld_item_application_ref_t	*item_application_prototype;
2487 	zbx_lld_item_prototype_t	*item_prototype;
2488 
2489 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2490 
2491 	zbx_vector_uint64_create(&item_prototypeids);
2492 
2493 	/* get item prototype links to application prototypes */
2494 
2495 	for (i = 0; i < item_prototypes->values_num; i++)
2496 	{
2497 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[i];
2498 
2499 		zbx_vector_uint64_append(&item_prototypeids, item_prototype->itemid);
2500 	}
2501 
2502 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2503 			"select application_prototypeid,itemid"
2504 			" from item_application_prototype"
2505 			" where");
2506 
2507 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2508 			item_prototypeids.values, item_prototypeids.values_num);
2509 
2510 	result = DBselect("%s", sql);
2511 
2512 	while (NULL != (row = DBfetch(result)))
2513 	{
2514 		ZBX_STR2UINT64(application_prototypeid, row[0]);
2515 
2516 		if (FAIL == (index = zbx_vector_ptr_search(application_prototypes, &application_prototypeid,
2517 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
2518 		{
2519 			THIS_SHOULD_NEVER_HAPPEN;
2520 			continue;
2521 		}
2522 
2523 		item_application_prototype = (zbx_lld_item_application_ref_t *)zbx_malloc(NULL,
2524 				sizeof(zbx_lld_item_application_ref_t));
2525 
2526 		item_application_prototype->application_prototype = application_prototypes->values[index];
2527 		item_application_prototype->applicationid = 0;
2528 
2529 		ZBX_STR2UINT64(itemid, row[1]);
2530 		index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2531 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2532 
2533 		zbx_vector_ptr_append(&item_prototype->applications, item_application_prototype);
2534 	}
2535 	DBfree_result(result);
2536 
2537 	/* get item prototype links to real applications */
2538 
2539 	sql_offset = 0;
2540 	zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2541 			"select applicationid,itemid"
2542 			" from items_applications"
2543 			" where");
2544 
2545 	DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid",
2546 			item_prototypeids.values, item_prototypeids.values_num);
2547 
2548 	result = DBselect("%s", sql);
2549 
2550 	while (NULL != (row = DBfetch(result)))
2551 	{
2552 		item_application_prototype = (zbx_lld_item_application_ref_t *)zbx_malloc(NULL,
2553 				sizeof(zbx_lld_item_application_ref_t));
2554 
2555 		item_application_prototype->application_prototype = NULL;
2556 		ZBX_STR2UINT64(item_application_prototype->applicationid, row[0]);
2557 
2558 		ZBX_STR2UINT64(itemid, row[1]);
2559 		index = zbx_vector_ptr_bsearch(item_prototypes, &itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2560 		item_prototype = (zbx_lld_item_prototype_t *)item_prototypes->values[index];
2561 
2562 		zbx_vector_ptr_append(&item_prototype->applications, item_application_prototype);
2563 	}
2564 	DBfree_result(result);
2565 
2566 	zbx_free(sql);
2567 	zbx_vector_uint64_destroy(&item_prototypeids);
2568 
2569 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2570 }
2571 
2572 /******************************************************************************
2573  *                                                                            *
2574  * Function: lld_applications_get                                             *
2575  *                                                                            *
2576  * Purpose: gets applications previously discovered by the discovery rule     *
2577  *                                                                            *
2578  * Parameters: lld_ruleid   - [IN] the discovery rule id                      *
2579  *             applications - [OUT] the applications                          *
2580  *                                                                            *
2581  ******************************************************************************/
lld_applications_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * applications)2582 static void	lld_applications_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *applications)
2583 {
2584 	const char		*__function_name = "lld_applications_get";
2585 	DB_RESULT		result;
2586 	DB_ROW			row;
2587 	zbx_lld_application_t	*application;
2588 
2589 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2590 
2591 	result = DBselect(
2592 			"select a.applicationid,a.name,ap.application_prototypeid,ad.lastcheck,ad.ts_delete,ad.name,"
2593 				"ad.application_discoveryid"
2594 			" from applications a,application_discovery ad,application_prototype ap"
2595 			" where ap.itemid=" ZBX_FS_UI64
2596 				" and ad.application_prototypeid=ap.application_prototypeid"
2597 				" and a.applicationid=ad.applicationid",
2598 			lld_ruleid);
2599 
2600 	while (NULL != (row = DBfetch(result)))
2601 	{
2602 		application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
2603 
2604 		ZBX_STR2UINT64(application->applicationid, row[0]);
2605 		ZBX_STR2UINT64(application->application_prototypeid, row[2]);
2606 		ZBX_STR2UINT64(application->application_discoveryid, row[6]);
2607 		application->name = zbx_strdup(NULL, row[1]);
2608 		application->lastcheck = atoi(row[3]);
2609 		application->ts_delete = atoi(row[4]);
2610 		application->name_proto = zbx_strdup(NULL, row[5]);
2611 		application->name_orig = NULL;
2612 		application->flags = ZBX_FLAG_LLD_APPLICATION_UNSET;
2613 		application->lld_row = NULL;
2614 
2615 		zbx_vector_ptr_append(applications, application);
2616 	}
2617 	DBfree_result(result);
2618 
2619 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d applications", __function_name, applications->values_num);
2620 }
2621 
2622 /******************************************************************************
2623  *                                                                            *
2624  * Function: lld_application_make                                             *
2625  *                                                                            *
2626  * Purpose: create a new application or mark an existing application as       *
2627  *          discovered based on prototype and lld row                         *
2628  *                                                                            *
2629  * Parameters: application_prototype - [IN] the application prototype         *
2630  *             lld_row               - [IN] the lld row                       *
2631  *             applications          - [IN/OUT] the applications              *
2632  *             applications_index    - [IN/OUT] the application index by      *
2633  *                                              prototype id and lld row      *
2634  *                                                                            *
2635  ******************************************************************************/
lld_application_make(const zbx_lld_application_prototype_t * application_prototype,const zbx_lld_row_t * lld_row,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index)2636 static void	lld_application_make(const zbx_lld_application_prototype_t *application_prototype,
2637 		const zbx_lld_row_t *lld_row, zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index)
2638 {
2639 	zbx_lld_application_t		*application;
2640 	zbx_lld_application_index_t	*application_index, application_index_local;
2641 	struct zbx_json_parse		*jp_row = (struct zbx_json_parse *)&lld_row->jp_row;
2642 	char				*buffer = NULL;
2643 
2644 	application_index_local.application_prototypeid = application_prototype->application_prototypeid;
2645 	application_index_local.lld_row = lld_row;
2646 
2647 	if (NULL == (application_index = zbx_hashset_search(applications_index, &application_index_local)))
2648 	{
2649 		application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
2650 		application->applicationid = 0;
2651 		application->application_prototypeid = application_prototype->application_prototypeid;
2652 		application->application_discoveryid = 0;
2653 		application->ts_delete = 0;
2654 
2655 		application->name = zbx_strdup(NULL, application_prototype->name);
2656 		substitute_discovery_macros(&application->name, jp_row, ZBX_MACRO_ANY, NULL, 0);
2657 		zbx_lrtrim(application->name, ZBX_WHITESPACE);
2658 
2659 		application->name_proto = zbx_strdup(NULL, application_prototype->name);
2660 		application->name_orig = NULL;
2661 		application->flags = ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY;
2662 		application->lld_row = lld_row;
2663 
2664 		zbx_vector_ptr_append(applications, application);
2665 
2666 		application_index_local.application = application;
2667 		zbx_hashset_insert(applications_index, &application_index_local, sizeof(zbx_lld_application_index_t));
2668 	}
2669 	else
2670 	{
2671 		application = application_index->application;
2672 
2673 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
2674 		{
2675 			buffer = zbx_strdup(NULL, application_prototype->name);
2676 			substitute_discovery_macros(&buffer, jp_row, ZBX_MACRO_ANY, NULL, 0);
2677 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
2678 
2679 			if (0 != strcmp(application->name, buffer))
2680 			{
2681 				application->name_orig = application->name;
2682 				application->name = buffer;
2683 				application->flags |= ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME;
2684 			}
2685 			else
2686 				zbx_free(buffer);
2687 		}
2688 	}
2689 
2690 	application->flags |= ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
2691 }
2692 
2693 /******************************************************************************
2694  *                                                                            *
2695  * Function: lld_applications_make                                            *
2696  *                                                                            *
2697  * Purpose: makes new applications and marks old applications as discovered   *
2698  *          based on application prototypes and lld rows                      *
2699  *                                                                            *
2700  * Parameters: application_prototypes - [IN] the application prototypes       *
2701  *             lld_rows               - [IN] the lld rows                     *
2702  *             applications           - [IN/OUT] the applications             *
2703  *             applications_index     - [OUT] the application index by        *
2704  *                                            prototype id and lld row        *
2705  *                                                                            *
2706  ******************************************************************************/
lld_applications_make(const zbx_vector_ptr_t * application_prototypes,const zbx_vector_ptr_t * lld_rows,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index)2707 static void	lld_applications_make(const zbx_vector_ptr_t *application_prototypes,
2708 		const zbx_vector_ptr_t *lld_rows, zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index)
2709 {
2710 	const char			*__function_name = "lld_applications_make";
2711 	int				i, j;
2712 	zbx_lld_application_t		*application;
2713 	zbx_lld_row_t			*lld_row;
2714 	zbx_lld_application_index_t	application_index_local;
2715 	char				*buffer = NULL;
2716 
2717 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2718 
2719 	/* index existing applications */
2720 
2721 	for (i = 0; i < applications->values_num; i++)
2722 	{
2723 		application = (zbx_lld_application_t *)applications->values[i];
2724 
2725 		for (j = 0; j < lld_rows->values_num; j++)
2726 		{
2727 			lld_row = (zbx_lld_row_t *)lld_rows->values[j];
2728 
2729 			buffer = zbx_strdup(buffer, application->name_proto);
2730 			substitute_discovery_macros(&buffer, &lld_row->jp_row, ZBX_MACRO_ANY, NULL, 0);
2731 			zbx_lrtrim(buffer, ZBX_WHITESPACE);
2732 
2733 			if (0 == strcmp(application->name, buffer))
2734 			{
2735 				application_index_local.application_prototypeid = application->application_prototypeid;
2736 				application_index_local.lld_row = lld_row;
2737 				application_index_local.application = application;
2738 				zbx_hashset_insert(applications_index, &application_index_local,
2739 						sizeof(application_index_local));
2740 
2741 				application->lld_row = lld_row;
2742 			}
2743 		}
2744 	}
2745 
2746 	zbx_free(buffer);
2747 
2748 	/* make the applications */
2749 	for (i = 0; i < application_prototypes->values_num; i++)
2750 	{
2751 		for (j = 0; j < lld_rows->values_num; j++)
2752 		{
2753 			lld_application_make(application_prototypes->values[i], lld_rows->values[j], applications,
2754 					applications_index);
2755 		}
2756 	}
2757 
2758 	zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
2759 
2760 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d applications", __function_name, applications->values_num);
2761 }
2762 
2763 /******************************************************************************
2764  *                                                                            *
2765  * Function: lld_applications_validate                                        *
2766  *                                                                            *
2767  * Purpose: validates the discovered and renamed applications                 *
2768  *                                                                            *
2769  * Parameters: hostid             - [IN] host id                              *
2770  *             lld_ruleid         - [IN] the discovery rule id                *
2771  *             applications       - [IN/OUT] the applications                 *
2772  *             applications_index - [OUT] the application index by            *
2773  *                                        prototype id and lld row            *
2774  *             error              - [IN/OUT] the lld error message            *
2775  *                                                                            *
2776  ******************************************************************************/
lld_applications_validate(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index,char ** error)2777 static void	lld_applications_validate(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *applications,
2778 		zbx_hashset_t *applications_index, char **error)
2779 {
2780 	const char			*__function_name = "lld_applications_validate";
2781 	int				i, j, index;
2782 	DB_RESULT			result;
2783 	DB_ROW				row;
2784 	zbx_lld_application_t		*application, *new_application, application_local;
2785 	char				*sql = NULL;
2786 	size_t				sql_alloc = 0, sql_offset = 0;
2787 	zbx_vector_str_t		names_new, names_old;
2788 	zbx_lld_application_index_t	*application_index, application_index_local;
2789 
2790 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2791 
2792 	if (0 == applications->values_num)
2793 		goto out;
2794 
2795 	zbx_vector_str_create(&names_new);
2796 	zbx_vector_str_create(&names_old);
2797 
2798 	/* check for conflicting application names in the discovered applications */
2799 
2800 	for (i = 0; i < applications->values_num; i++)
2801 	{
2802 		application = (zbx_lld_application_t *)applications->values[i];
2803 
2804 		if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
2805 			continue;
2806 
2807 		if (0 != application->applicationid && 0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
2808 			continue;
2809 
2810 		/* iterate in reverse order so existing applications would have more priority */
2811 		/* than new applications which have 0 applicationid and therefore are located */
2812 		/* at the beginning of applications vector which is sorted by applicationid   */
2813 		for (j = applications->values_num - 1; j > i; j--)
2814 		{
2815 			zbx_lld_application_t	*application_compare = (zbx_lld_application_t *)applications->values[j];
2816 
2817 			if (0 != strcmp(application->name, application_compare->name))
2818 				continue;
2819 
2820 			/* Applications with matching names are validated depending on their prototypes. */
2821 			/* If they are discovered by different prototypes we must fail with appropriate  */
2822 			/* lld error.                                                                    */
2823 			/* Otherwise we 'merge' application by updating index of the validated           */
2824 			/* validated application to point at the application with the same name.         */
2825 			/* In both cases the validated application is flagged as non-discovered.         */
2826 			application->flags &= ~ZBX_FLAG_LLD_ITEM_DISCOVERED;
2827 
2828 			/* fail if application has different prototype */
2829 			if (application->application_prototypeid != application_compare->application_prototypeid)
2830 			{
2831 				*error = zbx_strdcatf(*error, "Cannot %s application:"
2832 						" application with the same name \"%s\" already exists.\n",
2833 						(0 != application->applicationid ? "update" : "create"),
2834 						application->name);
2835 
2836 				break;
2837 			}
2838 
2839 			/* update application index to use the matching application */
2840 
2841 			application_index_local.application_prototypeid = application->application_prototypeid;
2842 			application_index_local.lld_row = application->lld_row;
2843 
2844 			if (NULL == (application_index = zbx_hashset_search(applications_index,
2845 					&application_index_local)))
2846 			{
2847 				THIS_SHOULD_NEVER_HAPPEN;
2848 				break;
2849 			}
2850 
2851 			application_index->application = application_compare;
2852 			break;
2853 		}
2854 
2855 		/* Prepare name lists to resolve naming conflicts with applications */
2856 		/* discovered by other discovery rules:                             */
2857 		/*   names_new - to check if discovered/renamed application names   */
2858 		/*               don't match existing applications discovered by    */
2859 		/*               other discovery rules                              */
2860 		/*   names_old - to check if renamed applications were also         */
2861 		/*               discovered by other discovery rules                */
2862 		if (i == j)
2863 		{
2864 			zbx_vector_str_append(&names_new, application->name);
2865 
2866 			if (NULL != application->name_orig)
2867 				zbx_vector_str_append(&names_old, application->name_orig);
2868 		}
2869 	}
2870 
2871 	/* validate new/renamed application names against applications discovered */
2872 	/* by other discovery rules                                               */
2873 
2874 	if (0 != names_new.values_num)
2875 	{
2876 		zbx_vector_str_sort(&names_new, ZBX_DEFAULT_STR_COMPARE_FUNC);
2877 
2878 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2879 				"select applicationid,name,flags"
2880 				" from applications"
2881 				" where hostid=" ZBX_FS_UI64
2882 					" and",
2883 				hostid);
2884 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "name",
2885 				(const char **)names_new.values, names_new.values_num);
2886 
2887 		result = DBselect("%s", sql);
2888 
2889 		application_local.flags = ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
2890 
2891 		while (NULL != (row = DBfetch(result)))
2892 		{
2893 			application_local.name = row[1];
2894 
2895 			if (FAIL == (index = zbx_vector_ptr_search(applications, &application_local,
2896 					lld_application_compare_name)))
2897 			{
2898 				THIS_SHOULD_NEVER_HAPPEN;
2899 				continue;
2900 			}
2901 
2902 			application = applications->values[index];
2903 
2904 			/* only discovered applications can be 'shared' between discovery rules */
2905 			if (ZBX_FLAG_DISCOVERY_CREATED != atoi(row[2]))
2906 			{
2907 				/* conflicting application name, reset discovery flags */
2908 				application->flags = ZBX_FLAG_LLD_APPLICATION_UNSET;
2909 
2910 				*error = zbx_strdcatf(*error, "Cannot create application:"
2911 						" non-discovered application"
2912 						" with the same name \"%s\" already exists.\n",
2913 						application->name);
2914 
2915 				continue;
2916 			}
2917 
2918 			if (0 != (application->flags & ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME))
2919 			{
2920 				/* During discovery process the application was renamed to an */
2921 				/* application already discovered by another discovery rule.  */
2922 				/* In this case we must delete the old application and relink */
2923 				/* its items to the application we have found.                */
2924 
2925 				/* create a pseudo application to remove the renamed application */
2926 
2927 				new_application = (zbx_lld_application_t *)zbx_malloc(NULL,
2928 						sizeof(zbx_lld_application_t));
2929 
2930 				memset(new_application, 0, sizeof(zbx_lld_application_t));
2931 				new_application->applicationid = application->applicationid;
2932 				new_application->flags = ZBX_FLAG_LLD_APPLICATION_REMOVE;
2933 
2934 				zbx_vector_ptr_append(applications, new_application);
2935 
2936 				/* update application flags so that instead of renaming it a new */
2937 				/* discovery record is created                                   */
2938 
2939 				application->application_discoveryid = 0;
2940 				application->flags &= ~ZBX_FLAG_LLD_APPLICATION_UPDATE_NAME;
2941 				application->flags |= ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY;
2942 			}
2943 
2944 			/* reuse application created by another discovery rule */
2945 			ZBX_STR2UINT64(application->applicationid, row[0]);
2946 		}
2947 		DBfree_result(result);
2948 	}
2949 
2950 	/* if an application shared with other discovery rule has been renamed we must */
2951 	/* create a new application with the new name instead of renaming the old one  */
2952 
2953 	if (0 != names_old.values_num)
2954 	{
2955 		sql_offset = 0;
2956 
2957 		zbx_vector_str_sort(&names_old, ZBX_DEFAULT_STR_COMPARE_FUNC);
2958 
2959 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2960 				"select a.name"
2961 				" from applications a,application_discovery ad,application_prototype ap"
2962 				" where a.applicationid=ad.applicationid"
2963 					" and ad.application_prototypeid=ap.application_prototypeid"
2964 					" and a.hostid=" ZBX_FS_UI64
2965 					" and ap.itemid<>" ZBX_FS_UI64
2966 					" and",
2967 				hostid, lld_ruleid);
2968 		DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "a.name",
2969 				(const char **)names_old.values, names_old.values_num);
2970 
2971 		result = DBselect("%s", sql);
2972 
2973 		application_local.flags = ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
2974 
2975 		while (NULL != (row = DBfetch(result)))
2976 		{
2977 			application_local.name_orig = row[0];
2978 
2979 			if (FAIL == (index = zbx_vector_ptr_search(applications, &application_local,
2980 					lld_application_compare_name_orig)))
2981 			{
2982 				THIS_SHOULD_NEVER_HAPPEN;
2983 				continue;
2984 			}
2985 
2986 			application = applications->values[index];
2987 
2988 			/* add a pseudo application to remove the application discovery record */
2989 			/* of the shared application and current discovery rule                */
2990 			new_application = (zbx_lld_application_t *)zbx_malloc(NULL, sizeof(zbx_lld_application_t));
2991 			memset(new_application, 0, sizeof(zbx_lld_application_t));
2992 			new_application->applicationid = application->applicationid;
2993 			new_application->application_prototypeid = application->application_prototypeid;
2994 			new_application->application_discoveryid = application->application_discoveryid;
2995 			new_application->flags = ZBX_FLAG_LLD_APPLICATION_REMOVE_DISCOVERY;
2996 			zbx_vector_ptr_append(applications, new_application);
2997 
2998 			/* reset applicationid, application_discoveryid and flags             */
2999 			/* so a new application is created instead of renaming the shared one */
3000 			application->applicationid = 0;
3001 			application->application_discoveryid = 0;
3002 			application->flags = ZBX_FLAG_LLD_APPLICATION_ADD_DISCOVERY |
3003 					ZBX_FLAG_LLD_APPLICATION_DISCOVERED;
3004 		}
3005 		DBfree_result(result);
3006 	}
3007 
3008 	zbx_vector_str_destroy(&names_old);
3009 	zbx_vector_str_destroy(&names_new);
3010 
3011 	zbx_free(sql);
3012 
3013 	zbx_vector_ptr_sort(applications, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3014 out:
3015 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3016 }
3017 
3018 /******************************************************************************
3019  *                                                                            *
3020  * Function: lld_items_applications_get                                       *
3021  *                                                                            *
3022  * Purpose: gets item-application links for the lld rule                      *
3023  *                                                                            *
3024  * Parameters: lld_rule           - [IN] the lld rule                         *
3025  *             items_applications - [OUT] the item-application links          *
3026  *                                                                            *
3027  ******************************************************************************/
lld_items_applications_get(zbx_uint64_t lld_ruleid,zbx_hashset_t * items_applications)3028 static void	lld_items_applications_get(zbx_uint64_t lld_ruleid, zbx_hashset_t *items_applications)
3029 {
3030 	const char			*__function_name = "lld_items_applications_get";
3031 	DB_RESULT			result;
3032 	DB_ROW				row;
3033 	zbx_lld_item_application_t	item_application;
3034 
3035 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3036 
3037 	result = DBselect(
3038 			"select ia.itemappid,ia.itemid,ia.applicationid"
3039 			" from items_applications ia,item_discovery id1,item_discovery id2"
3040 			" where id1.itemid=ia.itemid"
3041 				" and id1.parent_itemid=id2.itemid"
3042 				" and id2.parent_itemid=" ZBX_FS_UI64,
3043 			lld_ruleid);
3044 
3045 	item_application.application_ref.application = NULL;
3046 	item_application.item_ref.item = NULL;
3047 
3048 	while (NULL != (row = DBfetch(result)))
3049 	{
3050 		ZBX_STR2UINT64(item_application.itemappid, row[0]);
3051 		ZBX_STR2UINT64(item_application.item_ref.itemid, row[1]);
3052 		ZBX_STR2UINT64(item_application.application_ref.applicationid, row[2]);
3053 		item_application.flags = ZBX_FLAG_LLD_ITEM_APPLICATION_UNSET;
3054 
3055 		zbx_hashset_insert(items_applications, &item_application, sizeof(zbx_lld_item_application_t));
3056 	}
3057 	DBfree_result(result);
3058 
3059 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d links", __function_name, items_applications->num_data);
3060 }
3061 
3062 /******************************************************************************
3063  *                                                                            *
3064  * Function: lld_items_applications_make                                      *
3065  *                                                                            *
3066  * Purpose: makes new item-application links and marks existing links as      *
3067  *          discovered based on item_prototypes applications links            *
3068  *                                                                            *
3069  * Parameters: item_prototypes    - [IN] the item prototypes                  *
3070  *             items              - [IN] the items                            *
3071  *             applications       - [IN] the applications                     *
3072  *             applications_index - [IN] the application index by             *
3073  *                                       prototype id and lld row             *
3074  *             items_applications - [IN/OUT] the item-application links       *
3075  *                                                                            *
3076  ******************************************************************************/
lld_items_applications_make(const zbx_vector_ptr_t * item_prototypes,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * applications,zbx_hashset_t * applications_index,zbx_hashset_t * items_applications)3077 static void	lld_items_applications_make(const zbx_vector_ptr_t *item_prototypes, const zbx_vector_ptr_t *items,
3078 		const zbx_vector_ptr_t *applications, zbx_hashset_t *applications_index,
3079 		zbx_hashset_t *items_applications)
3080 {
3081 	const char			*__function_name = "lld_items_applications_make";
3082 	int				i, j, index;
3083 	zbx_lld_item_application_t	*item_application, item_application_local;
3084 	zbx_lld_application_t		*application;
3085 	zbx_lld_item_prototype_t	*item_prototype;
3086 	zbx_lld_item_t			*item;
3087 	zbx_lld_item_application_ref_t	*itemapp_prototype;
3088 	zbx_lld_application_index_t	*application_index, application_index_local;
3089 
3090 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3091 
3092 	item_application_local.itemappid = 0;
3093 	item_application_local.flags = ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED;
3094 
3095 	for (i = 0; i < items->values_num; i++)
3096 	{
3097 		item = items->values[i];
3098 
3099 		if (0 == (item->flags & ZBX_FLAG_LLD_ITEM_DISCOVERED))
3100 			continue;
3101 
3102 		/* if item is discovered its prototype must be in item_prototypes vector */
3103 		index = zbx_vector_ptr_bsearch(item_prototypes, &item->parent_itemid,
3104 				ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3105 		item_prototype = item_prototypes->values[index];
3106 
3107 		application_index_local.lld_row = item->lld_row;
3108 
3109 		if (0 == (item_application_local.item_ref.itemid = item->itemid))
3110 			item_application_local.item_ref.item = item;
3111 		else
3112 			item_application_local.item_ref.item = NULL;
3113 
3114 		for (j = 0; j < item_prototype->applications.values_num; j++)
3115 		{
3116 			itemapp_prototype = item_prototype->applications.values[j];
3117 
3118 			if (NULL != itemapp_prototype->application_prototype)
3119 			{
3120 				application_index_local.application_prototypeid =
3121 						itemapp_prototype->application_prototype->application_prototypeid;
3122 
3123 				if (NULL == (application_index = zbx_hashset_search(applications_index,
3124 						&application_index_local)))
3125 				{
3126 					continue;
3127 				}
3128 
3129 				application = application_index->application;
3130 
3131 				if (0 == (application->flags & ZBX_FLAG_LLD_APPLICATION_DISCOVERED))
3132 					continue;
3133 
3134 				if (0 == (item_application_local.application_ref.applicationid =
3135 						application->applicationid))
3136 				{
3137 					item_application_local.application_ref.application = application;
3138 				}
3139 				else
3140 					item_application_local.application_ref.application = NULL;
3141 			}
3142 			else
3143 			{
3144 				item_application_local.application_ref.application = NULL;
3145 				item_application_local.application_ref.applicationid = itemapp_prototype->applicationid;
3146 			}
3147 
3148 			if (NULL == (item_application = zbx_hashset_search(items_applications,
3149 					&item_application_local)))
3150 			{
3151 				item_application = zbx_hashset_insert(items_applications, &item_application_local,
3152 						sizeof(zbx_lld_item_application_t));
3153 			}
3154 
3155 			item_application->flags = ZBX_FLAG_LLD_ITEM_APPLICATION_DISCOVERED;
3156 		}
3157 	}
3158 
3159 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d links", __function_name, items_applications->num_data);
3160 }
3161 
3162 /******************************************************************************
3163  *                                                                            *
3164  * Function: lld_item_prototypes_get                                          *
3165  *                                                                            *
3166  * Purpose: load discovery rule item prototypes                               *
3167  *                                                                            *
3168  * Parameters: lld_ruleid      - [IN] the discovery rule id                   *
3169  *             item_prototypes - [OUT] the item prototypes                    *
3170  *                                                                            *
3171  ******************************************************************************/
lld_item_prototypes_get(zbx_uint64_t lld_ruleid,zbx_vector_ptr_t * item_prototypes)3172 static void	lld_item_prototypes_get(zbx_uint64_t lld_ruleid, zbx_vector_ptr_t *item_prototypes)
3173 {
3174 	const char			*__function_name = "lld_item_prototypes_get";
3175 	DB_RESULT			result;
3176 	DB_ROW				row;
3177 	zbx_lld_item_prototype_t	*item_prototype;
3178 
3179 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3180 
3181 	result = DBselect(
3182 			"select i.itemid,i.name,i.key_,i.type,i.value_type,i.data_type,i.delay,i.delay_flex,"
3183 				"i.history,i.trends,i.status,i.trapper_hosts,i.units,i.multiplier,i.delta,i.formula,"
3184 				"i.logtimefmt,i.valuemapid,i.params,i.ipmi_sensor,i.snmp_community,i.snmp_oid,"
3185 				"i.port,i.snmpv3_securityname,i.snmpv3_securitylevel,i.snmpv3_authprotocol,"
3186 				"i.snmpv3_authpassphrase,i.snmpv3_privprotocol,i.snmpv3_privpassphrase,i.authtype,"
3187 				"i.username,i.password,i.publickey,i.privatekey,i.description,i.interfaceid,"
3188 				"i.snmpv3_contextname"
3189 			" from items i,item_discovery id"
3190 			" where i.itemid=id.itemid"
3191 				" and id.parent_itemid=" ZBX_FS_UI64,
3192 			lld_ruleid);
3193 
3194 	while (NULL != (row = DBfetch(result)))
3195 	{
3196 		item_prototype = (zbx_lld_item_prototype_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_prototype_t));
3197 
3198 		ZBX_STR2UINT64(item_prototype->itemid, row[0]);
3199 		item_prototype->name = zbx_strdup(NULL, row[1]);
3200 		item_prototype->key = zbx_strdup(NULL, row[2]);
3201 		ZBX_STR2UCHAR(item_prototype->type, row[3]);
3202 		ZBX_STR2UCHAR(item_prototype->value_type, row[4]);
3203 		ZBX_STR2UCHAR(item_prototype->data_type, row[5]);
3204 		item_prototype->delay = atoi(row[6]);
3205 		item_prototype->delay_flex = zbx_strdup(NULL, row[7]);
3206 		item_prototype->history = atoi(row[8]);
3207 		item_prototype->trends = atoi(row[9]);
3208 		ZBX_STR2UCHAR(item_prototype->status, row[10]);
3209 		item_prototype->trapper_hosts = zbx_strdup(NULL, row[11]);
3210 		item_prototype->units = zbx_strdup(NULL, row[12]);
3211 		ZBX_STR2UCHAR(item_prototype->multiplier, row[13]);
3212 		ZBX_STR2UCHAR(item_prototype->delta, row[14]);
3213 		item_prototype->formula = zbx_strdup(NULL, row[15]);
3214 		item_prototype->logtimefmt = zbx_strdup(NULL, row[16]);
3215 		ZBX_DBROW2UINT64(item_prototype->valuemapid, row[17]);
3216 		item_prototype->params = zbx_strdup(NULL, row[18]);
3217 		item_prototype->ipmi_sensor = zbx_strdup(NULL, row[19]);
3218 		item_prototype->snmp_community = zbx_strdup(NULL, row[20]);
3219 		item_prototype->snmp_oid = zbx_strdup(NULL, row[21]);
3220 		item_prototype->port = zbx_strdup(NULL, row[22]);
3221 		item_prototype->snmpv3_securityname = zbx_strdup(NULL, row[23]);
3222 		ZBX_STR2UCHAR(item_prototype->snmpv3_securitylevel, row[24]);
3223 		ZBX_STR2UCHAR(item_prototype->snmpv3_authprotocol, row[25]);
3224 		item_prototype->snmpv3_authpassphrase = zbx_strdup(NULL, row[26]);
3225 		ZBX_STR2UCHAR(item_prototype->snmpv3_privprotocol, row[27]);
3226 		item_prototype->snmpv3_privpassphrase = zbx_strdup(NULL, row[28]);
3227 		ZBX_STR2UCHAR(item_prototype->authtype, row[29]);
3228 		item_prototype->username = zbx_strdup(NULL, row[30]);
3229 		item_prototype->password = zbx_strdup(NULL, row[31]);
3230 		item_prototype->publickey = zbx_strdup(NULL, row[32]);
3231 		item_prototype->privatekey = zbx_strdup(NULL, row[33]);
3232 		item_prototype->description = zbx_strdup(NULL, row[34]);
3233 		ZBX_DBROW2UINT64(item_prototype->interfaceid, row[35]);
3234 		item_prototype->snmpv3_contextname = zbx_strdup(NULL, row[36]);
3235 
3236 		zbx_vector_ptr_create(&item_prototype->lld_rows);
3237 		zbx_vector_ptr_create(&item_prototype->applications);
3238 
3239 		zbx_vector_ptr_append(item_prototypes, item_prototype);
3240 	}
3241 	DBfree_result(result);
3242 
3243 	zbx_vector_ptr_sort(item_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3244 
3245 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%d prototypes", __function_name, item_prototypes->values_num);
3246 }
3247 
3248 /******************************************************************************
3249  *                                                                            *
3250  * Function: lld_update_items                                                 *
3251  *                                                                            *
3252  * Purpose: add or update discovered items                                    *
3253  *                                                                            *
3254  * Return value: SUCCEED - if items were successfully added/updated or        *
3255  *                         adding/updating was not necessary                  *
3256  *               FAIL    - items cannot be added/updated                      *
3257  *                                                                            *
3258  ******************************************************************************/
lld_update_items(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,char ** error,unsigned short lifetime,int lastcheck)3259 int	lld_update_items(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows, char **error,
3260 		unsigned short lifetime, int lastcheck)
3261 {
3262 	const char		*__function_name = "lld_update_items";
3263 
3264 	zbx_vector_ptr_t	applications, application_prototypes, items, item_prototypes;
3265 	zbx_hashset_t		applications_index, items_index, items_applications;
3266 	int			ret = SUCCEED, host_record_is_locked = 0;
3267 
3268 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3269 
3270 	zbx_vector_ptr_create(&item_prototypes);
3271 
3272 	lld_item_prototypes_get(lld_ruleid, &item_prototypes);
3273 
3274 	if (0 == item_prototypes.values_num)
3275 		goto out;
3276 
3277 	zbx_vector_ptr_create(&application_prototypes);
3278 
3279 	lld_application_prototypes_get(lld_ruleid, &application_prototypes);
3280 
3281 	zbx_vector_ptr_create(&applications);
3282 	zbx_hashset_create(&applications_index, application_prototypes.values_num * lld_rows->values_num,
3283 			lld_application_index_hash_func, lld_application_index_compare_func);
3284 
3285 	zbx_vector_ptr_create(&items);
3286 	zbx_hashset_create(&items_index, item_prototypes.values_num * lld_rows->values_num, lld_item_index_hash_func,
3287 			lld_item_index_compare_func);
3288 
3289 	zbx_hashset_create(&items_applications, 100, lld_item_application_hash_func, lld_item_application_compare_func);
3290 
3291 	lld_applications_get(lld_ruleid, &applications);
3292 	lld_applications_make(&application_prototypes, lld_rows, &applications, &applications_index);
3293 	lld_applications_validate(hostid, lld_ruleid, &applications, &applications_index, error);
3294 
3295 	lld_item_application_prototypes_get(&item_prototypes, &application_prototypes);
3296 
3297 	lld_items_get(&item_prototypes, &items);
3298 	lld_items_make(&item_prototypes, lld_rows, &items, &items_index, error);
3299 	lld_items_validate(hostid, &items, error);
3300 
3301 	lld_items_applications_get(lld_ruleid, &items_applications);
3302 	lld_items_applications_make(&item_prototypes, &items, &applications, &applications_index, &items_applications);
3303 
3304 	DBbegin();
3305 
3306 	if (SUCCEED == lld_items_save(hostid, &item_prototypes, &items, &host_record_is_locked) &&
3307 			SUCCEED == lld_applications_save(hostid, &applications, &application_prototypes,
3308 					&host_record_is_locked))
3309 	{
3310 		lld_items_applications_save(&items_applications, &items, &applications);
3311 		DBcommit();
3312 	}
3313 	else
3314 	{
3315 		ret = FAIL;
3316 		DBrollback();
3317 		goto clean;
3318 	}
3319 
3320 	lld_item_links_populate(&item_prototypes, lld_rows, &items_index);
3321 	lld_remove_lost_items(&items, lifetime, lastcheck);
3322 	lld_remove_lost_applications(lld_ruleid, &applications, lifetime, lastcheck);
3323 clean:
3324 	zbx_hashset_destroy(&items_applications);
3325 	zbx_hashset_destroy(&items_index);
3326 
3327 	zbx_vector_ptr_clear_ext(&items, (zbx_clean_func_t)lld_item_free);
3328 	zbx_vector_ptr_destroy(&items);
3329 
3330 	zbx_hashset_destroy(&applications_index);
3331 
3332 	zbx_vector_ptr_clear_ext(&applications, (zbx_clean_func_t)lld_application_free);
3333 	zbx_vector_ptr_destroy(&applications);
3334 
3335 	zbx_vector_ptr_clear_ext(&application_prototypes, (zbx_clean_func_t)lld_application_prototype_free);
3336 	zbx_vector_ptr_destroy(&application_prototypes);
3337 
3338 	zbx_vector_ptr_clear_ext(&item_prototypes, (zbx_clean_func_t)lld_item_prototype_free);
3339 out:
3340 	zbx_vector_ptr_destroy(&item_prototypes);
3341 
3342 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3343 
3344 	return ret;
3345 }
3346