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 "common.h"
21
22 #include "db.h"
23 #include "log.h"
24 #include "dbcache.h"
25 #include "zbxserver.h"
26 #include "template.h"
27
get_template_names(const zbx_vector_uint64_t * templateids)28 static char *get_template_names(const zbx_vector_uint64_t *templateids)
29 {
30 DB_RESULT result;
31 DB_ROW row;
32 char *sql = NULL, *template_names = NULL;
33 size_t sql_alloc = 256, sql_offset=0, tmp_alloc = 64, tmp_offset = 0;
34
35 sql = (char *)zbx_malloc(sql, sql_alloc);
36 template_names = (char *)zbx_malloc(template_names, tmp_alloc);
37
38 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
39 "select host"
40 " from hosts"
41 " where");
42
43 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
44 templateids->values, templateids->values_num);
45
46 result = DBselect("%s", sql);
47
48 while (NULL != (row = DBfetch(result)))
49 zbx_snprintf_alloc(&template_names, &tmp_alloc, &tmp_offset, "\"%s\", ", row[0]);
50
51 template_names[tmp_offset - 2] = '\0';
52
53 DBfree_result(result);
54 zbx_free(sql);
55
56 return template_names;
57 }
58
59 /******************************************************************************
60 * *
61 * Function: DBget_screenitems_by_resource_types_ids *
62 * *
63 * Description: gets a vector of screen item identifiers used with the *
64 * specified resource types and identifiers *
65 * *
66 * Parameters: screen_itemids - [OUT] the screen item identifiers *
67 * types - [IN] an array of resource types *
68 * types_num - [IN] the number of values in types array *
69 * resourceids - [IN] the resource identifiers *
70 * *
71 ******************************************************************************/
DBget_screenitems_by_resource_types_ids(zbx_vector_uint64_t * screen_itemids,const zbx_uint64_t * types,int types_num,const zbx_vector_uint64_t * resourceids)72 static void DBget_screenitems_by_resource_types_ids(zbx_vector_uint64_t *screen_itemids, const zbx_uint64_t *types,
73 int types_num, const zbx_vector_uint64_t *resourceids)
74 {
75 char *sql = NULL;
76 size_t sql_alloc = 0, sql_offset = 0;
77
78 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct screenitemid from screens_items where");
79 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "resourcetype", types, types_num);
80 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
81 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "resourceid", resourceids->values,
82 resourceids->values_num);
83
84 DBselect_uint64(sql, screen_itemids);
85
86 zbx_free(sql);
87
88 zbx_vector_uint64_sort(screen_itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
89 }
90
91 /******************************************************************************
92 * *
93 * Function: DBget_profiles_by_source_idxs_values *
94 * *
95 * Description: gets a vector of profile identifiers used with the specified *
96 * source, indexes and value identifiers *
97 * *
98 * Parameters: profileids - [OUT] the screen item identifiers *
99 * source - [IN] the source *
100 * idxs - [IN] an array of index values *
101 * idxs_num - [IN] the number of values in idxs array *
102 * value_ids - [IN] the resource identifiers *
103 * *
104 ******************************************************************************/
DBget_profiles_by_source_idxs_values(zbx_vector_uint64_t * profileids,const char * source,const char ** idxs,int idxs_num,zbx_vector_uint64_t * value_ids)105 static void DBget_profiles_by_source_idxs_values(zbx_vector_uint64_t *profileids, const char *source,
106 const char **idxs, int idxs_num, zbx_vector_uint64_t *value_ids)
107 {
108 char *sql = NULL;
109 size_t sql_alloc = 0, sql_offset = 0;
110
111 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct profileid from profiles where");
112
113 if (NULL != source)
114 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " source='%s' and", source);
115
116 if (0 != idxs_num)
117 {
118 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "idx", idxs, idxs_num);
119 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
120 }
121
122 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "value_id", value_ids->values, value_ids->values_num);
123
124 DBselect_uint64(sql, profileids);
125
126 zbx_free(sql);
127
128 zbx_vector_uint64_sort(profileids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
129 }
130
131 /******************************************************************************
132 * *
133 * Function: DBget_sysmapelements_by_element_type_ids *
134 * *
135 * Description: gets a vector of sysmap element identifiers used with the *
136 * specified element type and identifiers *
137 * *
138 * Parameters: selementids - [OUT] the sysmap element identifiers *
139 * elementtype - [IN] the element type *
140 * elementids - [IN] the element identifiers *
141 * *
142 ******************************************************************************/
DBget_sysmapelements_by_element_type_ids(zbx_vector_uint64_t * selementids,int elementtype,zbx_vector_uint64_t * elementids)143 static void DBget_sysmapelements_by_element_type_ids(zbx_vector_uint64_t *selementids, int elementtype,
144 zbx_vector_uint64_t *elementids)
145 {
146 char *sql = NULL;
147 size_t sql_alloc = 0, sql_offset = 0;
148
149 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
150 "select distinct selementid"
151 " from sysmaps_elements"
152 " where elementtype=%d"
153 " and",
154 elementtype);
155
156 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "elementid", elementids->values, elementids->values_num);
157 DBselect_uint64(sql, selementids);
158
159 zbx_free(sql);
160
161 zbx_vector_uint64_sort(selementids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
162 }
163
164 /******************************************************************************
165 * *
166 * Function: validate_linked_templates *
167 * *
168 * Description: Check collisions between linked templates *
169 * *
170 * Parameters: templateids - [IN] array of template IDs *
171 * *
172 * Return value: SUCCEED if no collisions found *
173 * *
174 * Author: Alexander Vladishev *
175 * *
176 * Comments: !!! Don't forget to sync the code with PHP !!! *
177 * *
178 ******************************************************************************/
validate_linked_templates(const zbx_vector_uint64_t * templateids,char * error,size_t max_error_len)179 static int validate_linked_templates(const zbx_vector_uint64_t *templateids, char *error, size_t max_error_len)
180 {
181 const char *__function_name = "validate_linked_templates";
182
183 DB_RESULT result;
184 DB_ROW row;
185 char *sql = NULL;
186 size_t sql_alloc = 256, sql_offset;
187 int ret = SUCCEED;
188
189 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
190
191 if (0 == templateids->values_num)
192 goto out;
193
194 sql = (char *)zbx_malloc(sql, sql_alloc);
195
196 /* items */
197 if (SUCCEED == ret && 1 < templateids->values_num)
198 {
199 sql_offset = 0;
200 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
201 "select key_,count(*)"
202 " from items"
203 " where");
204 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
205 templateids->values, templateids->values_num);
206 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
207 " group by key_"
208 " having count(*)>1");
209
210 result = DBselectN(sql, 1);
211
212 if (NULL != (row = DBfetch(result)))
213 {
214 ret = FAIL;
215 zbx_snprintf(error, max_error_len, "conflicting item key \"%s\" found", row[0]);
216 }
217 DBfree_result(result);
218 }
219
220 /* trigger expressions */
221 if (SUCCEED == ret)
222 {
223 sql_offset = 0;
224 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
225 "select t1.description,h2.host"
226 " from items i1,functions f1,triggers t1,functions f2,items i2,hosts h2"
227 " where i1.itemid=f1.itemid"
228 " and f1.triggerid=t1.triggerid"
229 " and t1.triggerid=f2.triggerid"
230 " and f2.itemid=i2.itemid"
231 " and i2.hostid=h2.hostid"
232 " and h2.status=%d"
233 " and",
234 HOST_STATUS_TEMPLATE);
235 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i1.hostid",
236 templateids->values, templateids->values_num);
237 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
238 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i2.hostid",
239 templateids->values, templateids->values_num);
240
241 result = DBselectN(sql, 1);
242
243 if (NULL != (row = DBfetch(result)))
244 {
245 ret = FAIL;
246 zbx_snprintf(error, max_error_len,
247 "trigger \"%s\" has items from template \"%s\"",
248 row[0], row[1]);
249 }
250 DBfree_result(result);
251 }
252
253 /* trigger dependencies */
254 if (SUCCEED == ret)
255 {
256 sql_offset = 0;
257 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
258 /* don't remove "description2 and host2" aliases, the ORACLE needs them */
259 "select t1.description,h1.host,t2.description as description2,h2.host as host2"
260 " from trigger_depends td,triggers t1,functions f1,items i1,hosts h1,"
261 "triggers t2,functions f2,items i2,hosts h2"
262 " where td.triggerid_down=t1.triggerid"
263 " and t1.triggerid=f1.triggerid"
264 " and f1.itemid=i1.itemid"
265 " and i1.hostid=h1.hostid"
266 " and td.triggerid_up=t2.triggerid"
267 " and t2.triggerid=f2.triggerid"
268 " and f2.itemid=i2.itemid"
269 " and i2.hostid=h2.hostid"
270 " and");
271 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i1.hostid",
272 templateids->values, templateids->values_num);
273 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
274 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i2.hostid",
275 templateids->values, templateids->values_num);
276 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and h2.status=%d", HOST_STATUS_TEMPLATE);
277
278 result = DBselectN(sql, 1);
279
280 if (NULL != (row = DBfetch(result)))
281 {
282 ret = FAIL;
283 zbx_snprintf(error, max_error_len,
284 "trigger \"%s\" in template \"%s\""
285 " has dependency from trigger \"%s\" in template \"%s\"",
286 row[0], row[1], row[2], row[3]);
287 }
288 DBfree_result(result);
289 }
290
291 /* graphs */
292 if (SUCCEED == ret && 1 < templateids->values_num)
293 {
294 zbx_vector_uint64_t graphids;
295
296 zbx_vector_uint64_create(&graphids);
297
298 /* select all linked graphs */
299 sql_offset = 0;
300 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
301 "select distinct gi.graphid"
302 " from graphs_items gi,items i"
303 " where gi.itemid=i.itemid"
304 " and");
305 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid",
306 templateids->values, templateids->values_num);
307
308 DBselect_uint64(sql, &graphids);
309
310 /* check for names */
311 if (0 != graphids.values_num)
312 {
313 sql_offset = 0;
314 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
315 "select name,count(*)"
316 " from graphs"
317 " where");
318 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "graphid",
319 graphids.values, graphids.values_num);
320 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
321 " group by name"
322 " having count(*)>1");
323
324 result = DBselect("%s", sql);
325
326 if (NULL != (row = DBfetch(result)))
327 {
328 ret = FAIL;
329 zbx_snprintf(error, max_error_len,
330 "template with graph \"%s\" already linked to the host", row[0]);
331 }
332 DBfree_result(result);
333 }
334
335 zbx_vector_uint64_destroy(&graphids);
336 }
337
338 /* httptests */
339 if (SUCCEED == ret && 1 < templateids->values_num)
340 {
341 sql_offset = 0;
342 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
343 "select name,count(*)"
344 " from httptest"
345 " where");
346 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
347 templateids->values, templateids->values_num);
348 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
349 " group by name"
350 " having count(*)>1");
351
352 result = DBselectN(sql, 1);
353
354 if (NULL != (row = DBfetch(result)))
355 {
356 ret = FAIL;
357 zbx_snprintf(error, max_error_len,
358 "template with web scenario \"%s\" already linked to the host", row[0]);
359 }
360 DBfree_result(result);
361 }
362
363 zbx_free(sql);
364 out:
365 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
366
367 return ret;
368 }
369
370 /******************************************************************************
371 * *
372 * Function: DBcmp_triggers *
373 * *
374 * Purpose: compare two triggers *
375 * *
376 * Parameters: triggerid1 - first trigger identificator from database *
377 * triggerid2 - second trigger identificator from database *
378 * *
379 * Return value: SUCCEED - if triggers coincide *
380 * *
381 ******************************************************************************/
DBcmp_triggers(zbx_uint64_t triggerid1,const char * expression1,const char * recovery_expression1,zbx_uint64_t triggerid2,const char * expression2,const char * recovery_expression2)382 static int DBcmp_triggers(zbx_uint64_t triggerid1, const char *expression1, const char *recovery_expression1,
383 zbx_uint64_t triggerid2, const char *expression2, const char *recovery_expression2)
384 {
385 DB_RESULT result;
386 DB_ROW row;
387 char search[MAX_ID_LEN + 3], replace[MAX_ID_LEN + 3], *old_expr = NULL, *expr = NULL, *rexpr = NULL;
388 int res = SUCCEED;
389
390 expr = zbx_strdup(NULL, expression2);
391 rexpr = zbx_strdup(NULL, recovery_expression2);
392
393 result = DBselect(
394 "select f1.functionid,f2.functionid"
395 " from functions f1,functions f2,items i1,items i2"
396 " where f1.name=f2.name"
397 " and f1.parameter=f2.parameter"
398 " and i1.key_=i2.key_"
399 " and i1.itemid=f1.itemid"
400 " and i2.itemid=f2.itemid"
401 " and f1.triggerid=" ZBX_FS_UI64
402 " and f2.triggerid=" ZBX_FS_UI64,
403 triggerid1, triggerid2);
404
405 while (NULL != (row = DBfetch(result)))
406 {
407 zbx_snprintf(search, sizeof(search), "{%s}", row[1]);
408 zbx_snprintf(replace, sizeof(replace), "{%s}", row[0]);
409
410 old_expr = expr;
411 expr = string_replace(expr, search, replace);
412 zbx_free(old_expr);
413
414 old_expr = rexpr;
415 rexpr = string_replace(rexpr, search, replace);
416 zbx_free(old_expr);
417 }
418 DBfree_result(result);
419
420 if (0 != strcmp(expression1, expr) || 0 != strcmp(recovery_expression1, rexpr))
421 res = FAIL;
422
423 zbx_free(rexpr);
424 zbx_free(expr);
425
426 return res;
427 }
428
429 /******************************************************************************
430 * *
431 * Function: validate_inventory_links *
432 * *
433 * Description: Check collisions in item inventory links *
434 * *
435 * Parameters: hostid - [IN] host identificator from database *
436 * templateids - [IN] array of template IDs *
437 * *
438 * Return value: SUCCEED if no collisions found *
439 * *
440 * Author: Alexander Vladishev *
441 * *
442 * Comments: !!! Don't forget to sync the code with PHP !!! *
443 * *
444 ******************************************************************************/
validate_inventory_links(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids,char * error,size_t max_error_len)445 static int validate_inventory_links(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids,
446 char *error, size_t max_error_len)
447 {
448 const char *__function_name = "validate_inventory_links";
449 DB_RESULT result;
450 DB_ROW row;
451 char *sql = NULL;
452 size_t sql_alloc = 512, sql_offset;
453 int ret = SUCCEED;
454
455 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
456
457 sql = (char *)zbx_malloc(sql, sql_alloc);
458
459 sql_offset = 0;
460 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
461 "select inventory_link,count(*)"
462 " from items"
463 " where inventory_link<>0"
464 " and");
465 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
466 templateids->values, templateids->values_num);
467 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
468 " group by inventory_link"
469 " having count(*)>1");
470
471 result = DBselectN(sql, 1);
472
473 if (NULL != (row = DBfetch(result)))
474 {
475 ret = FAIL;
476 zbx_strlcpy(error, "two items cannot populate one host inventory field", max_error_len);
477 }
478 DBfree_result(result);
479
480 if (FAIL == ret)
481 goto out;
482
483 sql_offset = 0;
484 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
485 "select ti.itemid"
486 " from items ti,items i"
487 " where ti.key_<>i.key_"
488 " and ti.inventory_link=i.inventory_link"
489 " and");
490 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid",
491 templateids->values, templateids->values_num);
492 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
493 " and i.hostid=" ZBX_FS_UI64
494 " and ti.inventory_link<>0"
495 " and not exists ("
496 "select *"
497 " from items",
498 hostid);
499 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " where");
500 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "items.hostid",
501 templateids->values, templateids->values_num);
502 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
503 " and items.key_=i.key_"
504 ")");
505
506 result = DBselectN(sql, 1);
507
508 if (NULL != (row = DBfetch(result)))
509 {
510 ret = FAIL;
511 zbx_strlcpy(error, "two items cannot populate one host inventory field", max_error_len);
512 }
513 DBfree_result(result);
514 out:
515 zbx_free(sql);
516
517 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
518
519 return ret;
520 }
521
522 /******************************************************************************
523 * *
524 * Function: validate_httptests *
525 * *
526 * Description: checking collisions on linking of web scenarios *
527 * *
528 * Parameters: hostid - [IN] host identificator from database *
529 * templateids - [IN] array of template IDs *
530 * *
531 * Return value: SUCCEED if no collisions found *
532 * *
533 * Author: Alexander Vladishev *
534 * *
535 * Comments: !!! Don't forget to sync the code with PHP !!! *
536 * *
537 ******************************************************************************/
validate_httptests(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids,char * error,size_t max_error_len)538 static int validate_httptests(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids,
539 char *error, size_t max_error_len)
540 {
541 const char *__function_name = "validate_httptests";
542 DB_RESULT tresult;
543 DB_RESULT sresult;
544 DB_ROW trow;
545 char *sql = NULL;
546 size_t sql_alloc = 512, sql_offset = 0;
547 int ret = SUCCEED;
548 zbx_uint64_t t_httptestid, h_httptestid;
549
550 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
551
552 sql = (char *)zbx_malloc(sql, sql_alloc);
553
554 /* selects web scenarios from templates and host with identical names */
555 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
556 "select t.httptestid,t.name,h.httptestid"
557 " from httptest t"
558 " inner join httptest h"
559 " on h.name=t.name"
560 " and h.hostid=" ZBX_FS_UI64
561 " where", hostid);
562 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.hostid", templateids->values, templateids->values_num);
563
564 tresult = DBselect("%s", sql);
565
566 while (NULL != (trow = DBfetch(tresult)))
567 {
568 ZBX_STR2UINT64(t_httptestid, trow[0]);
569 ZBX_STR2UINT64(h_httptestid, trow[2]);
570
571 sql_offset = 0;
572 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
573 /* don't remove "h_httpstepid" alias, the ORACLE needs it */
574 "select t.httpstepid,h.httpstepid as h_httpstepid"
575 " from httpstep t"
576 " left join httpstep h"
577 " on h.httptestid=" ZBX_FS_UI64
578 " and h.no=t.no"
579 " and h.name=t.name"
580 " where t.httptestid=" ZBX_FS_UI64
581 " and h.httpstepid is null"
582 " union "
583 "select t.httpstepid,h.httpstepid as h_httpstepid"
584 " from httpstep h"
585 " left outer join httpstep t"
586 " on t.httptestid=" ZBX_FS_UI64
587 " and t.no=h.no"
588 " and t.name=h.name"
589 " where h.httptestid=" ZBX_FS_UI64
590 " and t.httpstepid is null",
591 h_httptestid, t_httptestid, t_httptestid, h_httptestid);
592
593 sresult = DBselectN(sql, 1);
594
595 if (NULL != DBfetch(sresult))
596 {
597 ret = FAIL;
598 zbx_snprintf(error, max_error_len,
599 "web scenario \"%s\" already exists on the host (steps are not identical)",
600 trow[1]);
601 }
602 DBfree_result(sresult);
603
604 if (SUCCEED != ret)
605 break;
606 }
607 DBfree_result(tresult);
608
609 zbx_free(sql);
610
611 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
612
613 return ret;
614 }
615
DBget_graphitems(const char * sql,ZBX_GRAPH_ITEMS ** gitems,size_t * gitems_alloc,size_t * gitems_num)616 static void DBget_graphitems(const char *sql, ZBX_GRAPH_ITEMS **gitems, size_t *gitems_alloc, size_t *gitems_num)
617 {
618 const char *__function_name = "DBget_graphitems";
619 DB_RESULT result;
620 DB_ROW row;
621 ZBX_GRAPH_ITEMS *gitem;
622
623 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
624
625 *gitems_num = 0;
626
627 result = DBselect("%s", sql);
628
629 while (NULL != (row = DBfetch(result)))
630 {
631 if (*gitems_alloc == *gitems_num)
632 {
633 *gitems_alloc += 16;
634 *gitems = (ZBX_GRAPH_ITEMS *)zbx_realloc(*gitems, *gitems_alloc * sizeof(ZBX_GRAPH_ITEMS));
635 }
636
637 gitem = &(*gitems)[*gitems_num];
638
639 ZBX_STR2UINT64(gitem->gitemid, row[0]);
640 ZBX_STR2UINT64(gitem->itemid, row[1]);
641 zbx_strlcpy(gitem->key, row[2], sizeof(gitem->key));
642 gitem->drawtype = atoi(row[3]);
643 gitem->sortorder = atoi(row[4]);
644 zbx_strlcpy(gitem->color, row[5], sizeof(gitem->color));
645 gitem->yaxisside = atoi(row[6]);
646 gitem->calc_fnc = atoi(row[7]);
647 gitem->type = atoi(row[8]);
648 gitem->flags = (unsigned char)atoi(row[9]);
649
650 zabbix_log(LOG_LEVEL_DEBUG, "%s() [" ZBX_FS_SIZE_T "] itemid:" ZBX_FS_UI64 " key:'%s'",
651 __function_name, (zbx_fs_size_t)*gitems_num, gitem->itemid, gitem->key);
652
653 (*gitems_num)++;
654 }
655 DBfree_result(result);
656
657 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
658 }
659
660 /******************************************************************************
661 * *
662 * Function: DBcmp_graphitems *
663 * *
664 * Purpose: Compare graph items from two graphs *
665 * *
666 * Parameters: gitems1 - [IN] first graph items, sorted by itemid *
667 * gitems1_num - [IN] number of first graph items *
668 * gitems2 - [IN] second graph items, sorted by itemid *
669 * gitems2_num - [IN] number of second graph items *
670 * *
671 * Return value: SUCCEED if graph items coincide *
672 * *
673 * Author: Alexander Vladishev *
674 * *
675 * Comments: !!! Don't forget to sync the code with PHP !!! *
676 * *
677 ******************************************************************************/
DBcmp_graphitems(ZBX_GRAPH_ITEMS * gitems1,int gitems1_num,ZBX_GRAPH_ITEMS * gitems2,int gitems2_num)678 static int DBcmp_graphitems(ZBX_GRAPH_ITEMS *gitems1, int gitems1_num,
679 ZBX_GRAPH_ITEMS *gitems2, int gitems2_num)
680 {
681 const char *__function_name = "DBcmp_graphitems";
682 int res = FAIL, i;
683
684 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
685
686 if (gitems1_num != gitems2_num)
687 goto clean;
688
689 for (i = 0; i < gitems1_num; i++)
690 if (0 != strcmp(gitems1[i].key, gitems2[i].key))
691 goto clean;
692
693 res = SUCCEED;
694 clean:
695 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res));
696
697 return res;
698 }
699
700 /******************************************************************************
701 * *
702 * Function: validate_host *
703 * *
704 * Description: Check collisions between host and linked template *
705 * *
706 * Parameters: hostid - [IN] host identificator from database *
707 * templateids - [IN] array of template IDs *
708 * *
709 * Return value: SUCCEED if no collisions found *
710 * *
711 * Author: Alexander Vladishev *
712 * *
713 * Comments: !!! Don't forget to sync the code with PHP !!! *
714 * *
715 ******************************************************************************/
validate_host(zbx_uint64_t hostid,zbx_vector_uint64_t * templateids,char * error,size_t max_error_len)716 static int validate_host(zbx_uint64_t hostid, zbx_vector_uint64_t *templateids, char *error, size_t max_error_len)
717 {
718 const char *__function_name = "validate_host";
719 DB_RESULT tresult;
720 DB_RESULT hresult;
721 DB_ROW trow;
722 DB_ROW hrow;
723 char *sql = NULL, *name_esc;
724 size_t sql_alloc = 256, sql_offset;
725 ZBX_GRAPH_ITEMS *gitems = NULL, *chd_gitems = NULL;
726 size_t gitems_alloc = 0, gitems_num = 0,
727 chd_gitems_alloc = 0, chd_gitems_num = 0;
728 int ret = SUCCEED, i;
729 zbx_uint64_t graphid, interfaceids[INTERFACE_TYPE_COUNT];
730 unsigned char t_flags, h_flags, type;
731
732 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
733
734 if (SUCCEED != (ret = validate_inventory_links(hostid, templateids, error, max_error_len)))
735 goto out;
736
737 if (SUCCEED != (ret = validate_httptests(hostid, templateids, error, max_error_len)))
738 goto out;
739
740 sql = (char *)zbx_malloc(sql, sql_alloc);
741
742 sql_offset = 0;
743 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
744 "select distinct g.graphid,g.name,g.flags"
745 " from graphs g,graphs_items gi,items i"
746 " where g.graphid=gi.graphid"
747 " and gi.itemid=i.itemid"
748 " and");
749 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", templateids->values, templateids->values_num);
750
751 tresult = DBselect("%s", sql);
752
753 while (SUCCEED == ret && NULL != (trow = DBfetch(tresult)))
754 {
755 ZBX_STR2UINT64(graphid, trow[0]);
756 t_flags = (unsigned char)atoi(trow[2]);
757
758 sql_offset = 0;
759 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
760 "select 0,0,i.key_,gi.drawtype,gi.sortorder,gi.color,gi.yaxisside,gi.calc_fnc,"
761 "gi.type,i.flags"
762 " from graphs_items gi,items i"
763 " where gi.itemid=i.itemid"
764 " and gi.graphid=" ZBX_FS_UI64
765 " order by i.key_",
766 graphid);
767
768 DBget_graphitems(sql, &gitems, &gitems_alloc, &gitems_num);
769
770 name_esc = DBdyn_escape_string(trow[1]);
771
772 hresult = DBselect(
773 "select distinct g.graphid,g.flags"
774 " from graphs g,graphs_items gi,items i"
775 " where g.graphid=gi.graphid"
776 " and gi.itemid=i.itemid"
777 " and i.hostid=" ZBX_FS_UI64
778 " and g.name='%s'"
779 " and g.templateid is null",
780 hostid, name_esc);
781
782 zbx_free(name_esc);
783
784 /* compare graphs */
785 while (NULL != (hrow = DBfetch(hresult)))
786 {
787 ZBX_STR2UINT64(graphid, hrow[0]);
788 h_flags = (unsigned char)atoi(hrow[1]);
789
790 if (t_flags != h_flags)
791 {
792 ret = FAIL;
793 zbx_snprintf(error, max_error_len,
794 "graph prototype and real graph \"%s\" have the same name", trow[1]);
795 break;
796 }
797
798 sql_offset = 0;
799 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
800 "select gi.gitemid,i.itemid,i.key_,gi.drawtype,gi.sortorder,gi.color,"
801 "gi.yaxisside,gi.calc_fnc,gi.type,i.flags"
802 " from graphs_items gi,items i"
803 " where gi.itemid=i.itemid"
804 " and gi.graphid=" ZBX_FS_UI64
805 " order by i.key_",
806 graphid);
807
808 DBget_graphitems(sql, &chd_gitems, &chd_gitems_alloc, &chd_gitems_num);
809
810 if (SUCCEED != DBcmp_graphitems(gitems, gitems_num, chd_gitems, chd_gitems_num))
811 {
812 ret = FAIL;
813 zbx_snprintf(error, max_error_len,
814 "graph \"%s\" already exists on the host (items are not identical)",
815 trow[1]);
816 break;
817 }
818 }
819 DBfree_result(hresult);
820 }
821 DBfree_result(tresult);
822
823 if (SUCCEED == ret)
824 {
825 sql_offset = 0;
826 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
827 "select i.key_"
828 " from items i,items t"
829 " where i.key_=t.key_"
830 " and i.flags<>t.flags"
831 " and i.hostid=" ZBX_FS_UI64
832 " and",
833 hostid);
834 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.hostid",
835 templateids->values, templateids->values_num);
836
837 tresult = DBselectN(sql, 1);
838
839 if (NULL != (trow = DBfetch(tresult)))
840 {
841 ret = FAIL;
842 zbx_snprintf(error, max_error_len,
843 "item prototype and real item \"%s\" have the same key", trow[0]);
844 }
845 DBfree_result(tresult);
846 }
847
848 /* interfaces */
849 if (SUCCEED == ret)
850 {
851 memset(&interfaceids, 0, sizeof(interfaceids));
852
853 tresult = DBselect(
854 "select type,interfaceid"
855 " from interface"
856 " where hostid=" ZBX_FS_UI64
857 " and type in (%d,%d,%d,%d)"
858 " and main=1",
859 hostid, INTERFACE_TYPE_AGENT, INTERFACE_TYPE_SNMP,
860 INTERFACE_TYPE_IPMI, INTERFACE_TYPE_JMX);
861
862 while (NULL != (trow = DBfetch(tresult)))
863 {
864 type = (unsigned char)atoi(trow[0]);
865 ZBX_STR2UINT64(interfaceids[type - 1], trow[1]);
866 }
867 DBfree_result(tresult);
868
869 sql_offset = 0;
870 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
871 "select distinct type"
872 " from items"
873 " where type not in (%d,%d,%d,%d,%d,%d,%d,%d)"
874 " and",
875 ITEM_TYPE_TRAPPER, ITEM_TYPE_INTERNAL, ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_AGGREGATE,
876 ITEM_TYPE_HTTPTEST, ITEM_TYPE_DB_MONITOR, ITEM_TYPE_CALCULATED, ITEM_TYPE_DEPENDENT);
877 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
878 templateids->values, templateids->values_num);
879
880 tresult = DBselect("%s", sql);
881
882 while (SUCCEED == ret && NULL != (trow = DBfetch(tresult)))
883 {
884 type = (unsigned char)atoi(trow[0]);
885 type = get_interface_type_by_item_type(type);
886
887 if (INTERFACE_TYPE_ANY == type)
888 {
889 for (i = 0; INTERFACE_TYPE_COUNT > i; i++)
890 {
891 if (0 != interfaceids[i])
892 break;
893 }
894
895 if (INTERFACE_TYPE_COUNT == i)
896 {
897 zbx_strlcpy(error, "cannot find any interfaces on host", max_error_len);
898 ret = FAIL;
899 }
900 }
901 else if (0 == interfaceids[type - 1])
902 {
903 zbx_snprintf(error, max_error_len, "cannot find \"%s\" host interface",
904 zbx_interface_type_string((zbx_interface_type_t)type));
905 ret = FAIL;
906 }
907 }
908 DBfree_result(tresult);
909 }
910
911 zbx_free(sql);
912 zbx_free(gitems);
913 zbx_free(chd_gitems);
914 out:
915 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
916
917 return ret;
918 }
919
920 /******************************************************************************
921 * *
922 * Function: DBdelete_action_conditions *
923 * *
924 * Purpose: delete action conditions by condition type and id *
925 * *
926 * Author: Alexander Vladishev *
927 * *
928 ******************************************************************************/
DBdelete_action_conditions(int conditiontype,zbx_uint64_t elementid)929 static void DBdelete_action_conditions(int conditiontype, zbx_uint64_t elementid)
930 {
931 DB_RESULT result;
932 DB_ROW row;
933 zbx_uint64_t id;
934 zbx_vector_uint64_t actionids, conditionids;
935 char *sql = NULL;
936 size_t sql_alloc = 0, sql_offset = 0;
937
938 zbx_vector_uint64_create(&actionids);
939 zbx_vector_uint64_create(&conditionids);
940
941 /* disable actions */
942 result = DBselect("select actionid,conditionid from conditions where conditiontype=%d and"
943 " value='" ZBX_FS_UI64 "'", conditiontype, elementid);
944
945 while (NULL != (row = DBfetch(result)))
946 {
947 ZBX_STR2UINT64(id, row[0]);
948 zbx_vector_uint64_append(&actionids, id);
949
950 ZBX_STR2UINT64(id, row[1]);
951 zbx_vector_uint64_append(&conditionids, id);
952 }
953
954 DBfree_result(result);
955
956 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
957
958 if (0 != actionids.values_num)
959 {
960 zbx_vector_uint64_sort(&actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
961 zbx_vector_uint64_uniq(&actionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
962
963 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update actions set status=%d where",
964 ACTION_STATUS_DISABLED);
965 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "actionid", actionids.values,
966 actionids.values_num);
967 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
968 }
969
970 if (0 != conditionids.values_num)
971 {
972 zbx_vector_uint64_sort(&conditionids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
973
974 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from conditions where");
975 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "conditionid", conditionids.values,
976 conditionids.values_num);
977 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
978 }
979
980 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
981
982 /* in ORACLE always present begin..end; */
983 if (16 < sql_offset)
984 DBexecute("%s", sql);
985
986 zbx_free(sql);
987
988 zbx_vector_uint64_destroy(&conditionids);
989 zbx_vector_uint64_destroy(&actionids);
990 }
991
992 /******************************************************************************
993 * *
994 * Function: DBadd_to_housekeeper *
995 * *
996 * Purpose: adds table and field with specific id to housekeeper list *
997 * *
998 * Parameters: ids - [IN] identificators for data removal *
999 * field - [IN] field name from table *
1000 * tables_hk - [IN] table name to delete information from *
1001 * count - [IN] number of tables in tables array *
1002 * *
1003 * Author: Eugene Grigorjev, Alexander Vladishev *
1004 * *
1005 * Comments: !!! Don't forget to sync the code with PHP !!! *
1006 * *
1007 ******************************************************************************/
DBadd_to_housekeeper(zbx_vector_uint64_t * ids,const char * field,const char ** tables_hk,int count)1008 static void DBadd_to_housekeeper(zbx_vector_uint64_t *ids, const char *field, const char **tables_hk, int count)
1009 {
1010 const char *__function_name = "DBadd_to_housekeeper";
1011 int i, j;
1012 zbx_uint64_t housekeeperid;
1013 zbx_db_insert_t db_insert;
1014
1015 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, ids->values_num);
1016
1017 if (0 == ids->values_num)
1018 goto out;
1019
1020 housekeeperid = DBget_maxid_num("housekeeper", count * ids->values_num);
1021
1022 zbx_db_insert_prepare(&db_insert, "housekeeper", "housekeeperid", "tablename", "field", "value", NULL);
1023
1024 for (i = 0; i < ids->values_num; i++)
1025 {
1026 for (j = 0; j < count; j++)
1027 zbx_db_insert_add_values(&db_insert, housekeeperid++, tables_hk[j], field, ids->values[i]);
1028 }
1029
1030 zbx_db_insert_execute(&db_insert);
1031 zbx_db_insert_clean(&db_insert);
1032 out:
1033 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1034 }
1035
1036 /******************************************************************************
1037 * *
1038 * Function: DBdelete_triggers *
1039 * *
1040 * Purpose: delete trigger from database *
1041 * *
1042 * Parameters: triggerids - [IN] trigger identificators from database *
1043 * *
1044 ******************************************************************************/
DBdelete_triggers(zbx_vector_uint64_t * triggerids)1045 static void DBdelete_triggers(zbx_vector_uint64_t *triggerids)
1046 {
1047 char *sql = NULL;
1048 size_t sql_alloc = 256, sql_offset;
1049 int i;
1050 zbx_vector_uint64_t selementids;
1051 const char *event_tables[] = {"events"};
1052
1053 if (0 == triggerids->values_num)
1054 return;
1055
1056 sql = (char *)zbx_malloc(sql, sql_alloc);
1057
1058 zbx_vector_uint64_create(&selementids);
1059
1060 DBremove_triggers_from_itservices(triggerids->values, triggerids->values_num);
1061
1062 sql_offset = 0;
1063 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1064
1065 DBget_sysmapelements_by_element_type_ids(&selementids, SYSMAP_ELEMENT_TYPE_TRIGGER, triggerids);
1066 if (0 != selementids.values_num)
1067 {
1068 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from sysmaps_elements where");
1069 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "selementid", selementids.values,
1070 selementids.values_num);
1071 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1072 }
1073
1074 for (i = 0; i < triggerids->values_num; i++)
1075 DBdelete_action_conditions(CONDITION_TYPE_TRIGGER, triggerids->values[i]);
1076
1077 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1078 "delete from triggers"
1079 " where");
1080 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid", triggerids->values, triggerids->values_num);
1081 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1082
1083 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1084
1085 DBexecute("%s", sql);
1086
1087 /* add housekeeper task to delete problems associated with trigger, this allows old events to be deleted */
1088 DBadd_to_housekeeper(triggerids, "triggerid", event_tables, ARRSIZE(event_tables));
1089
1090 zbx_vector_uint64_destroy(&selementids);
1091
1092 zbx_free(sql);
1093 }
1094
1095 /******************************************************************************
1096 * *
1097 * Function: DBdelete_trigger_hierarchy *
1098 * *
1099 * Purpose: delete parent triggers and auto-created children from database *
1100 * *
1101 * Parameters: triggerids - [IN] trigger identificators from database *
1102 * *
1103 ******************************************************************************/
DBdelete_trigger_hierarchy(zbx_vector_uint64_t * triggerids)1104 static void DBdelete_trigger_hierarchy(zbx_vector_uint64_t *triggerids)
1105 {
1106 char *sql = NULL;
1107 size_t sql_alloc = 256, sql_offset = 0;
1108 zbx_vector_uint64_t children_triggerids;
1109
1110 if (0 == triggerids->values_num)
1111 return;
1112
1113 sql = (char *)zbx_malloc(sql, sql_alloc);
1114
1115 zbx_vector_uint64_create(&children_triggerids);
1116
1117 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct triggerid from trigger_discovery where");
1118 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "parent_triggerid", triggerids->values,
1119 triggerids->values_num);
1120
1121 DBselect_uint64(sql, &children_triggerids);
1122 zbx_vector_uint64_setdiff(triggerids, &children_triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1123
1124 DBdelete_triggers(&children_triggerids);
1125 DBdelete_triggers(triggerids);
1126
1127 zbx_vector_uint64_destroy(&children_triggerids);
1128
1129 zbx_free(sql);
1130 }
1131
1132 /******************************************************************************
1133 * *
1134 * Function: DBdelete_triggers_by_itemids *
1135 * *
1136 * Purpose: delete triggers by itemid *
1137 * *
1138 * Parameters: itemids - [IN] item identificators from database *
1139 * *
1140 * Author: Eugene Grigorjev *
1141 * *
1142 * Comments: !!! Don't forget to sync the code with PHP !!! *
1143 * *
1144 ******************************************************************************/
DBdelete_triggers_by_itemids(zbx_vector_uint64_t * itemids)1145 static void DBdelete_triggers_by_itemids(zbx_vector_uint64_t *itemids)
1146 {
1147 const char *__function_name = "DBdelete_triggers_by_itemids";
1148
1149 char *sql = NULL;
1150 size_t sql_alloc = 0, sql_offset = 0;
1151 zbx_vector_uint64_t triggerids;
1152
1153 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, itemids->values_num);
1154
1155 if (0 == itemids->values_num)
1156 goto out;
1157
1158 zbx_vector_uint64_create(&triggerids);
1159
1160 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct triggerid from functions where");
1161 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids->values, itemids->values_num);
1162
1163 DBselect_uint64(sql, &triggerids);
1164
1165 DBdelete_trigger_hierarchy(&triggerids);
1166 zbx_vector_uint64_destroy(&triggerids);
1167 zbx_free(sql);
1168 out:
1169 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1170 }
1171
1172 /******************************************************************************
1173 * *
1174 * Function: DBdelete_graphs *
1175 * *
1176 * Purpose: delete graph from database *
1177 * *
1178 * Parameters: graphids - [IN] array of graph id's from database *
1179 * *
1180 ******************************************************************************/
DBdelete_graphs(zbx_vector_uint64_t * graphids)1181 void DBdelete_graphs(zbx_vector_uint64_t *graphids)
1182 {
1183 const char *__function_name = "DBdelete_graphs";
1184
1185 char *sql = NULL;
1186 size_t sql_alloc = 256, sql_offset = 0;
1187 zbx_vector_uint64_t profileids, screen_itemids;
1188 zbx_uint64_t resource_type = SCREEN_RESOURCE_GRAPH;
1189 const char *profile_idx = "web.favorite.graphids";
1190
1191 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, graphids->values_num);
1192
1193 if (0 == graphids->values_num)
1194 goto out;
1195
1196 sql = (char *)zbx_malloc(sql, sql_alloc);
1197
1198 zbx_vector_uint64_create(&profileids);
1199 zbx_vector_uint64_create(&screen_itemids);
1200
1201 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1202
1203 /* delete from screens_items */
1204 DBget_screenitems_by_resource_types_ids(&screen_itemids, &resource_type, 1, graphids);
1205 if (0 != screen_itemids.values_num)
1206 {
1207 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from screens_items where");
1208 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "screenitemid", screen_itemids.values,
1209 screen_itemids.values_num);
1210 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1211 }
1212
1213 /* delete from profiles */
1214 DBget_profiles_by_source_idxs_values(&profileids, "graphid", &profile_idx, 1, graphids);
1215 if (0 != profileids.values_num)
1216 {
1217 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from profiles where");
1218 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "profileid", profileids.values,
1219 profileids.values_num);
1220 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1221 }
1222
1223 /* delete from graphs */
1224 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from graphs where");
1225 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "graphid", graphids->values, graphids->values_num);
1226 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1227
1228 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1229
1230 DBexecute("%s", sql);
1231
1232 zbx_vector_uint64_destroy(&screen_itemids);
1233 zbx_vector_uint64_destroy(&profileids);
1234
1235 zbx_free(sql);
1236 out:
1237 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1238 }
1239
1240 /******************************************************************************
1241 * *
1242 * Function: DBdelete_graph_hierarchy *
1243 * *
1244 * Purpose: delete parent graphs and auto-created children from database *
1245 * *
1246 * Parameters: graphids - [IN] array of graph id's from database *
1247 * *
1248 ******************************************************************************/
DBdelete_graph_hierarchy(zbx_vector_uint64_t * graphids)1249 static void DBdelete_graph_hierarchy(zbx_vector_uint64_t *graphids)
1250 {
1251 char *sql = NULL;
1252 size_t sql_alloc = 256, sql_offset = 0;
1253 zbx_vector_uint64_t children_graphids;
1254
1255 if (0 == graphids->values_num)
1256 return;
1257
1258 sql = (char *)zbx_malloc(sql, sql_alloc);
1259
1260 zbx_vector_uint64_create(&children_graphids);
1261
1262 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct graphid from graph_discovery where");
1263 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "parent_graphid", graphids->values,
1264 graphids->values_num);
1265
1266 DBselect_uint64(sql, &children_graphids);
1267 zbx_vector_uint64_setdiff(graphids, &children_graphids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1268
1269 DBdelete_graphs(&children_graphids);
1270 DBdelete_graphs(graphids);
1271
1272 zbx_vector_uint64_destroy(&children_graphids);
1273
1274 zbx_free(sql);
1275 }
1276
1277 /******************************************************************************
1278 * *
1279 * Function: DBdelete_graphs_by_itemids *
1280 * *
1281 * Parameters: itemids - [IN] item identificators from database *
1282 * *
1283 * Author: Alexander Vladishev *
1284 * *
1285 ******************************************************************************/
DBdelete_graphs_by_itemids(zbx_vector_uint64_t * itemids)1286 static void DBdelete_graphs_by_itemids(zbx_vector_uint64_t *itemids)
1287 {
1288 const char *__function_name = "DBdelete_graphs_by_itemids";
1289 char *sql = NULL;
1290 size_t sql_alloc = 256, sql_offset;
1291 DB_RESULT result;
1292 DB_ROW row;
1293 zbx_uint64_t graphid;
1294 zbx_vector_uint64_t graphids;
1295 int index;
1296
1297 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, itemids->values_num);
1298
1299 if (0 == itemids->values_num)
1300 goto out;
1301
1302 sql = (char *)zbx_malloc(sql, sql_alloc);
1303 zbx_vector_uint64_create(&graphids);
1304
1305 /* select all graphs with items */
1306 sql_offset = 0;
1307 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "select distinct graphid from graphs_items where");
1308 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids->values, itemids->values_num);
1309
1310 DBselect_uint64(sql, &graphids);
1311
1312 if (0 == graphids.values_num)
1313 goto clean;
1314
1315 /* select graphs with other items */
1316 sql_offset = 0;
1317 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1318 "select distinct graphid"
1319 " from graphs_items"
1320 " where");
1321 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "graphid", graphids.values, graphids.values_num);
1322 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and not");
1323 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids->values, itemids->values_num);
1324 result = DBselect("%s", sql);
1325
1326 while (NULL != (row = DBfetch(result)))
1327 {
1328 ZBX_STR2UINT64(graphid, row[0]);
1329 if (FAIL != (index = zbx_vector_uint64_bsearch(&graphids, graphid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
1330 zbx_vector_uint64_remove(&graphids, index);
1331 }
1332 DBfree_result(result);
1333
1334 DBdelete_graph_hierarchy(&graphids);
1335 clean:
1336 zbx_vector_uint64_destroy(&graphids);
1337 zbx_free(sql);
1338 out:
1339 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1340 }
1341
1342 /******************************************************************************
1343 * *
1344 * Function: DBdelete_items *
1345 * *
1346 * Purpose: delete items from database *
1347 * *
1348 * Parameters: itemids - [IN] array of item identificators from database *
1349 * *
1350 ******************************************************************************/
DBdelete_items(zbx_vector_uint64_t * itemids)1351 void DBdelete_items(zbx_vector_uint64_t *itemids)
1352 {
1353 const char *__function_name = "DBdelete_items";
1354
1355 char *sql = NULL;
1356 size_t sql_alloc = 256, sql_offset;
1357 zbx_vector_uint64_t screen_itemids, profileids;
1358 int num;
1359 zbx_uint64_t resource_types[] = {SCREEN_RESOURCE_PLAIN_TEXT, SCREEN_RESOURCE_SIMPLE_GRAPH};
1360 const char *history_tables[] = {"history", "history_str", "history_uint", "history_log",
1361 "history_text", "trends", "trends_uint"};
1362 const char *event_tables[] = {"events"};
1363 const char *profile_idx = "web.favorite.graphids";
1364
1365 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, itemids->values_num);
1366
1367 if (0 == itemids->values_num)
1368 goto out;
1369
1370 sql = (char *)zbx_malloc(sql, sql_alloc);
1371 zbx_vector_uint64_create(&screen_itemids);
1372 zbx_vector_uint64_create(&profileids);
1373
1374 do /* add child items (auto-created and prototypes) */
1375 {
1376 num = itemids->values_num;
1377 sql_offset = 0;
1378 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select distinct itemid from item_discovery where");
1379 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "parent_itemid",
1380 itemids->values, itemids->values_num);
1381
1382 DBselect_uint64(sql, itemids);
1383 zbx_vector_uint64_uniq(itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1384 }
1385 while (num != itemids->values_num);
1386
1387 DBdelete_graphs_by_itemids(itemids);
1388 DBdelete_triggers_by_itemids(itemids);
1389
1390 DBadd_to_housekeeper(itemids, "itemid", history_tables, ARRSIZE(history_tables));
1391
1392 /* add housekeeper task to delete problems associated with item, this allows old events to be deleted */
1393 DBadd_to_housekeeper(itemids, "itemid", event_tables, ARRSIZE(event_tables));
1394 DBadd_to_housekeeper(itemids, "lldruleid", event_tables, ARRSIZE(event_tables));
1395
1396 sql_offset = 0;
1397 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1398
1399 /* delete from screens_items */
1400 DBget_screenitems_by_resource_types_ids(&screen_itemids, resource_types, ARRSIZE(resource_types), itemids);
1401 if (0 != screen_itemids.values_num)
1402 {
1403 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from screens_items where");
1404 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "screenitemid", screen_itemids.values,
1405 screen_itemids.values_num);
1406 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1407 }
1408
1409 /* delete from profiles */
1410 DBget_profiles_by_source_idxs_values(&profileids, "itemid", &profile_idx, 1, itemids);
1411 if (0 != profileids.values_num)
1412 {
1413 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from profiles where");
1414 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "profileid", profileids.values,
1415 profileids.values_num);
1416 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1417 }
1418
1419 /* delete from items */
1420 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from items where");
1421 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids->values, itemids->values_num);
1422 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1423
1424 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1425
1426 DBexecute("%s", sql);
1427
1428 zbx_vector_uint64_destroy(&profileids);
1429 zbx_vector_uint64_destroy(&screen_itemids);
1430
1431 zbx_free(sql);
1432 out:
1433 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1434 }
1435
1436 /******************************************************************************
1437 * *
1438 * Function: DBdelete_httptests *
1439 * *
1440 * Purpose: delete web tests from database *
1441 * *
1442 * Parameters: httptestids - [IN] array of httptest id's from database *
1443 * *
1444 * Author: Alexander Vladishev *
1445 * *
1446 * Comments: !!! Don't forget to sync the code with PHP !!! *
1447 * *
1448 ******************************************************************************/
DBdelete_httptests(zbx_vector_uint64_t * httptestids)1449 static void DBdelete_httptests(zbx_vector_uint64_t *httptestids)
1450 {
1451 const char *__function_name = "DBdelete_httptests";
1452
1453 char *sql = NULL;
1454 size_t sql_alloc = 256, sql_offset = 0;
1455 zbx_vector_uint64_t itemids;
1456
1457 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, httptestids->values_num);
1458
1459 if (0 == httptestids->values_num)
1460 goto out;
1461
1462 sql = (char *)zbx_malloc(sql, sql_alloc);
1463 zbx_vector_uint64_create(&itemids);
1464
1465 /* httpstepitem, httptestitem */
1466 sql_offset = 0;
1467 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1468 "select hsi.itemid"
1469 " from httpstepitem hsi,httpstep hs"
1470 " where hsi.httpstepid=hs.httpstepid"
1471 " and");
1472 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hs.httptestid",
1473 httptestids->values, httptestids->values_num);
1474 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1475 " union all "
1476 "select itemid"
1477 " from httptestitem"
1478 " where");
1479 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid",
1480 httptestids->values, httptestids->values_num);
1481
1482 DBselect_uint64(sql, &itemids);
1483
1484 DBdelete_items(&itemids);
1485
1486 sql_offset = 0;
1487 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from httptest where");
1488 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid",
1489 httptestids->values, httptestids->values_num);
1490 DBexecute("%s", sql);
1491
1492 zbx_vector_uint64_destroy(&itemids);
1493 zbx_free(sql);
1494 out:
1495 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1496 }
1497
1498 /******************************************************************************
1499 * *
1500 * Function: DBdelete_application *
1501 * *
1502 * Purpose: delete application *
1503 * *
1504 * Parameters: applicationid - [IN] application identificator from database *
1505 * *
1506 * Author: Eugene Grigorjev, Alexander Vladishev *
1507 * *
1508 * Comments: !!! Don't forget to sync the code with PHP !!! *
1509 * *
1510 ******************************************************************************/
DBdelete_applications(zbx_vector_uint64_t * applicationids)1511 static void DBdelete_applications(zbx_vector_uint64_t *applicationids)
1512 {
1513 DB_RESULT result;
1514 DB_ROW row;
1515 char *sql = NULL;
1516 size_t sql_alloc = 0, sql_offset = 0;
1517 zbx_uint64_t applicationid;
1518 int index;
1519
1520 if (0 == applicationids->values_num)
1521 goto out;
1522
1523 /* don't delete applications used in web scenarios */
1524 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1525 "select distinct applicationid"
1526 " from httptest"
1527 " where");
1528 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "applicationid", applicationids->values,
1529 applicationids->values_num);
1530
1531 result = DBselect("%s", sql);
1532
1533 while (NULL != (row = DBfetch(result)))
1534 {
1535 ZBX_STR2UINT64(applicationid, row[0]);
1536
1537 index = zbx_vector_uint64_bsearch(applicationids, applicationid, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1538 zbx_vector_uint64_remove(applicationids, index);
1539 }
1540 DBfree_result(result);
1541
1542 if (0 == applicationids->values_num)
1543 goto out;
1544
1545 /* don't delete applications with items assigned to them */
1546 sql_offset = 0;
1547 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
1548 "select distinct applicationid"
1549 " from items_applications"
1550 " where");
1551 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "applicationid", applicationids->values,
1552 applicationids->values_num);
1553
1554 result = DBselect("%s", sql);
1555
1556 while (NULL != (row = DBfetch(result)))
1557 {
1558 ZBX_STR2UINT64(applicationid, row[0]);
1559
1560 index = zbx_vector_uint64_bsearch(applicationids, applicationid, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1561 zbx_vector_uint64_remove(applicationids, index);
1562 }
1563 DBfree_result(result);
1564
1565 if (0 == applicationids->values_num)
1566 goto out;
1567
1568 sql_offset = 0;
1569 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1570
1571 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from applications where");
1572 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset,
1573 "applicationid", applicationids->values, applicationids->values_num);
1574 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1575
1576 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1577
1578 DBexecute("%s", sql);
1579 out:
1580 zbx_free(sql);
1581 }
1582
1583 /******************************************************************************
1584 * *
1585 * Function: DBgroup_prototypes_delete *
1586 * *
1587 * Parameters: del_group_prototypeids - [IN] list of group_prototypeids which *
1588 * will be deleted *
1589 * *
1590 ******************************************************************************/
DBgroup_prototypes_delete(zbx_vector_uint64_t * del_group_prototypeids)1591 static void DBgroup_prototypes_delete(zbx_vector_uint64_t *del_group_prototypeids)
1592 {
1593 char *sql = NULL;
1594 size_t sql_alloc = 0, sql_offset;
1595 zbx_vector_uint64_t groupids;
1596
1597 if (0 == del_group_prototypeids->values_num)
1598 return;
1599
1600 zbx_vector_uint64_create(&groupids);
1601
1602 sql_offset = 0;
1603 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select groupid from group_discovery where");
1604 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "parent_group_prototypeid",
1605 del_group_prototypeids->values, del_group_prototypeids->values_num);
1606
1607 DBselect_uint64(sql, &groupids);
1608
1609 DBdelete_groups(&groupids);
1610
1611 sql_offset = 0;
1612 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from group_prototype where");
1613 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "group_prototypeid",
1614 del_group_prototypeids->values, del_group_prototypeids->values_num);
1615
1616 DBexecute("%s", sql);
1617
1618 zbx_vector_uint64_destroy(&groupids);
1619 zbx_free(sql);
1620 }
1621
1622 /******************************************************************************
1623 * *
1624 * Function: DBdelete_host_prototypes *
1625 * *
1626 * Purpose: deletes host prototypes from database *
1627 * *
1628 * Parameters: host_prototypeids - [IN] list of host prototypes *
1629 * *
1630 ******************************************************************************/
DBdelete_host_prototypes(zbx_vector_uint64_t * host_prototypeids)1631 static void DBdelete_host_prototypes(zbx_vector_uint64_t *host_prototypeids)
1632 {
1633 char *sql = NULL;
1634 size_t sql_alloc = 0, sql_offset;
1635 zbx_vector_uint64_t hostids, group_prototypeids;
1636
1637 if (0 == host_prototypeids->values_num)
1638 return;
1639
1640 /* delete discovered hosts */
1641
1642 zbx_vector_uint64_create(&hostids);
1643 zbx_vector_uint64_create(&group_prototypeids);
1644
1645 sql_offset = 0;
1646 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select hostid from host_discovery where");
1647 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "parent_hostid",
1648 host_prototypeids->values, host_prototypeids->values_num);
1649
1650 DBselect_uint64(sql, &hostids);
1651
1652 if (0 != hostids.values_num)
1653 DBdelete_hosts(&hostids);
1654
1655 /* delete group prototypes */
1656
1657 sql_offset = 0;
1658 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "select group_prototypeid from group_prototype where");
1659 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
1660 host_prototypeids->values, host_prototypeids->values_num);
1661
1662 DBselect_uint64(sql, &group_prototypeids);
1663
1664 DBgroup_prototypes_delete(&group_prototypeids);
1665
1666 /* delete host prototypes */
1667
1668 sql_offset = 0;
1669 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hosts where");
1670 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid",
1671 host_prototypeids->values, host_prototypeids->values_num);
1672
1673 DBexecute("%s", sql);
1674
1675 zbx_vector_uint64_destroy(&group_prototypeids);
1676 zbx_vector_uint64_destroy(&hostids);
1677 zbx_free(sql);
1678 }
1679
1680 /******************************************************************************
1681 * *
1682 * Function: DBdelete_template_httptests *
1683 * *
1684 * Purpose: delete template web scenatios from host *
1685 * *
1686 * Parameters: hostid - [IN] host identificator from database *
1687 * templateids - [IN] array of template IDs *
1688 * *
1689 ******************************************************************************/
DBdelete_template_httptests(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1690 static void DBdelete_template_httptests(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1691 {
1692 const char *__function_name = "DBdelete_template_httptests";
1693
1694 char *sql = NULL;
1695 size_t sql_alloc = 0, sql_offset = 0;
1696 zbx_vector_uint64_t httptestids;
1697
1698 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1699
1700 zbx_vector_uint64_create(&httptestids);
1701
1702 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1703 "select h.httptestid"
1704 " from httptest h"
1705 " join httptest t"
1706 " on");
1707 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.hostid", templateids->values, templateids->values_num);
1708 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1709 " and t.httptestid=h.templateid"
1710 " where h.hostid=" ZBX_FS_UI64, hostid);
1711
1712 DBselect_uint64(sql, &httptestids);
1713
1714 DBdelete_httptests(&httptestids);
1715
1716 zbx_vector_uint64_destroy(&httptestids);
1717 zbx_free(sql);
1718
1719 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1720 }
1721
1722 /******************************************************************************
1723 * *
1724 * Function: DBdelete_template_graphs *
1725 * *
1726 * Purpose: delete template graphs from host *
1727 * *
1728 * Parameters: hostid - [IN] host identificator from database *
1729 * templateids - [IN] array of template IDs *
1730 * *
1731 * Author: Eugene Grigorjev *
1732 * *
1733 * Comments: !!! Don't forget to sync the code with PHP !!! *
1734 * *
1735 ******************************************************************************/
DBdelete_template_graphs(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1736 static void DBdelete_template_graphs(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1737 {
1738 const char *__function_name = "DBdelete_template_graphs";
1739
1740 char *sql = NULL;
1741 size_t sql_alloc = 0, sql_offset = 0;
1742 zbx_vector_uint64_t graphids;
1743
1744 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1745
1746 zbx_vector_uint64_create(&graphids);
1747
1748 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1749 "select distinct gi.graphid"
1750 " from graphs_items gi,items i,items ti"
1751 " where gi.itemid=i.itemid"
1752 " and i.templateid=ti.itemid"
1753 " and i.hostid=" ZBX_FS_UI64
1754 " and",
1755 hostid);
1756 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
1757
1758 DBselect_uint64(sql, &graphids);
1759
1760 DBdelete_graph_hierarchy(&graphids);
1761
1762 zbx_vector_uint64_destroy(&graphids);
1763 zbx_free(sql);
1764
1765 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1766 }
1767
1768 /******************************************************************************
1769 * *
1770 * Function: DBdelete_template_triggers *
1771 * *
1772 * Purpose: delete template triggers from host *
1773 * *
1774 * Parameters: hostid - [IN] host identificator from database *
1775 * templateids - [IN] array of template IDs *
1776 * *
1777 * Author: Eugene Grigorjev *
1778 * *
1779 * Comments: !!! Don't forget to sync the code with PHP !!! *
1780 * *
1781 ******************************************************************************/
DBdelete_template_triggers(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1782 static void DBdelete_template_triggers(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1783 {
1784 const char *__function_name = "DBdelete_template_triggers";
1785
1786 char *sql = NULL;
1787 size_t sql_alloc = 0, sql_offset = 0;
1788 zbx_vector_uint64_t triggerids;
1789
1790 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1791
1792 zbx_vector_uint64_create(&triggerids);
1793
1794 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1795 "select distinct f.triggerid"
1796 " from functions f,items i,items ti"
1797 " where f.itemid=i.itemid"
1798 " and i.templateid=ti.itemid"
1799 " and i.hostid=" ZBX_FS_UI64
1800 " and",
1801 hostid);
1802 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
1803
1804 DBselect_uint64(sql, &triggerids);
1805
1806 DBdelete_trigger_hierarchy(&triggerids);
1807 zbx_vector_uint64_destroy(&triggerids);
1808 zbx_free(sql);
1809
1810 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1811 }
1812
1813 /******************************************************************************
1814 * *
1815 * Function: DBdelete_template_host_prototypes *
1816 * *
1817 * Purpose: delete template host prototypes from host *
1818 * *
1819 * Parameters: hostid - [IN] host identificator from database *
1820 * templateids - [IN] array of template IDs *
1821 * *
1822 ******************************************************************************/
DBdelete_template_host_prototypes(zbx_uint64_t hostid,zbx_vector_uint64_t * templateids)1823 static void DBdelete_template_host_prototypes(zbx_uint64_t hostid, zbx_vector_uint64_t *templateids)
1824 {
1825 const char *__function_name = "DBdelete_template_host_prototypes";
1826
1827 char *sql = NULL;
1828 size_t sql_alloc = 0, sql_offset = 0;
1829 zbx_vector_uint64_t host_prototypeids;
1830
1831 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1832
1833 zbx_vector_uint64_create(&host_prototypeids);
1834
1835 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1836 "select hp.hostid"
1837 " from items hi,host_discovery hhd,hosts hp,host_discovery thd,items ti"
1838 " where hi.itemid=hhd.parent_itemid"
1839 " and hhd.hostid=hp.hostid"
1840 " and hp.templateid=thd.hostid"
1841 " and thd.parent_itemid=ti.itemid"
1842 " and hi.hostid=" ZBX_FS_UI64
1843 " and",
1844 hostid);
1845 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
1846
1847 DBselect_uint64(sql, &host_prototypeids);
1848
1849 DBdelete_host_prototypes(&host_prototypeids);
1850
1851 zbx_free(sql);
1852
1853 zbx_vector_uint64_destroy(&host_prototypeids);
1854
1855 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1856 }
1857
1858 /******************************************************************************
1859 * *
1860 * Function: DBdelete_template_items *
1861 * *
1862 * Purpose: delete template items from host *
1863 * *
1864 * Parameters: hostid - [IN] host identificator from database *
1865 * templateids - [IN] array of template IDs *
1866 * *
1867 * Author: Eugene Grigorjev *
1868 * *
1869 * Comments: !!! Don't forget to sync the code with PHP !!! *
1870 * *
1871 ******************************************************************************/
DBdelete_template_items(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1872 static void DBdelete_template_items(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1873 {
1874 const char *__function_name = "DBdelete_template_items";
1875
1876 char *sql = NULL;
1877 size_t sql_alloc = 0, sql_offset = 0;
1878 zbx_vector_uint64_t itemids;
1879
1880 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1881
1882 zbx_vector_uint64_create(&itemids);
1883
1884 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1885 "select distinct i.itemid"
1886 " from items i,items ti"
1887 " where i.templateid=ti.itemid"
1888 " and i.hostid=" ZBX_FS_UI64
1889 " and",
1890 hostid);
1891 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
1892
1893 DBselect_uint64(sql, &itemids);
1894
1895 DBdelete_items(&itemids);
1896
1897 zbx_vector_uint64_destroy(&itemids);
1898 zbx_free(sql);
1899
1900 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1901 }
1902
1903 /******************************************************************************
1904 * *
1905 * Function: DBdelete_template_applications *
1906 * *
1907 * Purpose: delete host applications that belong to an unlinked template *
1908 * *
1909 * Parameters: hostid - [IN] host identificator from database *
1910 * templateids - [IN] array of template IDs *
1911 * *
1912 * Author: Eugene Grigorjev *
1913 * *
1914 * Comments: !!! Don't forget to sync the code with PHP !!! *
1915 * *
1916 * This function does not remove applications discovered by *
1917 * application prototypes. *
1918 * Use DBdelete_template_discovered_applications() for that. *
1919 * *
1920 ******************************************************************************/
DBdelete_template_applications(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1921 static void DBdelete_template_applications(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1922 {
1923 const char *__function_name = "DBdelete_template_applications";
1924
1925 DB_RESULT result;
1926 DB_ROW row;
1927 char *sql = NULL;
1928 size_t sql_alloc = 0, sql_offset = 0;
1929 zbx_uint64_t id;
1930 zbx_vector_uint64_t applicationids, apptemplateids;
1931
1932 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1933
1934 zbx_vector_uint64_create(&applicationids);
1935 zbx_vector_uint64_create(&apptemplateids);
1936
1937 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1938 "select t.application_templateid,t.applicationid"
1939 " from application_template t,applications a,applications ta"
1940 " where t.applicationid=a.applicationid"
1941 " and t.templateid=ta.applicationid"
1942 " and a.hostid=" ZBX_FS_UI64
1943 " and a.flags=%d"
1944 " and",
1945 hostid, ZBX_FLAG_DISCOVERY_NORMAL);
1946 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ta.hostid", templateids->values, templateids->values_num);
1947
1948 result = DBselect("%s", sql);
1949
1950 while (NULL != (row = DBfetch(result)))
1951 {
1952 ZBX_STR2UINT64(id, row[0]);
1953 zbx_vector_uint64_append(&apptemplateids, id);
1954
1955 ZBX_STR2UINT64(id, row[1]);
1956 zbx_vector_uint64_append(&applicationids, id);
1957 }
1958 DBfree_result(result);
1959
1960 if (0 != apptemplateids.values_num)
1961 {
1962 zbx_vector_uint64_sort(&apptemplateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1963
1964 zbx_vector_uint64_sort(&applicationids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1965 zbx_vector_uint64_uniq(&applicationids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1966
1967 sql_offset = 0;
1968 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from application_template where");
1969 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "application_templateid",
1970 apptemplateids.values, apptemplateids.values_num);
1971
1972 DBexecute("%s", sql);
1973
1974 DBdelete_applications(&applicationids);
1975 }
1976
1977 zbx_vector_uint64_destroy(&apptemplateids);
1978 zbx_vector_uint64_destroy(&applicationids);
1979 zbx_free(sql);
1980
1981 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1982 }
1983
1984 /******************************************************************************
1985 * *
1986 * Function: DBdelete_template_discovered_applications *
1987 * *
1988 * Purpose: delete host applications that belong to an unlinked template *
1989 * *
1990 * Parameters: hostid - [IN] host identificator from database *
1991 * templateids - [IN] array of template IDs *
1992 * *
1993 * Comments: !!! Don't forget to sync the code with PHP !!! *
1994 * *
1995 ******************************************************************************/
DBdelete_template_discovered_applications(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)1996 static void DBdelete_template_discovered_applications(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
1997 {
1998 const char *__function_name = "DBdelete_template_discovered_applications";
1999
2000 DB_RESULT result;
2001 DB_ROW row;
2002 char *sql = NULL;
2003 size_t sql_alloc = 0, sql_offset = 0;
2004 zbx_uint64_t id;
2005 zbx_vector_uint64_t applicationids, lld_ruleids;
2006 int index;
2007
2008 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2009
2010 zbx_vector_uint64_create(&applicationids);
2011 zbx_vector_uint64_create(&lld_ruleids);
2012
2013 /* get the discovery rules */
2014
2015 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2016 "select i.itemid from items i"
2017 " left join items ti"
2018 " on i.templateid=ti.itemid"
2019 " where i.hostid=" ZBX_FS_UI64
2020 " and i.flags=%d"
2021 " and",
2022 hostid, ZBX_FLAG_DISCOVERY_RULE);
2023 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
2024
2025 DBselect_uint64(sql, &lld_ruleids);
2026
2027 if (0 == lld_ruleids.values_num)
2028 goto out;
2029
2030 /* get the applications discovered by those rules */
2031
2032 sql_offset = 0;
2033 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2034 "select ad.applicationid"
2035 " from application_discovery ad"
2036 " left join application_prototype ap"
2037 " on ap.application_prototypeid=ad.application_prototypeid"
2038 " where");
2039 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ap.itemid", lld_ruleids.values, lld_ruleids.values_num);
2040
2041 zbx_vector_uint64_clear(&applicationids);
2042 DBselect_uint64(sql, &applicationids);
2043
2044 if (0 == applicationids.values_num)
2045 goto out;
2046
2047 /* check if the applications are not discovered by other discovery rules */
2048
2049 sql_offset = 0;
2050 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2051 "select ad.applicationid"
2052 " from application_discovery ad"
2053 " left join application_prototype ap"
2054 " on ad.application_prototypeid=ap.application_prototypeid"
2055 " where not");
2056 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ap.itemid", lld_ruleids.values, lld_ruleids.values_num);
2057 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and");
2058 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ad.applicationid", applicationids.values,
2059 applicationids.values_num);
2060
2061 result = DBselect("%s", sql);
2062
2063 while (NULL != (row = DBfetch(result)))
2064 {
2065 ZBX_STR2UINT64(id, row[0]);
2066
2067 if (FAIL != (index = zbx_vector_uint64_bsearch(&applicationids, id, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2068 zbx_vector_uint64_remove(&applicationids, index);
2069 }
2070 DBfree_result(result);
2071
2072 if (0 == applicationids.values_num)
2073 goto out;
2074
2075 /* discovered applications must be always removed, that's why we are */
2076 /* doing it directly instead of using DBdelete_applications() */
2077 sql_offset = 0;
2078 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from applications where");
2079 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "applicationid", applicationids.values
2080 , applicationids.values_num);
2081 DBexecute("%s", sql);
2082 out:
2083 zbx_vector_uint64_destroy(&lld_ruleids);
2084 zbx_vector_uint64_destroy(&applicationids);
2085 zbx_free(sql);
2086
2087 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2088 }
2089
2090 /******************************************************************************
2091 * *
2092 * Function: DBcopy_trigger_to_host *
2093 * *
2094 * Purpose: copy specified trigger to host *
2095 * *
2096 * Parameters: new_triggerid - [OUT] id of new trigger created based on *
2097 * template trigger *
2098 * cur_triggerid - [OUT] id of existing trigger that was linked *
2099 * to the template trigger *
2100 * hostid - host identificator from database *
2101 * triggerid - trigger identificator from database *
2102 * description - trigger description *
2103 * expression - trigger expression *
2104 * recovery_expression - trigger recovery expression *
2105 * recovery_mode - trigger recovery mode *
2106 * status - trigger status *
2107 * type - trigger type *
2108 * priority - trigger priority *
2109 * comments - trigger comments *
2110 * url - trigger url *
2111 * *
2112 * Return value: upon successful completion return SUCCEED *
2113 * *
2114 ******************************************************************************/
DBcopy_trigger_to_host(zbx_uint64_t * new_triggerid,zbx_uint64_t * cur_triggerid,zbx_uint64_t hostid,zbx_uint64_t triggerid,const char * description,const char * expression,const char * recovery_expression,unsigned char recovery_mode,unsigned char status,unsigned char type,unsigned char priority,const char * comments,const char * url,unsigned char flags,unsigned char correlation_mode,const char * correlation_tag,unsigned char manual_close)2115 static int DBcopy_trigger_to_host(zbx_uint64_t *new_triggerid, zbx_uint64_t *cur_triggerid, zbx_uint64_t hostid,
2116 zbx_uint64_t triggerid, const char *description, const char *expression,
2117 const char *recovery_expression, unsigned char recovery_mode, unsigned char status, unsigned char type,
2118 unsigned char priority, const char *comments, const char *url, unsigned char flags,
2119 unsigned char correlation_mode, const char *correlation_tag, unsigned char manual_close)
2120 {
2121 DB_RESULT result;
2122 DB_ROW row;
2123 char *sql = NULL;
2124 size_t sql_alloc = 256, sql_offset = 0;
2125 zbx_uint64_t itemid, h_triggerid, functionid;
2126 char *old_expression = NULL,
2127 *new_expression = NULL,
2128 *expression_esc = NULL,
2129 *new_recovery_expression = NULL,
2130 *recovery_expression_esc = NULL,
2131 search[MAX_ID_LEN + 3],
2132 replace[MAX_ID_LEN + 3],
2133 *description_esc = NULL,
2134 *comments_esc = NULL,
2135 *url_esc = NULL,
2136 *function_esc = NULL,
2137 *parameter_esc = NULL,
2138 *correlation_tag_esc;
2139 int res = FAIL;
2140
2141 sql = (char *)zbx_malloc(sql, sql_alloc);
2142
2143 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
2144
2145 description_esc = DBdyn_escape_string(description);
2146 correlation_tag_esc = DBdyn_escape_string(correlation_tag);
2147
2148 result = DBselect(
2149 "select distinct t.triggerid,t.expression,t.recovery_expression"
2150 " from triggers t,functions f,items i"
2151 " where t.triggerid=f.triggerid"
2152 " and f.itemid=i.itemid"
2153 " and t.templateid is null"
2154 " and i.hostid=" ZBX_FS_UI64
2155 " and t.description='%s'",
2156 hostid, description_esc);
2157
2158 while (NULL != (row = DBfetch(result)))
2159 {
2160 ZBX_STR2UINT64(h_triggerid, row[0]);
2161
2162 if (SUCCEED != DBcmp_triggers(triggerid, expression, recovery_expression,
2163 h_triggerid, row[1], row[2]))
2164 continue;
2165
2166 /* link not linked trigger with same description and expression */
2167 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2168 "update triggers"
2169 " set templateid=" ZBX_FS_UI64
2170 ",flags=%d"
2171 ",recovery_mode=%d"
2172 ",correlation_mode=%d"
2173 ",correlation_tag='%s'"
2174 ",manual_close=%d"
2175 " where triggerid=" ZBX_FS_UI64 ";\n",
2176 triggerid, (int)flags, (int)recovery_mode, (int)correlation_mode, correlation_tag_esc,
2177 (int)manual_close, h_triggerid);
2178
2179 *new_triggerid = 0;
2180 *cur_triggerid = h_triggerid;
2181
2182 res = SUCCEED;
2183 break;
2184 }
2185 DBfree_result(result);
2186
2187 /* create trigger if no updated triggers */
2188 if (SUCCEED != res)
2189 {
2190 res = SUCCEED;
2191
2192 *new_triggerid = DBget_maxid("triggers");
2193 *cur_triggerid = 0;
2194 new_expression = zbx_strdup(NULL, expression);
2195 new_recovery_expression = zbx_strdup(NULL, recovery_expression);
2196
2197 comments_esc = DBdyn_escape_string(comments);
2198 url_esc = DBdyn_escape_string(url);
2199
2200 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2201 "insert into triggers"
2202 " (triggerid,description,priority,status,"
2203 "comments,url,type,value,state,templateid,flags,recovery_mode,"
2204 "correlation_mode,correlation_tag,manual_close)"
2205 " values (" ZBX_FS_UI64 ",'%s',%d,%d,"
2206 "'%s','%s',%d,%d,%d," ZBX_FS_UI64 ",%d,%d,"
2207 "%d,'%s',%d);\n",
2208 *new_triggerid, description_esc, (int)priority, (int)status, comments_esc,
2209 url_esc, (int)type, TRIGGER_VALUE_OK, TRIGGER_STATE_NORMAL, triggerid,
2210 (int)flags, (int)recovery_mode, (int)correlation_mode, correlation_tag_esc,
2211 (int)manual_close);
2212
2213 zbx_free(url_esc);
2214 zbx_free(comments_esc);
2215
2216 /* Loop: functions */
2217 result = DBselect(
2218 "select hi.itemid,tf.functionid,tf.name,tf.parameter,ti.key_"
2219 " from functions tf,items ti"
2220 " left join items hi"
2221 " on hi.key_=ti.key_"
2222 " and hi.hostid=" ZBX_FS_UI64
2223 " where tf.itemid=ti.itemid"
2224 " and tf.triggerid=" ZBX_FS_UI64,
2225 hostid, triggerid);
2226
2227 while (SUCCEED == res && NULL != (row = DBfetch(result)))
2228 {
2229 if (SUCCEED != DBis_null(row[0]))
2230 {
2231 ZBX_STR2UINT64(itemid, row[0]);
2232
2233 functionid = DBget_maxid("functions");
2234
2235 zbx_snprintf(search, sizeof(search), "{%s}", row[1]);
2236 zbx_snprintf(replace, sizeof(replace), "{" ZBX_FS_UI64 "}", functionid);
2237
2238 function_esc = DBdyn_escape_string(row[2]);
2239 parameter_esc = DBdyn_escape_string(row[3]);
2240
2241 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2242 "insert into functions"
2243 " (functionid,itemid,triggerid,name,parameter)"
2244 " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 ","
2245 ZBX_FS_UI64 ",'%s','%s');\n",
2246 functionid, itemid, *new_triggerid,
2247 function_esc, parameter_esc);
2248
2249 old_expression = new_expression;
2250 new_expression = string_replace(new_expression, search, replace);
2251 zbx_free(old_expression);
2252
2253 old_expression = new_recovery_expression;
2254 new_recovery_expression = string_replace(new_recovery_expression, search, replace);
2255 zbx_free(old_expression);
2256
2257 zbx_free(parameter_esc);
2258 zbx_free(function_esc);
2259 }
2260 else
2261 {
2262 zabbix_log(LOG_LEVEL_DEBUG, "Missing similar key '%s'"
2263 " for host [" ZBX_FS_UI64 "]",
2264 row[4], hostid);
2265 res = FAIL;
2266 }
2267 }
2268 DBfree_result(result);
2269
2270 if (SUCCEED == res)
2271 {
2272 expression_esc = DBdyn_escape_field("triggers", "expression", new_expression);
2273 recovery_expression_esc = DBdyn_escape_field("triggers", "recovery_expression",
2274 new_recovery_expression);
2275
2276 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2277 "update triggers"
2278 " set expression='%s',recovery_expression='%s'"
2279 " where triggerid=" ZBX_FS_UI64 ";\n",
2280 expression_esc, recovery_expression_esc, *new_triggerid);
2281
2282 zbx_free(recovery_expression_esc);
2283 zbx_free(expression_esc);
2284 }
2285
2286 zbx_free(new_recovery_expression);
2287 zbx_free(new_expression);
2288 }
2289
2290 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
2291
2292 if (sql_offset > 16) /* In ORACLE always present begin..end; */
2293 DBexecute("%s", sql);
2294
2295 zbx_free(sql);
2296 zbx_free(correlation_tag_esc);
2297 zbx_free(description_esc);
2298
2299 return res;
2300 }
2301
2302 /******************************************************************************
2303 * *
2304 * Function: DBresolve_template_trigger_dependencies *
2305 * *
2306 * Purpose: resolves trigger dependencies for the specified triggers based on *
2307 * host and linked templates *
2308 * *
2309 * Parameters: hostid - [IN] host identificator from database *
2310 * trids - [IN] array of trigger identifiers from database *
2311 * trids_num - [IN] trigger count in trids array *
2312 * links - [OUT] pairs of trigger dependencies (down,up) *
2313 * *
2314 ******************************************************************************/
DBresolve_template_trigger_dependencies(zbx_uint64_t hostid,const zbx_uint64_t * trids,int trids_num,zbx_vector_uint64_pair_t * links)2315 static void DBresolve_template_trigger_dependencies(zbx_uint64_t hostid, const zbx_uint64_t *trids,
2316 int trids_num, zbx_vector_uint64_pair_t *links)
2317 {
2318 DB_RESULT result;
2319 DB_ROW row;
2320 zbx_uint64_pair_t map_id, dep_list_id;
2321 char *sql = NULL;
2322 size_t sql_alloc = 512, sql_offset;
2323 zbx_vector_uint64_pair_t dep_list_ids, map_ids;
2324 zbx_vector_uint64_t all_templ_ids;
2325 zbx_uint64_t templateid_down, templateid_up,
2326 triggerid_down, triggerid_up,
2327 hst_triggerid, tpl_triggerid;
2328 int i, j;
2329
2330 zbx_vector_uint64_create(&all_templ_ids);
2331 zbx_vector_uint64_pair_create(&dep_list_ids);
2332 zbx_vector_uint64_pair_create(links);
2333 sql = (char *)zbx_malloc(sql, sql_alloc);
2334
2335 sql_offset = 0;
2336 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2337 "select distinct td.triggerid_down,td.triggerid_up"
2338 " from triggers t,trigger_depends td"
2339 " where t.templateid in (td.triggerid_up,td.triggerid_down) and");
2340 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid", trids, trids_num);
2341
2342 result = DBselect("%s", sql);
2343
2344 while (NULL != (row = DBfetch(result)))
2345 {
2346 ZBX_STR2UINT64(dep_list_id.first, row[0]);
2347 ZBX_STR2UINT64(dep_list_id.second, row[1]);
2348 zbx_vector_uint64_pair_append(&dep_list_ids, dep_list_id);
2349 zbx_vector_uint64_append(&all_templ_ids, dep_list_id.first);
2350 zbx_vector_uint64_append(&all_templ_ids, dep_list_id.second);
2351 }
2352 DBfree_result(result);
2353
2354 if (0 == dep_list_ids.values_num) /* not all trigger template have a dependency trigger */
2355 {
2356 zbx_vector_uint64_destroy(&all_templ_ids);
2357 zbx_vector_uint64_pair_destroy(&dep_list_ids);
2358 zbx_free(sql);
2359 return;
2360 }
2361
2362 zbx_vector_uint64_pair_create(&map_ids);
2363 zbx_vector_uint64_sort(&all_templ_ids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2364 zbx_vector_uint64_uniq(&all_templ_ids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2365
2366 sql_offset = 0;
2367 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2368 "select t.triggerid,t.templateid"
2369 " from triggers t,functions f,items i"
2370 " where t.triggerid=f.triggerid"
2371 " and f.itemid=i.itemid"
2372 " and i.hostid=" ZBX_FS_UI64
2373 " and",
2374 hostid);
2375 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.templateid", all_templ_ids.values,
2376 all_templ_ids.values_num);
2377
2378 result = DBselect("%s", sql);
2379
2380 while (NULL != (row = DBfetch(result)))
2381 {
2382 ZBX_STR2UINT64(map_id.first, row[0]);
2383 ZBX_DBROW2UINT64(map_id.second, row[1]);
2384 zbx_vector_uint64_pair_append(&map_ids, map_id);
2385 }
2386 DBfree_result(result);
2387
2388 zbx_free(sql);
2389 zbx_vector_uint64_destroy(&all_templ_ids);
2390
2391 for (i = 0; i < dep_list_ids.values_num; i++)
2392 {
2393 templateid_down = dep_list_ids.values[i].first;
2394 templateid_up = dep_list_ids.values[i].second;
2395
2396 /* Convert template ids to corresponding trigger ids. */
2397 /* If template trigger depends on host trigger rather than */
2398 /* template trigger then up id conversion will fail and the */
2399 /* original value (host trigger id) will be used as intended. */
2400 triggerid_down = 0;
2401 triggerid_up = templateid_up;
2402
2403 for (j = 0; j < map_ids.values_num; j++)
2404 {
2405 hst_triggerid = map_ids.values[j].first;
2406 tpl_triggerid = map_ids.values[j].second;
2407
2408 if (tpl_triggerid == templateid_down)
2409 triggerid_down = hst_triggerid;
2410
2411 if (tpl_triggerid == templateid_up)
2412 triggerid_up = hst_triggerid;
2413 }
2414
2415 if (0 != triggerid_down)
2416 {
2417 zbx_uint64_pair_t link = {triggerid_down, triggerid_up};
2418
2419 zbx_vector_uint64_pair_append(links, link);
2420 }
2421 }
2422
2423 zbx_vector_uint64_pair_destroy(&map_ids);
2424 zbx_vector_uint64_pair_destroy(&dep_list_ids);
2425 }
2426
2427 /******************************************************************************
2428 * *
2429 * Function: DBadd_template_dependencies_for_new_triggers *
2430 * *
2431 * Purpose: update trigger dependencies for specified host *
2432 * *
2433 * Parameters: hostid - [IN] host identificator from database *
2434 * trids - [IN] array of trigger identifiers from database *
2435 * trids_num - [IN] trigger count in trids array *
2436 * *
2437 * Return value: upon successful completion return SUCCEED *
2438 * *
2439 * Author: Eugene Grigorjev *
2440 * *
2441 * Comments: !!! Don't forget to sync the code with PHP !!! *
2442 * *
2443 ******************************************************************************/
DBadd_template_dependencies_for_new_triggers(zbx_uint64_t hostid,zbx_uint64_t * trids,int trids_num)2444 static int DBadd_template_dependencies_for_new_triggers(zbx_uint64_t hostid, zbx_uint64_t *trids, int trids_num)
2445 {
2446 int i;
2447 zbx_uint64_t triggerdepid;
2448 zbx_db_insert_t db_insert;
2449 zbx_vector_uint64_pair_t links;
2450
2451 if (0 == trids_num)
2452 return SUCCEED;
2453
2454 DBresolve_template_trigger_dependencies(hostid, trids, trids_num, &links);
2455
2456 if (0 < links.values_num)
2457 {
2458 triggerdepid = DBget_maxid_num("trigger_depends", links.values_num);
2459
2460 zbx_db_insert_prepare(&db_insert, "trigger_depends", "triggerdepid", "triggerid_down", "triggerid_up",
2461 NULL);
2462
2463 for (i = 0; i < links.values_num; i++)
2464 {
2465 zbx_db_insert_add_values(&db_insert, triggerdepid++, links.values[i].first,
2466 links.values[i].second);
2467 }
2468
2469 zbx_db_insert_execute(&db_insert);
2470 zbx_db_insert_clean(&db_insert);
2471 }
2472
2473 zbx_vector_uint64_pair_destroy(&links);
2474
2475 return SUCCEED;
2476 }
2477
2478 /******************************************************************************
2479 * *
2480 * Function: DBcopy_template_trigger_tags *
2481 * *
2482 * Purpose: copies tags from template triggers to created/linked triggers *
2483 * *
2484 * Parameters: new_triggerids - the created trigger ids *
2485 * cur_triggerids - the linked trigfer ids *
2486 * *
2487 * Return value: upon successful completion return SUCCEED *
2488 * *
2489 ******************************************************************************/
DBcopy_template_trigger_tags(const zbx_vector_uint64_t * new_triggerids,const zbx_vector_uint64_t * cur_triggerids)2490 static int DBcopy_template_trigger_tags(const zbx_vector_uint64_t *new_triggerids,
2491 const zbx_vector_uint64_t *cur_triggerids)
2492 {
2493 DB_RESULT result;
2494 DB_ROW row;
2495 char *sql = NULL;
2496 size_t sql_alloc = 0, sql_offset = 0;
2497 int i;
2498 zbx_vector_uint64_t triggerids;
2499 zbx_uint64_t triggerid;
2500 zbx_db_insert_t db_insert;
2501
2502 if (0 == new_triggerids->values_num && 0 == cur_triggerids->values_num)
2503 return SUCCEED;
2504
2505 zbx_vector_uint64_create(&triggerids);
2506 zbx_vector_uint64_reserve(&triggerids, new_triggerids->values_num + cur_triggerids->values_num);
2507
2508 if (0 != cur_triggerids->values_num)
2509 {
2510 /* remove tags from host triggers that were linking to template triggers */
2511 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from trigger_tag where");
2512 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "triggerid", cur_triggerids->values,
2513 cur_triggerids->values_num);
2514 DBexecute("%s", sql);
2515
2516 sql_offset = 0;
2517
2518 for (i = 0; i < cur_triggerids->values_num; i++)
2519 zbx_vector_uint64_append(&triggerids, cur_triggerids->values[i]);
2520 }
2521
2522 for (i = 0; i < new_triggerids->values_num; i++)
2523 zbx_vector_uint64_append(&triggerids, new_triggerids->values[i]);
2524
2525 zbx_vector_uint64_sort(&triggerids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2526
2527 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
2528 "select t.triggerid,tt.tag,tt.value"
2529 " from trigger_tag tt,triggers t"
2530 " where tt.triggerid=t.templateid"
2531 " and");
2532
2533 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.triggerid", triggerids.values, triggerids.values_num);
2534
2535 result = DBselect("%s", sql);
2536
2537 zbx_db_insert_prepare(&db_insert, "trigger_tag", "triggertagid", "triggerid", "tag", "value", NULL);
2538
2539 while (NULL != (row = DBfetch(result)))
2540 {
2541 ZBX_STR2UINT64(triggerid, row[0]);
2542
2543 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), triggerid, row[1], row[2]);
2544 }
2545 DBfree_result(result);
2546
2547 zbx_free(sql);
2548
2549 zbx_db_insert_autoincrement(&db_insert, "triggertagid");
2550 zbx_db_insert_execute(&db_insert);
2551 zbx_db_insert_clean(&db_insert);
2552
2553 zbx_vector_uint64_destroy(&triggerids);
2554
2555 return SUCCEED;
2556 }
2557
2558 /******************************************************************************
2559 * *
2560 * Function: get_templates_by_hostid *
2561 * *
2562 * Description: Retrieve already linked templates for specified host *
2563 * *
2564 * Parameters: hostid - [IN] host identificator from database *
2565 * templateids - [IN] array of template IDs *
2566 * *
2567 * Author: Alexander Vladishev *
2568 * *
2569 ******************************************************************************/
get_templates_by_hostid(zbx_uint64_t hostid,zbx_vector_uint64_t * templateids)2570 static void get_templates_by_hostid(zbx_uint64_t hostid, zbx_vector_uint64_t *templateids)
2571 {
2572 DB_RESULT result;
2573 DB_ROW row;
2574 zbx_uint64_t templateid;
2575
2576 result = DBselect(
2577 "select templateid"
2578 " from hosts_templates"
2579 " where hostid=" ZBX_FS_UI64,
2580 hostid);
2581
2582 while (NULL != (row = DBfetch(result)))
2583 {
2584 ZBX_STR2UINT64(templateid, row[0]);
2585 zbx_vector_uint64_append(templateids, templateid);
2586 }
2587 DBfree_result(result);
2588
2589 zbx_vector_uint64_sort(templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
2590 }
2591
2592 /******************************************************************************
2593 * *
2594 * Function: DBdelete_template_elements *
2595 * *
2596 * Purpose: delete template elements from host *
2597 * *
2598 * Parameters: hostid - [IN] host identificator from database *
2599 * del_templateids - [IN] array of template IDs *
2600 * *
2601 * Author: Eugene Grigorjev *
2602 * *
2603 * Comments: !!! Don't forget to sync the code with PHP !!! *
2604 * *
2605 ******************************************************************************/
DBdelete_template_elements(zbx_uint64_t hostid,zbx_vector_uint64_t * del_templateids,char ** error)2606 int DBdelete_template_elements(zbx_uint64_t hostid, zbx_vector_uint64_t *del_templateids, char **error)
2607 {
2608 const char *__function_name = "DBdelete_template_elements";
2609
2610 char *sql = NULL, err[MAX_STRING_LEN];
2611 size_t sql_alloc = 128, sql_offset = 0;
2612 zbx_vector_uint64_t templateids;
2613 int i, index, res = SUCCEED;
2614
2615 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2616
2617 zbx_vector_uint64_create(&templateids);
2618
2619 get_templates_by_hostid(hostid, &templateids);
2620
2621 for (i = 0; i < del_templateids->values_num; i++)
2622 {
2623 if (FAIL == (index = zbx_vector_uint64_bsearch(&templateids, del_templateids->values[i],
2624 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
2625 {
2626 /* template already unlinked */
2627 zbx_vector_uint64_remove(del_templateids, i--);
2628 }
2629 else
2630 zbx_vector_uint64_remove(&templateids, index);
2631 }
2632
2633 /* all templates already unlinked */
2634 if (0 == del_templateids->values_num)
2635 goto clean;
2636
2637 if (SUCCEED != (res = validate_linked_templates(&templateids, err, sizeof(err))))
2638 {
2639 *error = zbx_strdup(NULL, err);
2640 goto clean;
2641 }
2642
2643 DBdelete_template_httptests(hostid, del_templateids);
2644 DBdelete_template_graphs(hostid, del_templateids);
2645 DBdelete_template_triggers(hostid, del_templateids);
2646 DBdelete_template_host_prototypes(hostid, del_templateids);
2647
2648 /* Removing items will remove discovery rules and all application discovery records */
2649 /* related to them. Because of that discovered applications must be removed before */
2650 /* removing items. */
2651 DBdelete_template_discovered_applications(hostid, del_templateids);
2652 DBdelete_template_items(hostid, del_templateids);
2653
2654 /* normal applications must be removed after items are removed to cleanup */
2655 /* unlinked applications */
2656 DBdelete_template_applications(hostid, del_templateids);
2657
2658 sql = (char *)zbx_malloc(sql, sql_alloc);
2659
2660 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2661 "delete from hosts_templates"
2662 " where hostid=" ZBX_FS_UI64
2663 " and",
2664 hostid);
2665 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "templateid",
2666 del_templateids->values, del_templateids->values_num);
2667 DBexecute("%s", sql);
2668
2669 zbx_free(sql);
2670 clean:
2671 zbx_vector_uint64_destroy(&templateids);
2672
2673 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res));
2674
2675 return res;
2676 }
2677
2678 typedef struct
2679 {
2680 zbx_uint64_t applicationid;
2681 char *name;
2682 zbx_vector_uint64_t templateids;
2683 }
2684 zbx_application_t;
2685
zbx_application_clean(zbx_application_t * application)2686 static void zbx_application_clean(zbx_application_t *application)
2687 {
2688 zbx_vector_uint64_destroy(&application->templateids);
2689 zbx_free(application->name);
2690 zbx_free(application);
2691 }
2692
2693 /******************************************************************************
2694 * *
2695 * Function: DBcopy_template_application_prototypes *
2696 * *
2697 * Purpose: copy application prototypes from templates to host *
2698 * *
2699 * Parameters: hostid - [IN] host id *
2700 * templateids - [IN] array of template IDs *
2701 * *
2702 * Comments: The host items must be already copied. *
2703 * *
2704 ******************************************************************************/
DBcopy_template_application_prototypes(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)2705 static void DBcopy_template_application_prototypes(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
2706 {
2707 const char *__function_name = "DBcopy_template_application_prototypes";
2708 DB_RESULT result;
2709 DB_ROW row;
2710 char *sql = NULL;
2711 size_t sql_alloc = 0, sql_offset = 0;
2712 zbx_db_insert_t db_insert;
2713
2714 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2715
2716 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2717 "select ap.application_prototypeid,ap.name,i_t.itemid"
2718 " from application_prototype ap"
2719 " left join items i"
2720 " on ap.itemid=i.itemid"
2721 " left join items i_t"
2722 " on i_t.templateid=i.itemid"
2723 " where i.flags=%d"
2724 " and i_t.hostid=" ZBX_FS_UI64
2725 " and",
2726 ZBX_FLAG_DISCOVERY_RULE, hostid);
2727
2728 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", templateids->values, templateids->values_num);
2729
2730 result = DBselect("%s", sql);
2731
2732 zbx_free(sql);
2733
2734 if (NULL == (row = DBfetch(result)))
2735 goto out;
2736
2737 zbx_db_insert_prepare(&db_insert, "application_prototype", "application_prototypeid", "itemid", "templateid",
2738 "name", NULL);
2739 do
2740 {
2741 zbx_uint64_t application_prototypeid, lld_ruleid;
2742
2743 ZBX_STR2UINT64(application_prototypeid, row[0]);
2744 ZBX_STR2UINT64(lld_ruleid, row[2]);
2745
2746 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), lld_ruleid, application_prototypeid, row[1]);
2747 }
2748 while (NULL != (row = DBfetch(result)));
2749
2750 zbx_db_insert_autoincrement(&db_insert, "application_prototypeid");
2751 zbx_db_insert_execute(&db_insert);
2752 zbx_db_insert_clean(&db_insert);
2753 out:
2754 DBfree_result(result);
2755
2756 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2757 }
2758
2759 /******************************************************************************
2760 * *
2761 * Function: DBcopy_template_item_application_prototypes *
2762 * *
2763 * Purpose: copy application prototypes from templates to host *
2764 * *
2765 * Parameters: hostid - [IN] host id *
2766 * templateids - [IN] array of template IDs *
2767 * *
2768 * Comments: The host items and application prototypes must be already copied.*
2769 * *
2770 ******************************************************************************/
DBcopy_template_item_application_prototypes(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)2771 static void DBcopy_template_item_application_prototypes(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
2772 {
2773 const char *__function_name = "DBcopy_template_item_application_prototypes";
2774 DB_RESULT result;
2775 DB_ROW row;
2776 char *sql = NULL;
2777 size_t sql_alloc = 0, sql_offset = 0;
2778 zbx_db_insert_t db_insert;
2779
2780 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2781
2782 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2783 "select ap.application_prototypeid,i.itemid"
2784 " from items i_ap,item_application_prototype iap"
2785 " left join application_prototype ap"
2786 " on ap.templateid=iap.application_prototypeid"
2787 " left join items i_t"
2788 " on i_t.itemid=iap.itemid"
2789 " left join items i"
2790 " on i.templateid=i_t.itemid"
2791 " where i.hostid=" ZBX_FS_UI64
2792 " and i_ap.itemid=ap.itemid"
2793 " and i_ap.hostid=" ZBX_FS_UI64
2794 " and",
2795 hostid, hostid);
2796
2797 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i_t.hostid", templateids->values,
2798 templateids->values_num);
2799
2800 result = DBselect("%s", sql);
2801
2802 zbx_free(sql);
2803
2804 if (NULL == (row = DBfetch(result)))
2805 goto out;
2806
2807 zbx_db_insert_prepare(&db_insert, "item_application_prototype", "item_application_prototypeid",
2808 "application_prototypeid", "itemid", NULL);
2809
2810 do
2811 {
2812 zbx_uint64_t application_prototypeid, itemid;
2813
2814 ZBX_STR2UINT64(application_prototypeid, row[0]);
2815 ZBX_STR2UINT64(itemid, row[1]);
2816
2817 zbx_db_insert_add_values(&db_insert, __UINT64_C(0), application_prototypeid, itemid);
2818 }
2819 while (NULL != (row = DBfetch(result)));
2820
2821 zbx_db_insert_autoincrement(&db_insert, "item_application_prototypeid");
2822 zbx_db_insert_execute(&db_insert);
2823 zbx_db_insert_clean(&db_insert);
2824 out:
2825 DBfree_result(result);
2826
2827 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2828 }
2829
2830 /******************************************************************************
2831 * *
2832 * Function: DBcopy_template_applications *
2833 * *
2834 * Purpose: copy applications from templates to host *
2835 * *
2836 * Parameters: hostid - [IN] host id *
2837 * templateids - [IN] array of template IDs *
2838 * *
2839 ******************************************************************************/
DBcopy_template_applications(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)2840 static void DBcopy_template_applications(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
2841 {
2842 const char *__function_name = "DBcopy_template_applications";
2843 DB_RESULT result;
2844 DB_ROW row;
2845 char *sql = NULL;
2846 size_t sql_alloc = ZBX_KIBIBYTE, sql_offset = 0;
2847 zbx_application_t *application = NULL;
2848 zbx_vector_ptr_t applications;
2849 int i, j, new_applications = 0, new_application_templates = 0;
2850
2851 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2852
2853 zbx_vector_ptr_create(&applications);
2854
2855 sql = (char *)zbx_malloc(sql, sql_alloc);
2856
2857 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
2858 "select applicationid,hostid,name"
2859 " from applications"
2860 " where hostid=" ZBX_FS_UI64
2861 " or", hostid);
2862 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", templateids->values, templateids->values_num);
2863
2864 result = DBselect("%s", sql);
2865
2866 while (NULL != (row = DBfetch(result)))
2867 {
2868 zbx_uint64_t db_applicationid, db_hostid;
2869
2870 ZBX_STR2UINT64(db_applicationid, row[0]);
2871 ZBX_STR2UINT64(db_hostid, row[1]);
2872
2873 for (i = 0; i < applications.values_num; i++)
2874 {
2875 application = (zbx_application_t *)applications.values[i];
2876
2877 if (0 == strcmp(application->name, row[2]))
2878 break;
2879 }
2880
2881 if (i == applications.values_num)
2882 {
2883 application = (zbx_application_t *)zbx_malloc(NULL, sizeof(zbx_application_t));
2884
2885 application->applicationid = 0;
2886 application->name = zbx_strdup(NULL, row[2]);
2887 zbx_vector_uint64_create(&application->templateids);
2888
2889 zbx_vector_ptr_append(&applications, application);
2890 }
2891
2892 if (db_hostid == hostid)
2893 application->applicationid = db_applicationid;
2894 else
2895 zbx_vector_uint64_append(&application->templateids, db_applicationid);
2896 }
2897 DBfree_result(result);
2898
2899 for (i = 0; i < applications.values_num; i++)
2900 {
2901 application = (zbx_application_t *)applications.values[i];
2902
2903 if (0 == application->applicationid)
2904 new_applications++;
2905
2906 new_application_templates += application->templateids.values_num;
2907 }
2908
2909 if (0 != new_applications)
2910 {
2911 zbx_uint64_t applicationid;
2912 zbx_db_insert_t db_insert;
2913
2914 applicationid = DBget_maxid_num("applications", new_applications);
2915
2916 zbx_db_insert_prepare(&db_insert, "applications", "applicationid", "hostid", "name", NULL);
2917
2918 for (i = 0; i < applications.values_num; i++)
2919 {
2920 application = (zbx_application_t *)applications.values[i];
2921
2922 if (0 != application->applicationid)
2923 continue;
2924
2925 zbx_db_insert_add_values(&db_insert, applicationid, hostid, application->name);
2926
2927 application->applicationid = applicationid++;
2928 }
2929
2930 zbx_db_insert_execute(&db_insert);
2931 zbx_db_insert_clean(&db_insert);
2932 }
2933
2934 if (0 != new_application_templates)
2935 {
2936 zbx_uint64_t application_templateid;
2937 zbx_db_insert_t db_insert;
2938
2939 application_templateid = DBget_maxid_num("application_template", new_application_templates);
2940
2941 zbx_db_insert_prepare(&db_insert,"application_template", "application_templateid", "applicationid",
2942 "templateid", NULL);
2943
2944 for (i = 0; i < applications.values_num; i++)
2945 {
2946 application = (zbx_application_t *)applications.values[i];
2947
2948 for (j = 0; j < application->templateids.values_num; j++)
2949 {
2950 zbx_db_insert_add_values(&db_insert, application_templateid++,
2951 application->applicationid, application->templateids.values[j]);
2952 }
2953 }
2954
2955 zbx_db_insert_execute(&db_insert);
2956 zbx_db_insert_clean(&db_insert);
2957 }
2958
2959 zbx_vector_ptr_clear_ext(&applications, (zbx_clean_func_t)zbx_application_clean);
2960 zbx_vector_ptr_destroy(&applications);
2961 zbx_free(sql);
2962
2963 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2964 }
2965
2966 typedef struct
2967 {
2968 zbx_uint64_t group_prototypeid;
2969 zbx_uint64_t groupid;
2970 zbx_uint64_t templateid; /* reference to parent group_prototypeid */
2971 char *name;
2972 }
2973 zbx_group_prototype_t;
2974
DBgroup_prototype_clean(zbx_group_prototype_t * group_prototype)2975 static void DBgroup_prototype_clean(zbx_group_prototype_t *group_prototype)
2976 {
2977 zbx_free(group_prototype->name);
2978 zbx_free(group_prototype);
2979 }
2980
DBgroup_prototypes_clean(zbx_vector_ptr_t * group_prototypes)2981 static void DBgroup_prototypes_clean(zbx_vector_ptr_t *group_prototypes)
2982 {
2983 int i;
2984
2985 for (i = 0; i < group_prototypes->values_num; i++)
2986 DBgroup_prototype_clean((zbx_group_prototype_t *)group_prototypes->values[i]);
2987 }
2988
2989 typedef struct
2990 {
2991 zbx_uint64_t templateid; /* link to parent template */
2992 zbx_uint64_t hostid;
2993 zbx_uint64_t itemid; /* discovery rule id */
2994 zbx_vector_uint64_t lnk_templateids; /* list of templates which should be linked */
2995 zbx_vector_ptr_t group_prototypes; /* list of group prototypes */
2996 char *host;
2997 char *name;
2998 unsigned char status;
2999 #define ZBX_FLAG_HPLINK_UPDATE_NAME 0x01
3000 #define ZBX_FLAG_HPLINK_UPDATE_STATUS 0x02
3001 unsigned char flags;
3002 }
3003 zbx_host_prototype_t;
3004
DBhost_prototype_clean(zbx_host_prototype_t * host_prototype)3005 static void DBhost_prototype_clean(zbx_host_prototype_t *host_prototype)
3006 {
3007 zbx_free(host_prototype->name);
3008 zbx_free(host_prototype->host);
3009 DBgroup_prototypes_clean(&host_prototype->group_prototypes);
3010 zbx_vector_ptr_destroy(&host_prototype->group_prototypes);
3011 zbx_vector_uint64_destroy(&host_prototype->lnk_templateids);
3012 zbx_free(host_prototype);
3013 }
3014
DBhost_prototypes_clean(zbx_vector_ptr_t * host_prototypes)3015 static void DBhost_prototypes_clean(zbx_vector_ptr_t *host_prototypes)
3016 {
3017 int i;
3018
3019 for (i = 0; i < host_prototypes->values_num; i++)
3020 DBhost_prototype_clean((zbx_host_prototype_t *)host_prototypes->values[i]);
3021 }
3022
3023 /******************************************************************************
3024 * *
3025 * Function: DBis_regular_host *
3026 * *
3027 * Comments: auxiliary function for DBcopy_template_host_prototypes() *
3028 * *
3029 ******************************************************************************/
DBis_regular_host(zbx_uint64_t hostid)3030 static int DBis_regular_host(zbx_uint64_t hostid)
3031 {
3032 DB_RESULT result;
3033 DB_ROW row;
3034 int ret = FAIL;
3035
3036 result = DBselect("select flags from hosts where hostid=" ZBX_FS_UI64, hostid);
3037
3038 if (NULL != (row = DBfetch(result)))
3039 {
3040 if (0 == atoi(row[0]))
3041 ret = SUCCEED;
3042 }
3043 DBfree_result(result);
3044
3045 return ret;
3046 }
3047
3048 /******************************************************************************
3049 * *
3050 * Function: DBhost_prototypes_make *
3051 * *
3052 * Comments: auxiliary function for DBcopy_template_host_prototypes() *
3053 * *
3054 ******************************************************************************/
DBhost_prototypes_make(zbx_uint64_t hostid,zbx_vector_uint64_t * templateids,zbx_vector_ptr_t * host_prototypes)3055 static void DBhost_prototypes_make(zbx_uint64_t hostid, zbx_vector_uint64_t *templateids,
3056 zbx_vector_ptr_t *host_prototypes)
3057 {
3058 DB_RESULT result;
3059 DB_ROW row;
3060 char *sql = NULL;
3061 size_t sql_alloc = 0, sql_offset = 0;
3062 zbx_vector_uint64_t itemids;
3063 zbx_host_prototype_t *host_prototype;
3064
3065 zbx_vector_uint64_create(&itemids);
3066
3067 /* selects host prototypes from templates */
3068
3069 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3070 "select hi.itemid,th.hostid,th.host,th.name,th.status"
3071 " from items hi,items ti,host_discovery thd,hosts th"
3072 " where hi.templateid=ti.itemid"
3073 " and ti.itemid=thd.parent_itemid"
3074 " and thd.hostid=th.hostid"
3075 " and hi.hostid=" ZBX_FS_UI64
3076 " and",
3077 hostid);
3078 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "ti.hostid", templateids->values, templateids->values_num);
3079
3080 result = DBselect("%s", sql);
3081
3082 while (NULL != (row = DBfetch(result)))
3083 {
3084 host_prototype = (zbx_host_prototype_t *)zbx_malloc(NULL, sizeof(zbx_host_prototype_t));
3085
3086 host_prototype->hostid = 0;
3087 ZBX_STR2UINT64(host_prototype->itemid, row[0]);
3088 ZBX_STR2UINT64(host_prototype->templateid, row[1]);
3089 zbx_vector_uint64_create(&host_prototype->lnk_templateids);
3090 zbx_vector_ptr_create(&host_prototype->group_prototypes);
3091 host_prototype->host = zbx_strdup(NULL, row[2]);
3092 host_prototype->name = zbx_strdup(NULL, row[3]);
3093 host_prototype->status = (unsigned char)atoi(row[4]);
3094 host_prototype->flags = 0;
3095
3096 zbx_vector_ptr_append(host_prototypes, host_prototype);
3097 zbx_vector_uint64_append(&itemids, host_prototype->itemid);
3098 }
3099 DBfree_result(result);
3100
3101 if (0 != host_prototypes->values_num)
3102 {
3103 zbx_uint64_t itemid;
3104 unsigned char status;
3105 int i;
3106
3107 zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3108 zbx_vector_uint64_uniq(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3109
3110 /* selects host prototypes from host */
3111
3112 sql_offset = 0;
3113 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3114 "select i.itemid,h.hostid,h.host,h.name,h.status"
3115 " from items i,host_discovery hd,hosts h"
3116 " where i.itemid=hd.parent_itemid"
3117 " and hd.hostid=h.hostid"
3118 " and i.hostid=" ZBX_FS_UI64
3119 " and",
3120 hostid);
3121 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.itemid", itemids.values, itemids.values_num);
3122
3123 result = DBselect("%s", sql);
3124
3125 while (NULL != (row = DBfetch(result)))
3126 {
3127 ZBX_STR2UINT64(itemid, row[0]);
3128
3129 for (i = 0; i < host_prototypes->values_num; i++)
3130 {
3131 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3132
3133 if (host_prototype->itemid == itemid && 0 == strcmp(host_prototype->host, row[2]))
3134 {
3135 ZBX_STR2UINT64(host_prototype->hostid, row[1]);
3136 if (0 != strcmp(host_prototype->name, row[3]))
3137 host_prototype->flags |= ZBX_FLAG_HPLINK_UPDATE_NAME;
3138 if (host_prototype->status != (status = (unsigned char)atoi(row[4])))
3139 host_prototype->flags |= ZBX_FLAG_HPLINK_UPDATE_STATUS;
3140 break;
3141 }
3142 }
3143 }
3144 DBfree_result(result);
3145 }
3146
3147 zbx_free(sql);
3148
3149 zbx_vector_uint64_destroy(&itemids);
3150
3151 /* sort by templateid */
3152 zbx_vector_ptr_sort(host_prototypes, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
3153 }
3154
3155 /******************************************************************************
3156 * *
3157 * Function: DBhost_prototypes_templates_make *
3158 * *
3159 * Parameters: host_prototypes - [IN/OUT] list of host prototypes *
3160 * should be sorted by templateid *
3161 * del_hosttemplateids - [OUT] list of hosttemplateids which *
3162 * should be deleted *
3163 * *
3164 * Comments: auxiliary function for DBcopy_template_host_prototypes() *
3165 * *
3166 ******************************************************************************/
DBhost_prototypes_templates_make(zbx_vector_ptr_t * host_prototypes,zbx_vector_uint64_t * del_hosttemplateids)3167 static void DBhost_prototypes_templates_make(zbx_vector_ptr_t *host_prototypes,
3168 zbx_vector_uint64_t *del_hosttemplateids)
3169 {
3170 DB_RESULT result;
3171 DB_ROW row;
3172 char *sql = NULL;
3173 size_t sql_alloc = 0, sql_offset = 0;
3174 zbx_vector_uint64_t hostids;
3175 zbx_uint64_t hostid, templateid, hosttemplateid;
3176 zbx_host_prototype_t *host_prototype;
3177 int i;
3178
3179 zbx_vector_uint64_create(&hostids);
3180
3181 /* select list of templates which should be linked to host prototypes */
3182
3183 for (i = 0; i < host_prototypes->values_num; i++)
3184 {
3185 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3186
3187 zbx_vector_uint64_append(&hostids, host_prototype->templateid);
3188 }
3189
3190 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3191 "select hostid,templateid"
3192 " from hosts_templates"
3193 " where");
3194 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
3195 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by hostid,templateid");
3196
3197 result = DBselect("%s", sql);
3198
3199 while (NULL != (row = DBfetch(result)))
3200 {
3201 ZBX_STR2UINT64(hostid, row[0]);
3202 ZBX_STR2UINT64(templateid, row[1]);
3203
3204 if (FAIL == (i = zbx_vector_ptr_bsearch(host_prototypes, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3205 {
3206 THIS_SHOULD_NEVER_HAPPEN;
3207 continue;
3208 }
3209
3210 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3211
3212 zbx_vector_uint64_append(&host_prototype->lnk_templateids, templateid);
3213 }
3214 DBfree_result(result);
3215
3216 /* select list of templates which already linked to host prototypes */
3217
3218 zbx_vector_uint64_clear(&hostids);
3219
3220 for (i = 0; i < host_prototypes->values_num; i++)
3221 {
3222 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3223
3224 if (0 == host_prototype->hostid)
3225 continue;
3226
3227 zbx_vector_uint64_append(&hostids, host_prototype->hostid);
3228 }
3229
3230 if (0 != hostids.values_num)
3231 {
3232 zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3233
3234 sql_offset = 0;
3235 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3236 "select hostid,templateid,hosttemplateid"
3237 " from hosts_templates"
3238 " where");
3239 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
3240 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by hosttemplateid");
3241
3242 result = DBselect("%s", sql);
3243
3244 while (NULL != (row = DBfetch(result)))
3245 {
3246 ZBX_STR2UINT64(hostid, row[0]);
3247 ZBX_STR2UINT64(templateid, row[1]);
3248
3249 for (i = 0; i < host_prototypes->values_num; i++)
3250 {
3251 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3252
3253 if (host_prototype->hostid == hostid)
3254 {
3255 if (FAIL == (i = zbx_vector_uint64_bsearch(&host_prototype->lnk_templateids,
3256 templateid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
3257 {
3258 ZBX_STR2UINT64(hosttemplateid, row[2]);
3259 zbx_vector_uint64_append(del_hosttemplateids, hosttemplateid);
3260 }
3261 else
3262 zbx_vector_uint64_remove(&host_prototype->lnk_templateids, i);
3263
3264 break;
3265 }
3266 }
3267
3268 if (i == host_prototypes->values_num)
3269 THIS_SHOULD_NEVER_HAPPEN;
3270 }
3271 DBfree_result(result);
3272 }
3273
3274 zbx_vector_uint64_destroy(&hostids);
3275
3276 zbx_free(sql);
3277 }
3278
3279 /******************************************************************************
3280 * *
3281 * Function: DBhost_prototypes_groups_make *
3282 * *
3283 * Parameters: host_prototypes - [IN/OUT] list of host prototypes *
3284 * should be sorted by templateid *
3285 * del_group_prototypeids - [OUT] list of group_prototypeid which *
3286 * should be deleted *
3287 * *
3288 * Comments: auxiliary function for DBcopy_template_host_prototypes() *
3289 * *
3290 ******************************************************************************/
DBhost_prototypes_groups_make(zbx_vector_ptr_t * host_prototypes,zbx_vector_uint64_t * del_group_prototypeids)3291 static void DBhost_prototypes_groups_make(zbx_vector_ptr_t *host_prototypes,
3292 zbx_vector_uint64_t *del_group_prototypeids)
3293 {
3294 DB_RESULT result;
3295 DB_ROW row;
3296 char *sql = NULL;
3297 size_t sql_alloc = 0, sql_offset = 0;
3298 zbx_vector_uint64_t hostids;
3299 zbx_uint64_t hostid, groupid, group_prototypeid;
3300 zbx_host_prototype_t *host_prototype;
3301 zbx_group_prototype_t *group_prototype;
3302 int i;
3303
3304 zbx_vector_uint64_create(&hostids);
3305
3306 /* select list of groups which should be linked to host prototypes */
3307
3308 for (i = 0; i < host_prototypes->values_num; i++)
3309 {
3310 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3311
3312 zbx_vector_uint64_append(&hostids, host_prototype->templateid);
3313 }
3314
3315 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3316 "select hostid,name,groupid,group_prototypeid"
3317 " from group_prototype"
3318 " where");
3319 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
3320 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by hostid");
3321
3322 result = DBselect("%s", sql);
3323
3324 while (NULL != (row = DBfetch(result)))
3325 {
3326 ZBX_STR2UINT64(hostid, row[0]);
3327
3328 if (FAIL == (i = zbx_vector_ptr_bsearch(host_prototypes, &hostid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
3329 {
3330 THIS_SHOULD_NEVER_HAPPEN;
3331 continue;
3332 }
3333
3334 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3335
3336 group_prototype = (zbx_group_prototype_t *)zbx_malloc(NULL, sizeof(zbx_group_prototype_t));
3337 group_prototype->group_prototypeid = 0;
3338 group_prototype->name = zbx_strdup(NULL, row[1]);
3339 ZBX_DBROW2UINT64(group_prototype->groupid, row[2]);
3340 ZBX_STR2UINT64(group_prototype->templateid, row[3]);
3341
3342 zbx_vector_ptr_append(&host_prototype->group_prototypes, group_prototype);
3343 }
3344 DBfree_result(result);
3345
3346 /* select list of group prototypes which already linked to host prototypes */
3347
3348 zbx_vector_uint64_clear(&hostids);
3349
3350 for (i = 0; i < host_prototypes->values_num; i++)
3351 {
3352 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3353
3354 if (0 == host_prototype->hostid)
3355 continue;
3356
3357 zbx_vector_uint64_append(&hostids, host_prototype->hostid);
3358 }
3359
3360 if (0 != hostids.values_num)
3361 {
3362 zbx_vector_uint64_sort(&hostids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3363
3364 sql_offset = 0;
3365 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3366 "select hostid,group_prototypeid,groupid,name from group_prototype where");
3367 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids.values, hostids.values_num);
3368 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by group_prototypeid");
3369
3370 result = DBselect("%s", sql);
3371
3372 while (NULL != (row = DBfetch(result)))
3373 {
3374 ZBX_STR2UINT64(hostid, row[0]);
3375
3376 for (i = 0; i < host_prototypes->values_num; i++)
3377 {
3378 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3379
3380 if (host_prototype->hostid == hostid)
3381 {
3382 int k;
3383
3384 ZBX_STR2UINT64(group_prototypeid, row[1]);
3385 ZBX_DBROW2UINT64(groupid, row[2]);
3386
3387 for (k = 0; k < host_prototype->group_prototypes.values_num; k++)
3388 {
3389 group_prototype = (zbx_group_prototype_t *)
3390 host_prototype->group_prototypes.values[k];
3391
3392 if (0 != group_prototype->group_prototypeid)
3393 continue;
3394
3395 if (group_prototype->groupid == groupid &&
3396 0 == strcmp(group_prototype->name, row[3]))
3397 {
3398 group_prototype->group_prototypeid = group_prototypeid;
3399 break;
3400 }
3401 }
3402
3403 if (k == host_prototype->group_prototypes.values_num)
3404 zbx_vector_uint64_append(del_group_prototypeids, group_prototypeid);
3405
3406 break;
3407 }
3408 }
3409
3410 if (i == host_prototypes->values_num)
3411 THIS_SHOULD_NEVER_HAPPEN;
3412 }
3413 DBfree_result(result);
3414 }
3415
3416 zbx_vector_uint64_sort(del_group_prototypeids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
3417
3418 zbx_vector_uint64_destroy(&hostids);
3419 zbx_free(sql);
3420 }
3421
3422 /******************************************************************************
3423 * *
3424 * Function: DBhost_prototypes_save *
3425 * *
3426 * Comments: auxiliary function for DBcopy_template_host_prototypes() *
3427 * *
3428 ******************************************************************************/
DBhost_prototypes_save(zbx_vector_ptr_t * host_prototypes,zbx_vector_uint64_t * del_hosttemplateids)3429 static void DBhost_prototypes_save(zbx_vector_ptr_t *host_prototypes, zbx_vector_uint64_t *del_hosttemplateids)
3430 {
3431 char *sql1 = NULL, *sql2 = NULL, *name_esc;
3432 size_t sql1_alloc = ZBX_KIBIBYTE, sql1_offset = 0,
3433 sql2_alloc = ZBX_KIBIBYTE, sql2_offset = 0;
3434 zbx_host_prototype_t *host_prototype;
3435 zbx_group_prototype_t *group_prototype;
3436 zbx_uint64_t hostid = 0, hosttemplateid = 0, group_prototypeid = 0;
3437 int i, j, new_hosts = 0, new_hosts_templates = 0, new_group_prototypes = 0,
3438 upd_group_prototypes = 0;
3439 zbx_db_insert_t db_insert, db_insert_hdiscovery, db_insert_htemplates, db_insert_gproto;
3440
3441 for (i = 0; i < host_prototypes->values_num; i++)
3442 {
3443 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3444
3445 if (0 == host_prototype->hostid)
3446 new_hosts++;
3447
3448 new_hosts_templates += host_prototype->lnk_templateids.values_num;
3449
3450 for (j = 0; j < host_prototype->group_prototypes.values_num; j++)
3451 {
3452 group_prototype = (zbx_group_prototype_t *)host_prototype->group_prototypes.values[j];
3453
3454 if (0 == group_prototype->group_prototypeid)
3455 new_group_prototypes++;
3456 else
3457 upd_group_prototypes++;
3458 }
3459 }
3460
3461 if (0 != new_hosts)
3462 {
3463 hostid = DBget_maxid_num("hosts", new_hosts);
3464
3465 zbx_db_insert_prepare(&db_insert, "hosts", "hostid", "host", "name", "status", "flags", "templateid",
3466 NULL);
3467
3468 zbx_db_insert_prepare(&db_insert_hdiscovery, "host_discovery", "hostid", "parent_itemid", NULL);
3469 }
3470
3471 if (new_hosts != host_prototypes->values_num || 0 != upd_group_prototypes)
3472 {
3473 sql1 = (char *)zbx_malloc(sql1, sql1_alloc);
3474 DBbegin_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
3475 }
3476
3477 if (0 != new_hosts_templates)
3478 {
3479 hosttemplateid = DBget_maxid_num("hosts_templates", new_hosts_templates);
3480
3481 zbx_db_insert_prepare(&db_insert_htemplates, "hosts_templates", "hosttemplateid", "hostid",
3482 "templateid", NULL);
3483 }
3484
3485 if (0 != del_hosttemplateids->values_num)
3486 {
3487 sql2 = (char *)zbx_malloc(sql2, sql2_alloc);
3488 zbx_strcpy_alloc(&sql2, &sql2_alloc, &sql2_offset, "delete from hosts_templates where");
3489 DBadd_condition_alloc(&sql2, &sql2_alloc, &sql2_offset, "hosttemplateid",
3490 del_hosttemplateids->values, del_hosttemplateids->values_num);
3491 }
3492
3493 if (0 != new_group_prototypes)
3494 {
3495 group_prototypeid = DBget_maxid_num("group_prototype", new_group_prototypes);
3496
3497 zbx_db_insert_prepare(&db_insert_gproto, "group_prototype", "group_prototypeid", "hostid", "name",
3498 "groupid", "templateid", NULL);
3499 }
3500
3501 for (i = 0; i < host_prototypes->values_num; i++)
3502 {
3503 host_prototype = (zbx_host_prototype_t *)host_prototypes->values[i];
3504
3505 if (0 == host_prototype->hostid)
3506 {
3507 host_prototype->hostid = hostid++;
3508
3509 zbx_db_insert_add_values(&db_insert, host_prototype->hostid, host_prototype->host,
3510 host_prototype->name, (int)host_prototype->status,
3511 (int)ZBX_FLAG_DISCOVERY_PROTOTYPE, host_prototype->templateid);
3512
3513 zbx_db_insert_add_values(&db_insert_hdiscovery, host_prototype->hostid, host_prototype->itemid);
3514 }
3515 else
3516 {
3517 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, "update hosts set templateid=" ZBX_FS_UI64,
3518 host_prototype->templateid);
3519 if (0 != (host_prototype->flags & ZBX_FLAG_HPLINK_UPDATE_NAME))
3520 {
3521 name_esc = DBdyn_escape_string(host_prototype->name);
3522 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, ",name='%s'", name_esc);
3523 zbx_free(name_esc);
3524 }
3525 if (0 != (host_prototype->flags & ZBX_FLAG_HPLINK_UPDATE_STATUS))
3526 {
3527 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, ",status=%d",
3528 host_prototype->status);
3529 }
3530 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset, " where hostid=" ZBX_FS_UI64 ";\n",
3531 host_prototype->hostid);
3532 }
3533
3534 for (j = 0; j < host_prototype->lnk_templateids.values_num; j++)
3535 {
3536 zbx_db_insert_add_values(&db_insert_htemplates, hosttemplateid++, host_prototype->hostid,
3537 host_prototype->lnk_templateids.values[j]);
3538 }
3539
3540 for (j = 0; j < host_prototype->group_prototypes.values_num; j++)
3541 {
3542 group_prototype = (zbx_group_prototype_t *)host_prototype->group_prototypes.values[j];
3543
3544 if (0 == group_prototype->group_prototypeid)
3545 {
3546 zbx_db_insert_add_values(&db_insert_gproto, group_prototypeid++, host_prototype->hostid,
3547 group_prototype->name, group_prototype->groupid,
3548 group_prototype->templateid);
3549 }
3550 else
3551 {
3552 zbx_snprintf_alloc(&sql1, &sql1_alloc, &sql1_offset,
3553 "update group_prototype"
3554 " set templateid=" ZBX_FS_UI64
3555 " where group_prototypeid=" ZBX_FS_UI64 ";\n",
3556 group_prototype->templateid, group_prototype->group_prototypeid);
3557 }
3558 }
3559 }
3560
3561 if (0 != new_hosts)
3562 {
3563 zbx_db_insert_execute(&db_insert);
3564 zbx_db_insert_clean(&db_insert);
3565
3566 zbx_db_insert_execute(&db_insert_hdiscovery);
3567 zbx_db_insert_clean(&db_insert_hdiscovery);
3568 }
3569
3570 if (0 != new_hosts_templates)
3571 {
3572 zbx_db_insert_execute(&db_insert_htemplates);
3573 zbx_db_insert_clean(&db_insert_htemplates);
3574 }
3575
3576 if (0 != new_group_prototypes)
3577 {
3578 zbx_db_insert_execute(&db_insert_gproto);
3579 zbx_db_insert_clean(&db_insert_gproto);
3580 }
3581
3582 if (new_hosts != host_prototypes->values_num || 0 != upd_group_prototypes)
3583 {
3584 DBend_multiple_update(&sql1, &sql1_alloc, &sql1_offset);
3585 DBexecute("%s", sql1);
3586 zbx_free(sql1);
3587 }
3588
3589 if (0 != del_hosttemplateids->values_num)
3590 {
3591 DBexecute("%s", sql2);
3592 zbx_free(sql2);
3593 }
3594 }
3595
3596 /******************************************************************************
3597 * *
3598 * Function: DBcopy_template_host_prototypes *
3599 * *
3600 * Purpose: copy host prototypes from templates and create links between *
3601 * them and discovery rules *
3602 * *
3603 * Comments: auxiliary function for DBcopy_template_elements() *
3604 * *
3605 ******************************************************************************/
DBcopy_template_host_prototypes(zbx_uint64_t hostid,zbx_vector_uint64_t * templateids)3606 static void DBcopy_template_host_prototypes(zbx_uint64_t hostid, zbx_vector_uint64_t *templateids)
3607 {
3608 zbx_vector_ptr_t host_prototypes;
3609
3610 /* only regular hosts can have host prototypes */
3611 if (SUCCEED != DBis_regular_host(hostid))
3612 return;
3613
3614 zbx_vector_ptr_create(&host_prototypes);
3615
3616 DBhost_prototypes_make(hostid, templateids, &host_prototypes);
3617
3618 if (0 != host_prototypes.values_num)
3619 {
3620 zbx_vector_uint64_t del_hosttemplateids, del_group_prototypeids;
3621
3622 zbx_vector_uint64_create(&del_hosttemplateids);
3623 zbx_vector_uint64_create(&del_group_prototypeids);
3624
3625 DBhost_prototypes_templates_make(&host_prototypes, &del_hosttemplateids);
3626 DBhost_prototypes_groups_make(&host_prototypes, &del_group_prototypeids);
3627 DBhost_prototypes_save(&host_prototypes, &del_hosttemplateids);
3628 DBgroup_prototypes_delete(&del_group_prototypeids);
3629
3630 zbx_vector_uint64_destroy(&del_group_prototypeids);
3631 zbx_vector_uint64_destroy(&del_hosttemplateids);
3632 }
3633
3634 DBhost_prototypes_clean(&host_prototypes);
3635 zbx_vector_ptr_destroy(&host_prototypes);
3636 }
3637
3638 /******************************************************************************
3639 * *
3640 * Function: DBcopy_template_triggers *
3641 * *
3642 * Purpose: Copy template triggers to host *
3643 * *
3644 * Parameters: hostid - [IN] host identificator from database *
3645 * templateids - [IN] array of template IDs *
3646 * *
3647 * Return value: upon successful completion return SUCCEED *
3648 * *
3649 * Author: Eugene Grigorjev *
3650 * *
3651 * Comments: !!! Don't forget to sync the code with PHP !!! *
3652 * *
3653 ******************************************************************************/
DBcopy_template_triggers(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)3654 static int DBcopy_template_triggers(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
3655 {
3656 const char *__function_name = "DBcopy_template_triggers";
3657
3658 char *sql = NULL;
3659 size_t sql_alloc = 512, sql_offset = 0;
3660 DB_RESULT result;
3661 DB_ROW row;
3662 zbx_uint64_t triggerid, new_triggerid, cur_triggerid;
3663 int res = SUCCEED;
3664 zbx_vector_uint64_t new_triggerids, cur_triggerids;
3665
3666 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3667
3668 zbx_vector_uint64_create(&new_triggerids);
3669 zbx_vector_uint64_create(&cur_triggerids);
3670
3671 sql = (char *)zbx_malloc(sql, sql_alloc);
3672
3673 sql_offset = 0;
3674 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
3675 "select distinct t.triggerid,t.description,t.expression,t.status,"
3676 "t.type,t.priority,t.comments,t.url,t.flags,t.recovery_expression,t.recovery_mode,"
3677 "t.correlation_mode,t.correlation_tag,t.manual_close"
3678 " from triggers t,functions f,items i"
3679 " where t.triggerid=f.triggerid"
3680 " and f.itemid=i.itemid"
3681 " and");
3682 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", templateids->values, templateids->values_num);
3683
3684 result = DBselect("%s", sql);
3685
3686 zbx_free(sql);
3687
3688 while (SUCCEED == res && NULL != (row = DBfetch(result)))
3689 {
3690 ZBX_STR2UINT64(triggerid, row[0]);
3691
3692 res = DBcopy_trigger_to_host(&new_triggerid, &cur_triggerid, hostid, triggerid,
3693 row[1], /* description */
3694 row[2], /* expression */
3695 row[9], /* recovery_expression */
3696 (unsigned char)atoi(row[10]), /* recovery_mode */
3697 (unsigned char)atoi(row[3]), /* status */
3698 (unsigned char)atoi(row[4]), /* type */
3699 (unsigned char)atoi(row[5]), /* priority */
3700 row[6], /* comments */
3701 row[7], /* url */
3702 (unsigned char)atoi(row[8]), /* flags */
3703 (unsigned char)atoi(row[11]), /* correlation_mode */
3704 row[12], /* correlation_tag */
3705 (unsigned char)atoi(row[13])); /* manual_close */
3706
3707 if (0 != new_triggerid) /* new trigger added */
3708 zbx_vector_uint64_append(&new_triggerids, new_triggerid);
3709 else
3710 zbx_vector_uint64_append(&cur_triggerids, cur_triggerid);
3711 }
3712 DBfree_result(result);
3713
3714 if (SUCCEED == res)
3715 res = DBadd_template_dependencies_for_new_triggers(hostid, new_triggerids.values, new_triggerids.values_num);
3716
3717 if (SUCCEED == res)
3718 res = DBcopy_template_trigger_tags(&new_triggerids, &cur_triggerids);
3719
3720 zbx_vector_uint64_destroy(&cur_triggerids);
3721 zbx_vector_uint64_destroy(&new_triggerids);
3722
3723 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res));
3724
3725 return res;
3726 }
3727
3728 /******************************************************************************
3729 * *
3730 * Function: DBget_same_itemid *
3731 * *
3732 * Purpose: get same itemid for selected host by itemid from template *
3733 * *
3734 * Parameters: hostid - host identificator from database *
3735 * itemid - item identificator from database (from template) *
3736 * *
3737 * Return value: new item identificator or zero if item not found *
3738 * *
3739 * Author: Alexander Vladishev *
3740 * *
3741 * Comments: !!! Don't forget to sync the code with PHP !!! *
3742 * *
3743 ******************************************************************************/
DBget_same_itemid(zbx_uint64_t hostid,zbx_uint64_t titemid)3744 static zbx_uint64_t DBget_same_itemid(zbx_uint64_t hostid, zbx_uint64_t titemid)
3745 {
3746 const char *__function_name = "DBget_same_itemid";
3747 DB_RESULT result;
3748 DB_ROW row;
3749 zbx_uint64_t itemid = 0;
3750
3751 zabbix_log(LOG_LEVEL_DEBUG, "In %s() hostid:" ZBX_FS_UI64
3752 " titemid:" ZBX_FS_UI64,
3753 __function_name, hostid, titemid);
3754
3755 result = DBselect(
3756 "select hi.itemid"
3757 " from items hi,items ti"
3758 " where hi.key_=ti.key_"
3759 " and hi.hostid=" ZBX_FS_UI64
3760 " and ti.itemid=" ZBX_FS_UI64,
3761 hostid, titemid);
3762
3763 if (NULL != (row = DBfetch(result)))
3764 ZBX_STR2UINT64(itemid, row[0]);
3765 DBfree_result(result);
3766
3767 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_UI64, __function_name, itemid);
3768
3769 return itemid;
3770 }
3771
3772 /******************************************************************************
3773 * *
3774 * Function: DBcopy_graph_to_host *
3775 * *
3776 * Purpose: copy specified graph to host *
3777 * *
3778 * Parameters: graphid - graph identificator from database *
3779 * hostid - host identificator from database *
3780 * *
3781 * Author: Eugene Grigorjev, Alexander Vladishev *
3782 * *
3783 * Comments: !!! Don't forget to sync the code with PHP !!! *
3784 * *
3785 ******************************************************************************/
DBcopy_graph_to_host(zbx_uint64_t hostid,zbx_uint64_t graphid,const char * name,int width,int height,double yaxismin,double yaxismax,unsigned char show_work_period,unsigned char show_triggers,unsigned char graphtype,unsigned char show_legend,unsigned char show_3d,double percent_left,double percent_right,unsigned char ymin_type,unsigned char ymax_type,zbx_uint64_t ymin_itemid,zbx_uint64_t ymax_itemid,unsigned char flags)3786 static void DBcopy_graph_to_host(zbx_uint64_t hostid, zbx_uint64_t graphid,
3787 const char *name, int width, int height, double yaxismin,
3788 double yaxismax, unsigned char show_work_period,
3789 unsigned char show_triggers, unsigned char graphtype,
3790 unsigned char show_legend, unsigned char show_3d,
3791 double percent_left, double percent_right,
3792 unsigned char ymin_type, unsigned char ymax_type,
3793 zbx_uint64_t ymin_itemid, zbx_uint64_t ymax_itemid,
3794 unsigned char flags)
3795 {
3796 const char *__function_name = "DBcopy_graph_to_host";
3797 DB_RESULT result;
3798 DB_ROW row;
3799 ZBX_GRAPH_ITEMS *gitems = NULL, *chd_gitems = NULL;
3800 size_t gitems_alloc = 0, gitems_num = 0,
3801 chd_gitems_alloc = 0, chd_gitems_num = 0;
3802 zbx_uint64_t hst_graphid, hst_gitemid;
3803 char *sql = NULL, *name_esc, *color_esc;
3804 size_t sql_alloc = ZBX_KIBIBYTE, sql_offset, i;
3805
3806 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
3807
3808 sql = (char *)zbx_malloc(sql, sql_alloc * sizeof(char));
3809
3810 name_esc = DBdyn_escape_string(name);
3811
3812 sql_offset = 0;
3813 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3814 "select 0,dst.itemid,dst.key_,gi.drawtype,gi.sortorder,gi.color,gi.yaxisside,gi.calc_fnc,"
3815 "gi.type,i.flags"
3816 " from graphs_items gi,items i,items dst"
3817 " where gi.itemid=i.itemid"
3818 " and i.key_=dst.key_"
3819 " and gi.graphid=" ZBX_FS_UI64
3820 " and dst.hostid=" ZBX_FS_UI64
3821 " order by dst.key_",
3822 graphid, hostid);
3823
3824 DBget_graphitems(sql, &gitems, &gitems_alloc, &gitems_num);
3825
3826 result = DBselect(
3827 "select distinct g.graphid"
3828 " from graphs g,graphs_items gi,items i"
3829 " where g.graphid=gi.graphid"
3830 " and gi.itemid=i.itemid"
3831 " and i.hostid=" ZBX_FS_UI64
3832 " and g.name='%s'"
3833 " and g.templateid is null",
3834 hostid, name_esc);
3835
3836 /* compare graphs */
3837 hst_graphid = 0;
3838 while (NULL != (row = DBfetch(result)))
3839 {
3840 ZBX_STR2UINT64(hst_graphid, row[0]);
3841
3842 sql_offset = 0;
3843 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3844 "select gi.gitemid,i.itemid,i.key_,gi.drawtype,gi.sortorder,gi.color,gi.yaxisside,"
3845 "gi.calc_fnc,gi.type,i.flags"
3846 " from graphs_items gi,items i"
3847 " where gi.itemid=i.itemid"
3848 " and gi.graphid=" ZBX_FS_UI64
3849 " order by i.key_",
3850 hst_graphid);
3851
3852 DBget_graphitems(sql, &chd_gitems, &chd_gitems_alloc, &chd_gitems_num);
3853
3854 if (SUCCEED == DBcmp_graphitems(gitems, gitems_num, chd_gitems, chd_gitems_num))
3855 break; /* found equal graph */
3856
3857 hst_graphid = 0;
3858 }
3859 DBfree_result(result);
3860
3861 sql_offset = 0;
3862 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
3863
3864 if (GRAPH_YAXIS_TYPE_ITEM_VALUE == ymin_type)
3865 ymin_itemid = DBget_same_itemid(hostid, ymin_itemid);
3866 else
3867 ymin_itemid = 0;
3868
3869 if (GRAPH_YAXIS_TYPE_ITEM_VALUE == ymax_type)
3870 ymax_itemid = DBget_same_itemid(hostid, ymax_itemid);
3871 else
3872 ymax_itemid = 0;
3873
3874 if (0 != hst_graphid)
3875 {
3876 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3877 "update graphs"
3878 " set name='%s',"
3879 "width=%d,"
3880 "height=%d,"
3881 "yaxismin=" ZBX_FS_DBL ","
3882 "yaxismax=" ZBX_FS_DBL ","
3883 "templateid=" ZBX_FS_UI64 ","
3884 "show_work_period=%d,"
3885 "show_triggers=%d,"
3886 "graphtype=%d,"
3887 "show_legend=%d,"
3888 "show_3d=%d,"
3889 "percent_left=" ZBX_FS_DBL ","
3890 "percent_right=" ZBX_FS_DBL ","
3891 "ymin_type=%d,"
3892 "ymax_type=%d,"
3893 "ymin_itemid=%s,"
3894 "ymax_itemid=%s,"
3895 "flags=%d"
3896 " where graphid=" ZBX_FS_UI64 ";\n",
3897 name_esc, width, height, yaxismin, yaxismax,
3898 graphid, (int)show_work_period, (int)show_triggers,
3899 (int)graphtype, (int)show_legend, (int)show_3d,
3900 percent_left, percent_right, (int)ymin_type, (int)ymax_type,
3901 DBsql_id_ins(ymin_itemid), DBsql_id_ins(ymax_itemid), (int)flags,
3902 hst_graphid);
3903
3904 for (i = 0; i < gitems_num; i++)
3905 {
3906 color_esc = DBdyn_escape_string(gitems[i].color);
3907
3908 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3909 "update graphs_items"
3910 " set drawtype=%d,"
3911 "sortorder=%d,"
3912 "color='%s',"
3913 "yaxisside=%d,"
3914 "calc_fnc=%d,"
3915 "type=%d"
3916 " where gitemid=" ZBX_FS_UI64 ";\n",
3917 gitems[i].drawtype,
3918 gitems[i].sortorder,
3919 color_esc,
3920 gitems[i].yaxisside,
3921 gitems[i].calc_fnc,
3922 gitems[i].type,
3923 chd_gitems[i].gitemid);
3924
3925 zbx_free(color_esc);
3926 }
3927 }
3928 else
3929 {
3930 hst_graphid = DBget_maxid("graphs");
3931
3932 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3933 "insert into graphs"
3934 " (graphid,name,width,height,yaxismin,yaxismax,templateid,"
3935 "show_work_period,show_triggers,graphtype,show_legend,"
3936 "show_3d,percent_left,percent_right,ymin_type,ymax_type,"
3937 "ymin_itemid,ymax_itemid,flags)"
3938 " values (" ZBX_FS_UI64 ",'%s',%d,%d," ZBX_FS_DBL ","
3939 ZBX_FS_DBL "," ZBX_FS_UI64 ",%d,%d,%d,%d,%d," ZBX_FS_DBL ","
3940 ZBX_FS_DBL ",%d,%d,%s,%s,%d);\n",
3941 hst_graphid, name_esc, width, height, yaxismin, yaxismax,
3942 graphid, (int)show_work_period, (int)show_triggers,
3943 (int)graphtype, (int)show_legend, (int)show_3d,
3944 percent_left, percent_right, (int)ymin_type, (int)ymax_type,
3945 DBsql_id_ins(ymin_itemid), DBsql_id_ins(ymax_itemid), (int)flags);
3946
3947 hst_gitemid = DBget_maxid_num("graphs_items", gitems_num);
3948
3949 for (i = 0; i < gitems_num; i++)
3950 {
3951 color_esc = DBdyn_escape_string(gitems[i].color);
3952
3953 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
3954 "insert into graphs_items (gitemid,graphid,itemid,drawtype,"
3955 "sortorder,color,yaxisside,calc_fnc,type)"
3956 " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64
3957 ",%d,%d,'%s',%d,%d,%d);\n",
3958 hst_gitemid, hst_graphid, gitems[i].itemid,
3959 gitems[i].drawtype, gitems[i].sortorder, color_esc,
3960 gitems[i].yaxisside, gitems[i].calc_fnc, gitems[i].type);
3961 hst_gitemid++;
3962
3963 zbx_free(color_esc);
3964 }
3965 }
3966
3967 zbx_free(name_esc);
3968
3969 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
3970
3971 if (sql_offset > 16) /* In ORACLE always present begin..end; */
3972 DBexecute("%s", sql);
3973
3974 zbx_free(gitems);
3975 zbx_free(chd_gitems);
3976 zbx_free(sql);
3977
3978 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
3979 }
3980
3981 /******************************************************************************
3982 * *
3983 * Function: DBcopy_template_graphs *
3984 * *
3985 * Purpose: copy graphs from template to host *
3986 * *
3987 * Parameters: hostid - [IN] host identificator from database *
3988 * templateids - [IN] array of template IDs *
3989 * *
3990 * Author: Eugene Grigorjev *
3991 * *
3992 * Comments: !!! Don't forget to sync the code with PHP !!! *
3993 * *
3994 ******************************************************************************/
DBcopy_template_graphs(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)3995 static void DBcopy_template_graphs(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
3996 {
3997 const char *__function_name = "DBcopy_template_graphs";
3998 char *sql = NULL;
3999 size_t sql_alloc = 512, sql_offset = 0;
4000 DB_RESULT result;
4001 DB_ROW row;
4002 zbx_uint64_t graphid, ymin_itemid, ymax_itemid;
4003
4004 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4005
4006 sql = (char *)zbx_malloc(sql, sql_alloc);
4007
4008 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4009 "select distinct g.graphid,g.name,g.width,g.height,g.yaxismin,"
4010 "g.yaxismax,g.show_work_period,g.show_triggers,"
4011 "g.graphtype,g.show_legend,g.show_3d,g.percent_left,"
4012 "g.percent_right,g.ymin_type,g.ymax_type,g.ymin_itemid,"
4013 "g.ymax_itemid,g.flags"
4014 " from graphs g,graphs_items gi,items i"
4015 " where g.graphid=gi.graphid"
4016 " and gi.itemid=i.itemid"
4017 " and");
4018 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", templateids->values, templateids->values_num);
4019
4020 result = DBselect("%s", sql);
4021
4022 zbx_free(sql);
4023
4024 while (NULL != (row = DBfetch(result)))
4025 {
4026 ZBX_STR2UINT64(graphid, row[0]);
4027 ZBX_DBROW2UINT64(ymin_itemid, row[15]);
4028 ZBX_DBROW2UINT64(ymax_itemid, row[16]);
4029
4030 DBcopy_graph_to_host(hostid, graphid,
4031 row[1], /* name */
4032 atoi(row[2]), /* width */
4033 atoi(row[3]), /* height */
4034 atof(row[4]), /* yaxismin */
4035 atof(row[5]), /* yaxismax */
4036 (unsigned char)atoi(row[6]), /* show_work_period */
4037 (unsigned char)atoi(row[7]), /* show_triggers */
4038 (unsigned char)atoi(row[8]), /* graphtype */
4039 (unsigned char)atoi(row[9]), /* show_legend */
4040 (unsigned char)atoi(row[10]), /* show_3d */
4041 atof(row[11]), /* percent_left */
4042 atof(row[12]), /* percent_right */
4043 (unsigned char)atoi(row[13]), /* ymin_type */
4044 (unsigned char)atoi(row[14]), /* ymax_type */
4045 ymin_itemid,
4046 ymax_itemid,
4047 (unsigned char)atoi(row[17])); /* flags */
4048 }
4049 DBfree_result(result);
4050
4051 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4052 }
4053
4054 typedef struct
4055 {
4056 zbx_uint64_t t_itemid;
4057 zbx_uint64_t h_itemid;
4058 unsigned char type;
4059 }
4060 httpstepitem_t;
4061
4062 typedef struct
4063 {
4064 zbx_uint64_t httpstepid;
4065 char *name;
4066 char *url;
4067 char *posts;
4068 char *required;
4069 char *status_codes;
4070 zbx_vector_ptr_t httpstepitems;
4071 zbx_vector_ptr_t fields;
4072 char *timeout;
4073 int no;
4074 int follow_redirects;
4075 int retrieve_mode;
4076 int post_type;
4077 }
4078 httpstep_t;
4079
4080 typedef struct
4081 {
4082 zbx_uint64_t t_itemid;
4083 zbx_uint64_t h_itemid;
4084 unsigned char type;
4085 }
4086 httptestitem_t;
4087
4088 typedef struct
4089 {
4090 zbx_uint64_t templateid;
4091 zbx_uint64_t httptestid;
4092 zbx_uint64_t t_applicationid;
4093 zbx_uint64_t h_applicationid;
4094 char *name;
4095 char *delay;
4096 zbx_vector_ptr_t fields;
4097 char *agent;
4098 char *http_user;
4099 char *http_password;
4100 char *http_proxy;
4101 zbx_vector_ptr_t httpsteps;
4102 zbx_vector_ptr_t httptestitems;
4103 int retries;
4104 unsigned char status;
4105 unsigned char authentication;
4106 }
4107 httptest_t;
4108
4109 typedef struct
4110 {
4111 int type;
4112 char *name;
4113 char *value;
4114 }
4115 httpfield_t;
4116
4117 /******************************************************************************
4118 * *
4119 * Function: DBget_httptests *
4120 * *
4121 * *
4122 ******************************************************************************/
DBget_httptests(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids,zbx_vector_ptr_t * httptests)4123 static void DBget_httptests(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids, zbx_vector_ptr_t *httptests)
4124 {
4125 const char *__function_name = "DBget_httptests";
4126
4127 char *sql = NULL;
4128 size_t sql_alloc = 512, sql_offset = 0;
4129 DB_RESULT result;
4130 DB_ROW row;
4131 httptest_t *httptest;
4132 httpstep_t *httpstep;
4133 httpfield_t *httpfield;
4134 httptestitem_t *httptestitem;
4135 httpstepitem_t *httpstepitem;
4136 zbx_vector_uint64_t httptestids; /* the list of web scenarios which should be added to a host */
4137 zbx_vector_uint64_t applications;
4138 zbx_vector_uint64_t items;
4139 zbx_uint64_t httptestid, httpstepid, applicationid, itemid;
4140 int i, j, k;
4141
4142 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4143
4144 zbx_vector_uint64_create(&httptestids);
4145 zbx_vector_uint64_create(&applications);
4146 zbx_vector_uint64_create(&items);
4147
4148 sql = (char *)zbx_malloc(sql, sql_alloc);
4149
4150 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4151 "select t.httptestid,t.name,t.applicationid,t.delay,t.status,t.agent,t.authentication,"
4152 "t.http_user,t.http_password,t.http_proxy,t.retries,h.httptestid"
4153 " from httptest t"
4154 " left join httptest h"
4155 " on h.hostid=" ZBX_FS_UI64
4156 " and h.name=t.name"
4157 " where", hostid);
4158 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.hostid", templateids->values, templateids->values_num);
4159 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by t.httptestid");
4160
4161 result = DBselect("%s", sql);
4162
4163 while (NULL != (row = DBfetch(result)))
4164 {
4165 httptest = (httptest_t *)zbx_calloc(NULL, 1, sizeof(httptest_t));
4166
4167 ZBX_STR2UINT64(httptest->templateid, row[0]);
4168 ZBX_DBROW2UINT64(httptest->httptestid, row[11]);
4169 zbx_vector_ptr_create(&httptest->httpsteps);
4170 zbx_vector_ptr_create(&httptest->httptestitems);
4171 zbx_vector_ptr_create(&httptest->fields);
4172
4173 zbx_vector_ptr_append(httptests, httptest);
4174
4175 if (0 == httptest->httptestid)
4176 {
4177 httptest->name = zbx_strdup(NULL, row[1]);
4178 ZBX_DBROW2UINT64(httptest->t_applicationid, row[2]);
4179 httptest->delay = zbx_strdup(NULL, row[3]);
4180 httptest->status = (unsigned char)atoi(row[4]);
4181 httptest->agent = zbx_strdup(NULL, row[5]);
4182 httptest->authentication = (unsigned char)atoi(row[6]);
4183 httptest->http_user = zbx_strdup(NULL, row[7]);
4184 httptest->http_password = zbx_strdup(NULL, row[8]);
4185 httptest->http_proxy = zbx_strdup(NULL, row[9]);
4186 httptest->retries = atoi(row[10]);
4187
4188 zbx_vector_uint64_append(&httptestids, httptest->templateid);
4189
4190 if (0 != httptest->t_applicationid)
4191 zbx_vector_uint64_append(&applications, httptest->t_applicationid);
4192 }
4193 }
4194 DBfree_result(result);
4195
4196 if (0 != httptestids.values_num)
4197 {
4198 httptest = NULL;
4199
4200 /* web scenario fields */
4201 sql_offset = 0;
4202 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4203 "select httptestid,type,name,value"
4204 " from httptest_field"
4205 " where");
4206 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid",
4207 httptestids.values, httptestids.values_num);
4208 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by httptestid,httptest_fieldid");
4209
4210 result = DBselect("%s", sql);
4211
4212 while (NULL != (row = DBfetch(result)))
4213 {
4214 ZBX_STR2UINT64(httptestid, row[0]);
4215
4216 if (NULL == httptest || httptest->templateid != httptestid)
4217 {
4218 if (FAIL == (i = zbx_vector_ptr_bsearch(httptests, &httptestid,
4219 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4220 {
4221 THIS_SHOULD_NEVER_HAPPEN;
4222 continue;
4223 }
4224
4225 httptest = (httptest_t *)httptests->values[i];
4226 }
4227
4228 httpfield = (httpfield_t *)zbx_malloc(NULL, sizeof(httpfield_t));
4229
4230 httpfield->type = atoi(row[1]);
4231 httpfield->name = zbx_strdup(NULL, row[2]);
4232 httpfield->value = zbx_strdup(NULL, row[3]);
4233
4234 zbx_vector_ptr_append(&httptest->fields, httpfield);
4235 }
4236 DBfree_result(result);
4237
4238 /* web scenario steps */
4239 httptest = NULL;
4240
4241 sql_offset = 0;
4242 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4243 "select httpstepid,httptestid,name,no,url,timeout,posts,required,status_codes,"
4244 "follow_redirects,retrieve_mode,post_type"
4245 " from httpstep"
4246 " where");
4247 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid",
4248 httptestids.values, httptestids.values_num);
4249 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " order by httptestid");
4250
4251 result = DBselect("%s", sql);
4252
4253 while (NULL != (row = DBfetch(result)))
4254 {
4255 ZBX_STR2UINT64(httptestid, row[1]);
4256
4257 if (NULL == httptest || httptest->templateid != httptestid)
4258 {
4259 if (FAIL == (i = zbx_vector_ptr_bsearch(httptests, &httptestid,
4260 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4261 {
4262 THIS_SHOULD_NEVER_HAPPEN;
4263 continue;
4264 }
4265
4266 httptest = (httptest_t *)httptests->values[i];
4267 }
4268
4269 httpstep = (httpstep_t *)zbx_malloc(NULL, sizeof(httptest_t));
4270
4271 ZBX_STR2UINT64(httpstep->httpstepid, row[0]);
4272 httpstep->name = zbx_strdup(NULL, row[2]);
4273 httpstep->no = atoi(row[3]);
4274 httpstep->url = zbx_strdup(NULL, row[4]);
4275 httpstep->timeout = zbx_strdup(NULL, row[5]);
4276 httpstep->posts = zbx_strdup(NULL, row[6]);
4277 httpstep->required = zbx_strdup(NULL, row[7]);
4278 httpstep->status_codes = zbx_strdup(NULL, row[8]);
4279 httpstep->follow_redirects = atoi(row[9]);
4280 httpstep->retrieve_mode = atoi(row[10]);
4281 httpstep->post_type = atoi(row[11]);
4282 zbx_vector_ptr_create(&httpstep->httpstepitems);
4283 zbx_vector_ptr_create(&httpstep->fields);
4284
4285 zbx_vector_ptr_append(&httptest->httpsteps, httpstep);
4286 }
4287 DBfree_result(result);
4288
4289 for (i = 0; i < httptests->values_num; i++)
4290 {
4291 httptest = (httptest_t *)httptests->values[i];
4292 zbx_vector_ptr_sort(&httptest->httpsteps, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
4293 }
4294
4295 /* web scenario step fields */
4296 httptest = NULL;
4297
4298 sql_offset = 0;
4299 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4300 "select s.httptestid,f.httpstepid,f.type,f.name,f.value"
4301 " from httpstep_field f"
4302 " join httpstep s"
4303 " on f.httpstepid=s.httpstepid"
4304 " and");
4305 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "s.httptestid",
4306 httptestids.values, httptestids.values_num);
4307 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4308 " order by s.httptestid,f.httpstepid,f.httpstep_fieldid");
4309
4310 result = DBselect("%s", sql);
4311
4312 while (NULL != (row = DBfetch(result)))
4313 {
4314 ZBX_STR2UINT64(httptestid, row[0]);
4315 ZBX_STR2UINT64(httpstepid, row[1]);
4316
4317 if (NULL == httptest || httptest->templateid != httptestid)
4318 {
4319 if (FAIL == (i = zbx_vector_ptr_bsearch(httptests, &httptestid,
4320 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4321 {
4322 THIS_SHOULD_NEVER_HAPPEN;
4323 continue;
4324 }
4325
4326 httptest = (httptest_t *)httptests->values[i];
4327 httpstep = NULL;
4328 }
4329
4330 if (NULL == httpstep || httpstep->httpstepid != httpstepid)
4331 {
4332 if (FAIL == (i = zbx_vector_ptr_bsearch(&httptest->httpsteps, &httpstepid,
4333 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4334 {
4335 THIS_SHOULD_NEVER_HAPPEN;
4336 continue;
4337 }
4338
4339 httpstep = (httpstep_t *)httptest->httpsteps.values[i];
4340 }
4341
4342 httpfield = (httpfield_t *)zbx_malloc(NULL, sizeof(httpfield_t));
4343
4344 httpfield->type = atoi(row[2]);
4345 httpfield->name = zbx_strdup(NULL, row[3]);
4346 httpfield->value = zbx_strdup(NULL, row[4]);
4347
4348 zbx_vector_ptr_append(&httpstep->fields, httpfield);
4349 }
4350 DBfree_result(result);
4351 }
4352
4353 /* applications */
4354 if (0 != applications.values_num)
4355 {
4356 zbx_vector_uint64_sort(&applications, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4357 zbx_vector_uint64_uniq(&applications, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4358
4359 sql_offset = 0;
4360 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4361 "select t.applicationid,h.applicationid"
4362 " from applications t"
4363 " join applications h"
4364 " on t.name=h.name"
4365 " and h.hostid=" ZBX_FS_UI64
4366 " where", hostid);
4367 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.applicationid",
4368 applications.values, applications.values_num);
4369
4370 result = DBselect("%s", sql);
4371
4372 while (NULL != (row = DBfetch(result)))
4373 {
4374 ZBX_STR2UINT64(applicationid, row[0]);
4375
4376 for (i = 0; i < httptests->values_num; i++)
4377 {
4378 httptest = (httptest_t *)httptests->values[i];
4379
4380 if (httptest->t_applicationid == applicationid)
4381 ZBX_STR2UINT64(httptest->h_applicationid, row[1]);
4382 }
4383 }
4384 DBfree_result(result);
4385 }
4386
4387 /* web scenario items */
4388 if (0 != httptestids.values_num)
4389 {
4390 httptest = NULL;
4391
4392 sql_offset = 0;
4393 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4394 "select httptestid,itemid,type"
4395 " from httptestitem"
4396 " where");
4397 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "httptestid",
4398 httptestids.values, httptestids.values_num);
4399
4400 result = DBselect("%s", sql);
4401
4402 while (NULL != (row = DBfetch(result)))
4403 {
4404 ZBX_STR2UINT64(httptestid, row[0]);
4405
4406 if (NULL == httptest || httptest->templateid != httptestid)
4407 {
4408 if (FAIL == (i = zbx_vector_ptr_bsearch(httptests, &httptestid,
4409 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4410 {
4411 THIS_SHOULD_NEVER_HAPPEN;
4412 continue;
4413 }
4414
4415 httptest = (httptest_t *)httptests->values[i];
4416 }
4417
4418 httptestitem = (httptestitem_t *)zbx_calloc(NULL, 1, sizeof(httptestitem_t));
4419
4420 ZBX_STR2UINT64(httptestitem->t_itemid, row[1]);
4421 httptestitem->type = (unsigned char)atoi(row[2]);
4422
4423 zbx_vector_ptr_append(&httptest->httptestitems, httptestitem);
4424
4425 zbx_vector_uint64_append(&items, httptestitem->t_itemid);
4426 }
4427 DBfree_result(result);
4428 }
4429
4430 /* web scenario step items */
4431 if (0 != httptestids.values_num)
4432 {
4433 httptest = NULL;
4434 httpstep = NULL;
4435
4436 sql_offset = 0;
4437 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4438 "select hs.httptestid,hsi.httpstepid,hsi.itemid,hsi.type"
4439 " from httpstepitem hsi"
4440 " join httpstep hs"
4441 " on");
4442 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hs.httptestid",
4443 httptestids.values, httptestids.values_num);
4444 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
4445 " and hs.httpstepid=hsi.httpstepid"
4446 " order by hs.httptestid,hsi.httpstepid");
4447
4448 result = DBselect("%s", sql);
4449
4450 while (NULL != (row = DBfetch(result)))
4451 {
4452 ZBX_STR2UINT64(httptestid, row[0]);
4453 ZBX_STR2UINT64(httpstepid, row[1]);
4454
4455 if (NULL == httptest || httptest->templateid != httptestid)
4456 {
4457 if (FAIL == (i = zbx_vector_ptr_bsearch(httptests, &httptestid,
4458 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4459 {
4460 THIS_SHOULD_NEVER_HAPPEN;
4461 continue;
4462 }
4463
4464 httptest = (httptest_t *)httptests->values[i];
4465 httpstep = NULL;
4466 }
4467
4468 if (NULL == httpstep || httpstep->httpstepid != httpstepid)
4469 {
4470 if (FAIL == (i = zbx_vector_ptr_bsearch(&httptest->httpsteps, &httpstepid,
4471 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
4472 {
4473 THIS_SHOULD_NEVER_HAPPEN;
4474 continue;
4475 }
4476
4477 httpstep = (httpstep_t *)httptest->httpsteps.values[i];
4478 }
4479
4480 httpstepitem = (httpstepitem_t *)zbx_calloc(NULL, 1, sizeof(httpstepitem_t));
4481
4482 ZBX_STR2UINT64(httpstepitem->t_itemid, row[2]);
4483 httpstepitem->type = (unsigned char)atoi(row[3]);
4484
4485 zbx_vector_ptr_append(&httpstep->httpstepitems, httpstepitem);
4486
4487 zbx_vector_uint64_append(&items, httpstepitem->t_itemid);
4488 }
4489 DBfree_result(result);
4490 }
4491
4492 /* items */
4493 if (0 != items.values_num)
4494 {
4495 zbx_vector_uint64_sort(&items, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4496
4497 sql_offset = 0;
4498 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4499 "select t.itemid,h.itemid"
4500 " from items t"
4501 " join items h"
4502 " on h.hostid=" ZBX_FS_UI64
4503 " and h.key_=t.key_"
4504 " where", hostid);
4505 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "t.itemid",
4506 items.values, items.values_num);
4507
4508 result = DBselect("%s", sql);
4509
4510 while (NULL != (row = DBfetch(result)))
4511 {
4512 ZBX_STR2UINT64(itemid, row[0]);
4513
4514 for (i = 0; i < httptests->values_num; i++)
4515 {
4516 httptest = (httptest_t *)httptests->values[i];
4517
4518 for (j = 0; j < httptest->httptestitems.values_num; j++)
4519 {
4520 httptestitem = (httptestitem_t *)httptest->httptestitems.values[j];
4521
4522 if (httptestitem->t_itemid == itemid)
4523 ZBX_STR2UINT64(httptestitem->h_itemid, row[1]);
4524 }
4525
4526 for (j = 0; j < httptest->httpsteps.values_num; j++)
4527 {
4528 httpstep = (httpstep_t *)httptest->httpsteps.values[j];
4529
4530 for (k = 0; k < httpstep->httpstepitems.values_num; k++)
4531 {
4532 httpstepitem = (httpstepitem_t *)httpstep->httpstepitems.values[k];
4533
4534 if (httpstepitem->t_itemid == itemid)
4535 ZBX_STR2UINT64(httpstepitem->h_itemid, row[1]);
4536 }
4537 }
4538 }
4539 }
4540 DBfree_result(result);
4541 }
4542
4543 zbx_free(sql);
4544
4545 zbx_vector_uint64_destroy(&items);
4546 zbx_vector_uint64_destroy(&applications);
4547 zbx_vector_uint64_destroy(&httptestids);
4548
4549 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4550 }
4551
4552 /******************************************************************************
4553 * *
4554 * Function: DBsave_httptests *
4555 * *
4556 * *
4557 ******************************************************************************/
DBsave_httptests(zbx_uint64_t hostid,zbx_vector_ptr_t * httptests)4558 static void DBsave_httptests(zbx_uint64_t hostid, zbx_vector_ptr_t *httptests)
4559 {
4560 char *sql = NULL;
4561 size_t sql_alloc = 512, sql_offset = 0;
4562 httptest_t *httptest;
4563 httpfield_t *httpfield;
4564 httpstep_t *httpstep;
4565 httptestitem_t *httptestitem;
4566 httpstepitem_t *httpstepitem;
4567 zbx_uint64_t httptestid = 0, httpstepid = 0, httptestitemid = 0, httpstepitemid = 0, httptestfieldid = 0,
4568 httpstepfieldid = 0;
4569 int i, j, k, num_httptests = 0, num_httpsteps = 0, num_httptestitems = 0, num_httpstepitems = 0,
4570 num_httptestfields = 0, num_httpstepfields = 0;
4571 zbx_db_insert_t db_insert_htest, db_insert_hstep, db_insert_htitem, db_insert_hsitem, db_insert_tfield,
4572 db_insert_sfield;
4573
4574 if (0 == httptests->values_num)
4575 return;
4576
4577 for (i = 0; i < httptests->values_num; i++)
4578 {
4579 httptest = (httptest_t *)httptests->values[i];
4580
4581 if (0 == httptest->httptestid)
4582 {
4583 num_httptests++;
4584 num_httpsteps += httptest->httpsteps.values_num;
4585 num_httptestitems += httptest->httptestitems.values_num;
4586 num_httptestfields += httptest->fields.values_num;
4587
4588 for (j = 0; j < httptest->httpsteps.values_num; j++)
4589 {
4590 httpstep = (httpstep_t *)httptest->httpsteps.values[j];
4591
4592 num_httpstepfields += httpstep->fields.values_num;
4593 num_httpstepitems += httpstep->httpstepitems.values_num;
4594 }
4595 }
4596 }
4597
4598 if (0 != num_httptests)
4599 {
4600 httptestid = DBget_maxid_num("httptest", num_httptests);
4601
4602 zbx_db_insert_prepare(&db_insert_htest, "httptest", "httptestid", "name", "applicationid", "delay",
4603 "status", "agent", "authentication", "http_user", "http_password", "http_proxy",
4604 "retries", "hostid", "templateid", NULL);
4605 }
4606
4607 if (httptests->values_num != num_httptests)
4608 sql = (char *)zbx_malloc(sql, sql_alloc);
4609
4610 if (0 != num_httptestfields)
4611 {
4612 httptestfieldid = DBget_maxid_num("httptest_field", num_httptestfields);
4613
4614 zbx_db_insert_prepare(&db_insert_tfield, "httptest_field", "httptest_fieldid", "httptestid", "type",
4615 "name", "value", NULL);
4616 }
4617
4618 if (0 != num_httpsteps)
4619 {
4620 httpstepid = DBget_maxid_num("httpstep", num_httpsteps);
4621
4622 zbx_db_insert_prepare(&db_insert_hstep, "httpstep", "httpstepid", "httptestid", "name", "no", "url",
4623 "timeout", "posts", "required", "status_codes", "follow_redirects", "retrieve_mode",
4624 "post_type", NULL);
4625 }
4626
4627 if (0 != num_httptestitems)
4628 {
4629 httptestitemid = DBget_maxid_num("httptestitem", num_httptestitems);
4630
4631 zbx_db_insert_prepare(&db_insert_htitem, "httptestitem", "httptestitemid", "httptestid", "itemid",
4632 "type", NULL);
4633 }
4634
4635 if (0 != num_httpstepitems)
4636 {
4637 httpstepitemid = DBget_maxid_num("httpstepitem", num_httpstepitems);
4638
4639 zbx_db_insert_prepare(&db_insert_hsitem, "httpstepitem", "httpstepitemid", "httpstepid", "itemid",
4640 "type", NULL);
4641 }
4642
4643 if (0 != num_httpstepfields)
4644 {
4645 httpstepfieldid = DBget_maxid_num("httpstep_field", num_httpstepfields);
4646
4647 zbx_db_insert_prepare(&db_insert_sfield, "httpstep_field", "httpstep_fieldid", "httpstepid", "type",
4648 "name", "value", NULL);
4649 }
4650
4651 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
4652
4653 for (i = 0; i < httptests->values_num; i++)
4654 {
4655 httptest = (httptest_t *)httptests->values[i];
4656
4657 if (0 == httptest->httptestid)
4658 {
4659 httptest->httptestid = httptestid++;
4660
4661 zbx_db_insert_add_values(&db_insert_htest, httptest->httptestid, httptest->name,
4662 httptest->h_applicationid, httptest->delay, (int)httptest->status,
4663 httptest->agent, (int)httptest->authentication, httptest->http_user,
4664 httptest->http_password, httptest->http_proxy, httptest->retries, hostid,
4665 httptest->templateid);
4666
4667 for (j = 0; j < httptest->fields.values_num; j++)
4668 {
4669 httpfield = (httpfield_t *)httptest->fields.values[j];
4670
4671 zbx_db_insert_add_values(&db_insert_tfield, httptestfieldid, httptest->httptestid,
4672 httpfield->type, httpfield->name, httpfield->value);
4673
4674 httptestfieldid++;
4675 }
4676
4677 for (j = 0; j < httptest->httpsteps.values_num; j++)
4678 {
4679 httpstep = (httpstep_t *)httptest->httpsteps.values[j];
4680
4681 zbx_db_insert_add_values(&db_insert_hstep, httpstepid, httptest->httptestid,
4682 httpstep->name, httpstep->no, httpstep->url, httpstep->timeout,
4683 httpstep->posts, httpstep->required, httpstep->status_codes,
4684 httpstep->follow_redirects, httpstep->retrieve_mode,
4685 httpstep->post_type);
4686
4687 for (k = 0; k < httpstep->fields.values_num; k++)
4688 {
4689 httpfield = (httpfield_t *)httpstep->fields.values[k];
4690
4691 zbx_db_insert_add_values(&db_insert_sfield, httpstepfieldid, httpstepid,
4692 httpfield->type, httpfield->name, httpfield->value);
4693
4694 httpstepfieldid++;
4695 }
4696
4697 for (k = 0; k < httpstep->httpstepitems.values_num; k++)
4698 {
4699 httpstepitem = (httpstepitem_t *)httpstep->httpstepitems.values[k];
4700
4701 zbx_db_insert_add_values(&db_insert_hsitem, httpstepitemid, httpstepid,
4702 httpstepitem->h_itemid, (int)httpstepitem->type);
4703
4704 httpstepitemid++;
4705 }
4706
4707 httpstepid++;
4708 }
4709
4710 for (j = 0; j < httptest->httptestitems.values_num; j++)
4711 {
4712 httptestitem = (httptestitem_t *)httptest->httptestitems.values[j];
4713
4714 zbx_db_insert_add_values(&db_insert_htitem, httptestitemid, httptest->httptestid,
4715 httptestitem->h_itemid, (int)httptestitem->type);
4716
4717 httptestitemid++;
4718 }
4719 }
4720 else
4721 {
4722 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
4723 "update httptest"
4724 " set templateid=" ZBX_FS_UI64
4725 " where httptestid=" ZBX_FS_UI64 ";\n",
4726 httptest->templateid, httptest->httptestid);
4727 }
4728 }
4729
4730 if (0 != num_httptests)
4731 {
4732 zbx_db_insert_execute(&db_insert_htest);
4733 zbx_db_insert_clean(&db_insert_htest);
4734 }
4735
4736 if (0 != num_httpsteps)
4737 {
4738 zbx_db_insert_execute(&db_insert_hstep);
4739 zbx_db_insert_clean(&db_insert_hstep);
4740 }
4741
4742 if (0 != num_httptestitems)
4743 {
4744 zbx_db_insert_execute(&db_insert_htitem);
4745 zbx_db_insert_clean(&db_insert_htitem);
4746 }
4747
4748 if (0 != num_httpstepitems)
4749 {
4750 zbx_db_insert_execute(&db_insert_hsitem);
4751 zbx_db_insert_clean(&db_insert_hsitem);
4752 }
4753
4754 if (0 != num_httptestfields)
4755 {
4756 zbx_db_insert_execute(&db_insert_tfield);
4757 zbx_db_insert_clean(&db_insert_tfield);
4758 }
4759
4760 if (0 != num_httpstepfields)
4761 {
4762 zbx_db_insert_execute(&db_insert_sfield);
4763 zbx_db_insert_clean(&db_insert_sfield);
4764 }
4765
4766 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
4767
4768 if (16 < sql_offset)
4769 DBexecute("%s", sql);
4770
4771 zbx_free(sql);
4772 }
4773
4774 /******************************************************************************
4775 * *
4776 * Function: clean_httptests *
4777 * *
4778 * *
4779 ******************************************************************************/
clean_httptests(zbx_vector_ptr_t * httptests)4780 static void clean_httptests(zbx_vector_ptr_t *httptests)
4781 {
4782 httptest_t *httptest;
4783 httpfield_t *httpfield;
4784 httpstep_t *httpstep;
4785 int i, j, k;
4786
4787 for (i = 0; i < httptests->values_num; i++)
4788 {
4789 httptest = (httptest_t *)httptests->values[i];
4790
4791 zbx_free(httptest->http_proxy);
4792 zbx_free(httptest->http_password);
4793 zbx_free(httptest->http_user);
4794 zbx_free(httptest->agent);
4795 zbx_free(httptest->delay);
4796 zbx_free(httptest->name);
4797
4798 for (j = 0; j < httptest->fields.values_num; j++)
4799 {
4800 httpfield = (httpfield_t *)httptest->fields.values[j];
4801
4802 zbx_free(httpfield->name);
4803 zbx_free(httpfield->value);
4804
4805 zbx_free(httpfield);
4806 }
4807
4808 zbx_vector_ptr_destroy(&httptest->fields);
4809
4810 for (j = 0; j < httptest->httpsteps.values_num; j++)
4811 {
4812 httpstep = (httpstep_t *)httptest->httpsteps.values[j];
4813
4814 zbx_free(httpstep->status_codes);
4815 zbx_free(httpstep->required);
4816 zbx_free(httpstep->posts);
4817 zbx_free(httpstep->timeout);
4818 zbx_free(httpstep->url);
4819 zbx_free(httpstep->name);
4820
4821 for (k = 0; k < httpstep->fields.values_num; k++)
4822 {
4823 httpfield = (httpfield_t *)httpstep->fields.values[k];
4824
4825 zbx_free(httpfield->name);
4826 zbx_free(httpfield->value);
4827
4828 zbx_free(httpfield);
4829 }
4830
4831 zbx_vector_ptr_destroy(&httpstep->fields);
4832
4833 for (k = 0; k < httpstep->httpstepitems.values_num; k++)
4834 zbx_free(httpstep->httpstepitems.values[k]);
4835
4836 zbx_vector_ptr_destroy(&httpstep->httpstepitems);
4837
4838 zbx_free(httpstep);
4839 }
4840
4841 zbx_vector_ptr_destroy(&httptest->httpsteps);
4842
4843 for (j = 0; j < httptest->httptestitems.values_num; j++)
4844 zbx_free(httptest->httptestitems.values[j]);
4845
4846 zbx_vector_ptr_destroy(&httptest->httptestitems);
4847
4848 zbx_free(httptest);
4849 }
4850 }
4851
4852 /******************************************************************************
4853 * *
4854 * Function: DBcopy_template_httptests *
4855 * *
4856 * Purpose: copy web scenarios from template to host *
4857 * *
4858 * Parameters: hostid - [IN] host identificator from database *
4859 * templateids - [IN] array of template IDs *
4860 * *
4861 ******************************************************************************/
DBcopy_template_httptests(zbx_uint64_t hostid,const zbx_vector_uint64_t * templateids)4862 static void DBcopy_template_httptests(zbx_uint64_t hostid, const zbx_vector_uint64_t *templateids)
4863 {
4864 const char *__function_name = "DBcopy_template_httptests";
4865 zbx_vector_ptr_t httptests;
4866
4867 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4868
4869 zbx_vector_ptr_create(&httptests);
4870
4871 DBget_httptests(hostid, templateids, &httptests);
4872 DBsave_httptests(hostid, &httptests);
4873
4874 clean_httptests(&httptests);
4875 zbx_vector_ptr_destroy(&httptests);
4876
4877 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
4878 }
4879
4880 /******************************************************************************
4881 * *
4882 * Function: DBcopy_template_elements *
4883 * *
4884 * Purpose: copy elements from specified template *
4885 * *
4886 * Parameters: hostid - [IN] host identificator from database *
4887 * lnk_templateids - [IN] array of template IDs *
4888 * *
4889 * Return value: upon successful completion return SUCCEED *
4890 * *
4891 ******************************************************************************/
DBcopy_template_elements(zbx_uint64_t hostid,zbx_vector_uint64_t * lnk_templateids,char ** error)4892 int DBcopy_template_elements(zbx_uint64_t hostid, zbx_vector_uint64_t *lnk_templateids, char **error)
4893 {
4894 const char *__function_name = "DBcopy_template_elements";
4895 zbx_vector_uint64_t templateids;
4896 zbx_uint64_t hosttemplateid;
4897 int i, res = SUCCEED;
4898 char *template_names, err[MAX_STRING_LEN];
4899
4900 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4901
4902 zbx_vector_uint64_create(&templateids);
4903
4904 get_templates_by_hostid(hostid, &templateids);
4905
4906 for (i = 0; i < lnk_templateids->values_num; i++)
4907 {
4908 if (FAIL != zbx_vector_uint64_search(&templateids, lnk_templateids->values[i],
4909 ZBX_DEFAULT_UINT64_COMPARE_FUNC))
4910 {
4911 /* template already linked */
4912 zbx_vector_uint64_remove(lnk_templateids, i--);
4913 }
4914 else
4915 zbx_vector_uint64_append(&templateids, lnk_templateids->values[i]);
4916 }
4917
4918 /* all templates already linked */
4919 if (0 == lnk_templateids->values_num)
4920 goto clean;
4921
4922 zbx_vector_uint64_sort(&templateids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
4923
4924 if (SUCCEED != (res = validate_linked_templates(&templateids, err, sizeof(err))))
4925 {
4926 template_names = get_template_names(lnk_templateids);
4927
4928 *error = zbx_dsprintf(NULL, "%s to host \"%s\": %s", template_names, zbx_host_string(hostid), err);
4929
4930 zbx_free(template_names);
4931 goto clean;
4932 }
4933
4934 if (SUCCEED != (res = validate_host(hostid, lnk_templateids, err, sizeof(err))))
4935 {
4936 template_names = get_template_names(lnk_templateids);
4937
4938 *error = zbx_dsprintf(NULL, "%s to host \"%s\": %s", template_names, zbx_host_string(hostid), err);
4939
4940 zbx_free(template_names);
4941 goto clean;
4942 }
4943
4944 hosttemplateid = DBget_maxid_num("hosts_templates", lnk_templateids->values_num);
4945
4946 for (i = 0; i < lnk_templateids->values_num; i++)
4947 {
4948 DBexecute("insert into hosts_templates (hosttemplateid,hostid,templateid)"
4949 " values (" ZBX_FS_UI64 "," ZBX_FS_UI64 "," ZBX_FS_UI64 ")",
4950 hosttemplateid++, hostid, lnk_templateids->values[i]);
4951 }
4952
4953 DBcopy_template_applications(hostid, lnk_templateids);
4954 DBcopy_template_items(hostid, lnk_templateids);
4955 DBcopy_template_application_prototypes(hostid, lnk_templateids);
4956 DBcopy_template_item_application_prototypes(hostid, lnk_templateids);
4957 DBcopy_template_host_prototypes(hostid, lnk_templateids);
4958 if (SUCCEED == (res = DBcopy_template_triggers(hostid, lnk_templateids)))
4959 {
4960 DBcopy_template_graphs(hostid, lnk_templateids);
4961 DBcopy_template_httptests(hostid, lnk_templateids);
4962 }
4963 clean:
4964 zbx_vector_uint64_destroy(&templateids);
4965
4966 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(res));
4967
4968 return res;
4969 }
4970
4971 /******************************************************************************
4972 * *
4973 * Function: DBdelete_hosts *
4974 * *
4975 * Purpose: delete hosts from database with all elements *
4976 * *
4977 * Parameters: hostids - [IN] host identificators from database *
4978 * *
4979 ******************************************************************************/
DBdelete_hosts(zbx_vector_uint64_t * hostids)4980 void DBdelete_hosts(zbx_vector_uint64_t *hostids)
4981 {
4982 const char *__function_name = "DBdelete_hosts";
4983
4984 zbx_vector_uint64_t itemids, httptestids, selementids;
4985 char *sql = NULL;
4986 size_t sql_alloc = 0, sql_offset;
4987 int i;
4988
4989 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
4990
4991 if (SUCCEED != DBlock_hostids(hostids))
4992 goto out;
4993
4994 zbx_vector_uint64_create(&httptestids);
4995 zbx_vector_uint64_create(&selementids);
4996
4997 /* delete web tests */
4998
4999 sql_offset = 0;
5000 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5001 "select httptestid"
5002 " from httptest"
5003 " where");
5004 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num);
5005
5006 DBselect_uint64(sql, &httptestids);
5007
5008 DBdelete_httptests(&httptestids);
5009
5010 zbx_vector_uint64_destroy(&httptestids);
5011
5012 /* delete items -> triggers -> graphs */
5013
5014 zbx_vector_uint64_create(&itemids);
5015
5016 sql_offset = 0;
5017 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5018 "select itemid"
5019 " from items"
5020 " where");
5021 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num);
5022
5023 DBselect_uint64(sql, &itemids);
5024
5025 DBdelete_items(&itemids);
5026
5027 zbx_vector_uint64_destroy(&itemids);
5028
5029 sql_offset = 0;
5030 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
5031
5032 /* delete host from maps */
5033 DBget_sysmapelements_by_element_type_ids(&selementids, SYSMAP_ELEMENT_TYPE_HOST, hostids);
5034 if (0 != selementids.values_num)
5035 {
5036 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from sysmaps_elements where");
5037 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "selementid", selementids.values,
5038 selementids.values_num);
5039 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
5040 }
5041
5042 /* delete action conditions */
5043 for (i = 0; i < hostids->values_num; i++)
5044 DBdelete_action_conditions(CONDITION_TYPE_HOST, hostids->values[i]);
5045
5046 /* delete host */
5047 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hosts where");
5048 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hostid", hostids->values, hostids->values_num);
5049 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
5050
5051 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
5052
5053 DBexecute("%s", sql);
5054
5055 zbx_free(sql);
5056
5057 zbx_vector_uint64_destroy(&selementids);
5058 out:
5059 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5060 }
5061
5062 /******************************************************************************
5063 * *
5064 * Function: DBdelete_hosts_with_prototypes *
5065 * *
5066 * Purpose: delete hosts from database, check if there are any host *
5067 * prototypes and delete them first *
5068 * *
5069 * Parameters: hostids - [IN] host identificators from database *
5070 * *
5071 ******************************************************************************/
DBdelete_hosts_with_prototypes(zbx_vector_uint64_t * hostids)5072 void DBdelete_hosts_with_prototypes(zbx_vector_uint64_t *hostids)
5073 {
5074 const char *__function_name = "DBdelete_hosts_with_prototypes";
5075
5076 zbx_vector_uint64_t host_prototypeids;
5077 char *sql = NULL;
5078 size_t sql_alloc = 0, sql_offset = 0;
5079
5080 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
5081
5082 zbx_vector_uint64_create(&host_prototypeids);
5083
5084 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5085 "select hd.hostid"
5086 " from items i,host_discovery hd"
5087 " where i.itemid=hd.parent_itemid"
5088 " and");
5089 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "i.hostid", hostids->values, hostids->values_num);
5090
5091 DBselect_uint64(sql, &host_prototypeids);
5092
5093 DBdelete_host_prototypes(&host_prototypeids);
5094
5095 zbx_free(sql);
5096 zbx_vector_uint64_destroy(&host_prototypeids);
5097
5098 DBdelete_hosts(hostids);
5099
5100 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5101 }
5102
5103 /******************************************************************************
5104 * *
5105 * Function: DBadd_interface *
5106 * *
5107 * Purpose: add new interface to specified host *
5108 * *
5109 * Parameters: hostid - [IN] host identificator from database *
5110 * type - [IN] new interface type *
5111 * useip - [IN] how to connect to the host 0/1 - DNS/IP *
5112 * ip - [IN] IP address *
5113 * dns - [IN] DNS address *
5114 * port - [IN] port *
5115 * *
5116 * Return value: upon successful completion return interface identificator *
5117 * *
5118 * Author: Alexander Vladishev *
5119 * *
5120 * Comments: *
5121 * *
5122 ******************************************************************************/
DBadd_interface(zbx_uint64_t hostid,unsigned char type,unsigned char useip,const char * ip,const char * dns,unsigned short port)5123 zbx_uint64_t DBadd_interface(zbx_uint64_t hostid, unsigned char type,
5124 unsigned char useip, const char *ip, const char *dns, unsigned short port)
5125 {
5126 const char *__function_name = "DBadd_interface";
5127
5128 DB_RESULT result;
5129 DB_ROW row;
5130 char *ip_esc, *dns_esc, *tmp = NULL;
5131 zbx_uint64_t interfaceid = 0;
5132 unsigned char main_ = 1, db_main, db_useip;
5133 unsigned short db_port;
5134 const char *db_ip, *db_dns;
5135
5136 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
5137
5138 result = DBselect(
5139 "select interfaceid,useip,ip,dns,port,main"
5140 " from interface"
5141 " where hostid=" ZBX_FS_UI64
5142 " and type=%d",
5143 hostid, (int)type);
5144
5145 while (NULL != (row = DBfetch(result)))
5146 {
5147 db_useip = (unsigned char)atoi(row[1]);
5148 db_ip = row[2];
5149 db_dns = row[3];
5150 db_main = (unsigned char)atoi(row[5]);
5151 if (1 == db_main)
5152 main_ = 0;
5153
5154 if (db_useip != useip)
5155 continue;
5156
5157 if (useip && 0 != strcmp(db_ip, ip))
5158 continue;
5159
5160 if (!useip && 0 != strcmp(db_dns, dns))
5161 continue;
5162
5163 zbx_free(tmp);
5164 tmp = strdup(row[4]);
5165 substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL, NULL,
5166 &tmp, MACRO_TYPE_COMMON, NULL, 0);
5167 if (FAIL == is_ushort(tmp, &db_port) || db_port != port)
5168 continue;
5169
5170 ZBX_STR2UINT64(interfaceid, row[0]);
5171 break;
5172 }
5173 DBfree_result(result);
5174
5175 zbx_free(tmp);
5176
5177 if (0 != interfaceid)
5178 goto out;
5179
5180 ip_esc = DBdyn_escape_field("interface", "ip", ip);
5181 dns_esc = DBdyn_escape_field("interface", "dns", dns);
5182
5183 interfaceid = DBget_maxid("interface");
5184
5185 DBexecute("insert into interface"
5186 " (interfaceid,hostid,main,type,useip,ip,dns,port)"
5187 " values"
5188 " (" ZBX_FS_UI64 "," ZBX_FS_UI64 ",%d,%d,%d,'%s','%s',%d)",
5189 interfaceid, hostid, (int)main_, (int)type, (int)useip, ip_esc, dns_esc, (int)port);
5190
5191 zbx_free(dns_esc);
5192 zbx_free(ip_esc);
5193 out:
5194 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():" ZBX_FS_UI64, __function_name, interfaceid);
5195
5196 return interfaceid;
5197 }
5198
5199 /******************************************************************************
5200 * *
5201 * Function: DBdelete_groups_validate *
5202 * *
5203 * Purpose: removes the groupids from the list which cannot be deleted *
5204 * (host or template can remain without groups or it's an internal *
5205 * group or it's used by a host prototype) *
5206 * *
5207 ******************************************************************************/
DBdelete_groups_validate(zbx_vector_uint64_t * groupids)5208 static void DBdelete_groups_validate(zbx_vector_uint64_t *groupids)
5209 {
5210 DB_RESULT result;
5211 DB_ROW row;
5212 char *sql = NULL;
5213 size_t sql_alloc = 0, sql_offset = 0;
5214 zbx_vector_uint64_t hostids;
5215 zbx_uint64_t groupid;
5216 int index, internal;
5217
5218 if (0 == groupids->values_num)
5219 return;
5220
5221 zbx_vector_uint64_create(&hostids);
5222
5223 /* select of the list of hosts which remain without groups */
5224
5225 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5226 "select hg.hostid"
5227 " from hosts_groups hg"
5228 " where");
5229 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.groupid", groupids->values, groupids->values_num);
5230 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5231 " and not exists ("
5232 "select null"
5233 " from hosts_groups hg2"
5234 " where hg.hostid=hg2.hostid"
5235 " and not");
5236 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg2.groupid", groupids->values, groupids->values_num);
5237 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5238 ")");
5239
5240 DBselect_uint64(sql, &hostids);
5241
5242 /* select of the list of groups which cannot be deleted */
5243
5244 sql_offset = 0;
5245 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5246 "select g.groupid,g.internal,g.name"
5247 " from hstgrp g"
5248 " where");
5249 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.groupid", groupids->values, groupids->values_num);
5250 if (0 < hostids.values_num)
5251 {
5252 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
5253 " and (g.internal=%d"
5254 " or exists ("
5255 "select null"
5256 " from hosts_groups hg"
5257 " where g.groupid=hg.groupid"
5258 " and",
5259 ZBX_INTERNAL_GROUP);
5260 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "hg.hostid", hostids.values, hostids.values_num);
5261 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "))");
5262 }
5263 else
5264 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " and g.internal=%d", ZBX_INTERNAL_GROUP);
5265
5266 result = DBselect("%s", sql);
5267
5268 while (NULL != (row = DBfetch(result)))
5269 {
5270 ZBX_STR2UINT64(groupid, row[0]);
5271 internal = atoi(row[1]);
5272
5273 if (FAIL != (index = zbx_vector_uint64_bsearch(groupids, groupid, ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
5274 zbx_vector_uint64_remove(groupids, index);
5275
5276 if (ZBX_INTERNAL_GROUP == internal)
5277 {
5278 zabbix_log(LOG_LEVEL_WARNING, "host group \"%s\" is internal and cannot be deleted", row[2]);
5279 }
5280 else
5281 {
5282 zabbix_log(LOG_LEVEL_WARNING, "host group \"%s\" cannot be deleted,"
5283 " because some hosts or templates depend on it", row[2]);
5284 }
5285 }
5286 DBfree_result(result);
5287
5288 /* check if groups is used in the groups prototypes */
5289
5290 if (0 != groupids->values_num)
5291 {
5292 sql_offset = 0;
5293 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5294 "select g.groupid,g.name"
5295 " from hstgrp g"
5296 " where");
5297 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.groupid",
5298 groupids->values, groupids->values_num);
5299 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
5300 " and exists ("
5301 "select null"
5302 " from group_prototype gp"
5303 " where g.groupid=gp.groupid"
5304 ")");
5305
5306 result = DBselect("%s", sql);
5307
5308 while (NULL != (row = DBfetch(result)))
5309 {
5310 ZBX_STR2UINT64(groupid, row[0]);
5311
5312 if (FAIL != (index = zbx_vector_uint64_bsearch(groupids, groupid,
5313 ZBX_DEFAULT_UINT64_COMPARE_FUNC)))
5314 {
5315 zbx_vector_uint64_remove(groupids, index);
5316 }
5317
5318 zabbix_log(LOG_LEVEL_WARNING, "host group \"%s\" cannot be deleted,"
5319 " because it is used by a host prototype", row[1]);
5320 }
5321 DBfree_result(result);
5322 }
5323
5324 zbx_vector_uint64_destroy(&hostids);
5325 zbx_free(sql);
5326 }
5327
5328 /******************************************************************************
5329 * *
5330 * Function: DBdelete_groups *
5331 * *
5332 * Purpose: delete host groups from database *
5333 * *
5334 * Parameters: groupids - [IN] array of group identificators from database *
5335 * *
5336 ******************************************************************************/
DBdelete_groups(zbx_vector_uint64_t * groupids)5337 void DBdelete_groups(zbx_vector_uint64_t *groupids)
5338 {
5339 const char *__function_name = "DBdelete_groups";
5340
5341 char *sql = NULL;
5342 size_t sql_alloc = 256, sql_offset = 0;
5343 int i;
5344 zbx_vector_uint64_t screen_itemids, selementids;
5345 zbx_uint64_t resource_types_delete[] = {SCREEN_RESOURCE_DATA_OVERVIEW,
5346 SCREEN_RESOURCE_TRIGGER_OVERVIEW};
5347 zbx_uint64_t resource_types_update[] = {SCREEN_RESOURCE_HOST_INFO, SCREEN_RESOURCE_TRIGGER_INFO,
5348 SCREEN_RESOURCE_HOSTGROUP_TRIGGERS, SCREEN_RESOURCE_HOST_TRIGGERS};
5349
5350 zabbix_log(LOG_LEVEL_DEBUG, "In %s() values_num:%d", __function_name, groupids->values_num);
5351
5352 DBdelete_groups_validate(groupids);
5353
5354 if (0 == groupids->values_num)
5355 goto out;
5356
5357 for (i = 0; i < groupids->values_num; i++)
5358 DBdelete_action_conditions(CONDITION_TYPE_HOST_GROUP, groupids->values[i]);
5359
5360 sql = (char *)zbx_malloc(sql, sql_alloc);
5361
5362 zbx_vector_uint64_create(&screen_itemids);
5363 zbx_vector_uint64_create(&selementids);
5364
5365 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
5366
5367 /* delete sysmaps_elements */
5368 DBget_sysmapelements_by_element_type_ids(&selementids, SYSMAP_ELEMENT_TYPE_HOST_GROUP, groupids);
5369 if (0 != selementids.values_num)
5370 {
5371 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from sysmaps_elements where");
5372 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "selementid", selementids.values,
5373 selementids.values_num);
5374 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
5375 }
5376
5377 /* delete screens_items (host group is mandatory for this elements) */
5378 DBget_screenitems_by_resource_types_ids(&screen_itemids, resource_types_delete, ARRSIZE(resource_types_delete),
5379 groupids);
5380 if (0 != screen_itemids.values_num)
5381 {
5382 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from screens_items where");
5383 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "screenitemid", screen_itemids.values,
5384 screen_itemids.values_num);
5385 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
5386 }
5387
5388 /* update screens_items (host group isn't mandatory for this elements) */
5389 zbx_vector_uint64_clear(&screen_itemids);
5390 DBget_screenitems_by_resource_types_ids(&screen_itemids, resource_types_update, ARRSIZE(resource_types_update),
5391 groupids);
5392
5393 if (0 != screen_itemids.values_num)
5394 {
5395 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update screens_items set resourceid=0 where");
5396 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "screenitemid", screen_itemids.values,
5397 screen_itemids.values_num);
5398 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
5399 }
5400
5401 /* groups */
5402 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from hstgrp where");
5403 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "groupid", groupids->values, groupids->values_num);
5404 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
5405
5406 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
5407
5408 DBexecute("%s", sql);
5409
5410 zbx_vector_uint64_destroy(&selementids);
5411 zbx_vector_uint64_destroy(&screen_itemids);
5412
5413 zbx_free(sql);
5414 out:
5415 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
5416 }
5417
5418 /******************************************************************************
5419 * *
5420 * Function: DBadd_host_inventory *
5421 * *
5422 * Purpose: adds host inventory to the host *
5423 * *
5424 * Parameters: hostid - [IN] host identifier *
5425 * inventory_mode - [IN] the host inventory mode *
5426 * *
5427 ******************************************************************************/
DBadd_host_inventory(zbx_uint64_t hostid,int inventory_mode)5428 void DBadd_host_inventory(zbx_uint64_t hostid, int inventory_mode)
5429 {
5430 zbx_db_insert_t db_insert;
5431
5432 zbx_db_insert_prepare(&db_insert, "host_inventory", "hostid", "inventory_mode", NULL);
5433 zbx_db_insert_add_values(&db_insert, hostid, inventory_mode);
5434 zbx_db_insert_execute(&db_insert);
5435 zbx_db_insert_clean(&db_insert);
5436 }
5437
5438 /******************************************************************************
5439 * *
5440 * Function: DBset_host_inventory *
5441 * *
5442 * Purpose: sets host inventory mode for the specified host *
5443 * *
5444 * Parameters: hostid - [IN] host identifier *
5445 * inventory_mode - [IN] the host inventory mode *
5446 * *
5447 * Comments: The host_inventory table record is created if absent. *
5448 * *
5449 * This function does not allow disabling host inventory - only *
5450 * setting manual or automatic host inventory mode is supported. *
5451 * *
5452 ******************************************************************************/
DBset_host_inventory(zbx_uint64_t hostid,int inventory_mode)5453 void DBset_host_inventory(zbx_uint64_t hostid, int inventory_mode)
5454 {
5455 DB_RESULT result;
5456 DB_ROW row;
5457
5458 result = DBselect("select inventory_mode from host_inventory where hostid=" ZBX_FS_UI64, hostid);
5459
5460 if (NULL == (row = DBfetch(result)))
5461 {
5462 DBadd_host_inventory(hostid, inventory_mode);
5463 }
5464 else if (inventory_mode != atoi(row[0]))
5465 {
5466 DBexecute("update host_inventory set inventory_mode=%d where hostid=" ZBX_FS_UI64, inventory_mode,
5467 hostid);
5468 }
5469
5470 DBfree_result(result);
5471 }
5472