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