1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "lld.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxalgo.h"
24 #include "zbxserver.h"
25
26 typedef struct
27 {
28 zbx_uint64_t graphid;
29 char *name;
30 char *name_orig;
31 zbx_uint64_t ymin_itemid;
32 zbx_uint64_t ymax_itemid;
33 zbx_vector_ptr_t gitems;
34 #define ZBX_FLAG_LLD_GRAPH_UNSET __UINT64_C(0x00000000)
35 #define ZBX_FLAG_LLD_GRAPH_DISCOVERED __UINT64_C(0x00000001)
36 #define ZBX_FLAG_LLD_GRAPH_UPDATE_NAME __UINT64_C(0x00000002)
37 #define ZBX_FLAG_LLD_GRAPH_UPDATE_WIDTH __UINT64_C(0x00000004)
38 #define ZBX_FLAG_LLD_GRAPH_UPDATE_HEIGHT __UINT64_C(0x00000008)
39 #define ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMIN __UINT64_C(0x00000010)
40 #define ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMAX __UINT64_C(0x00000020)
41 #define ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_WORK_PERIOD __UINT64_C(0x00000040)
42 #define ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_TRIGGERS __UINT64_C(0x00000080)
43 #define ZBX_FLAG_LLD_GRAPH_UPDATE_GRAPHTYPE __UINT64_C(0x00000100)
44 #define ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_LEGEND __UINT64_C(0x00000200)
45 #define ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_3D __UINT64_C(0x00000400)
46 #define ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_LEFT __UINT64_C(0x00000800)
47 #define ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_RIGHT __UINT64_C(0x00001000)
48 #define ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_TYPE __UINT64_C(0x00002000)
49 #define ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_ITEMID __UINT64_C(0x00004000)
50 #define ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_TYPE __UINT64_C(0x00008000)
51 #define ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_ITEMID __UINT64_C(0x00010000)
52 #define ZBX_FLAG_LLD_GRAPH_UPDATE \
53 (ZBX_FLAG_LLD_GRAPH_UPDATE_NAME | ZBX_FLAG_LLD_GRAPH_UPDATE_WIDTH | \
54 ZBX_FLAG_LLD_GRAPH_UPDATE_HEIGHT | ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMIN | \
55 ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMAX | ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_WORK_PERIOD | \
56 ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_TRIGGERS | ZBX_FLAG_LLD_GRAPH_UPDATE_GRAPHTYPE | \
57 ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_LEGEND | ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_3D | \
58 ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_LEFT | ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_RIGHT | \
59 ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_TYPE | ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_ITEMID | \
60 ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_TYPE | ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_ITEMID)
61 zbx_uint64_t flags;
62 int lastcheck;
63 int ts_delete;
64 }
65 zbx_lld_graph_t;
66
67 typedef struct
68 {
69 zbx_uint64_t gitemid;
70 zbx_uint64_t itemid;
71 char *color;
72 int sortorder;
73 unsigned char drawtype;
74 unsigned char yaxisside;
75 unsigned char calc_fnc;
76 unsigned char type;
77 #define ZBX_FLAG_LLD_GITEM_UNSET __UINT64_C(0x0000)
78 #define ZBX_FLAG_LLD_GITEM_DISCOVERED __UINT64_C(0x0001)
79 #define ZBX_FLAG_LLD_GITEM_UPDATE_ITEMID __UINT64_C(0x0002)
80 #define ZBX_FLAG_LLD_GITEM_UPDATE_DRAWTYPE __UINT64_C(0x0004)
81 #define ZBX_FLAG_LLD_GITEM_UPDATE_SORTORDER __UINT64_C(0x0008)
82 #define ZBX_FLAG_LLD_GITEM_UPDATE_COLOR __UINT64_C(0x0010)
83 #define ZBX_FLAG_LLD_GITEM_UPDATE_YAXISSIDE __UINT64_C(0x0020)
84 #define ZBX_FLAG_LLD_GITEM_UPDATE_CALC_FNC __UINT64_C(0x0040)
85 #define ZBX_FLAG_LLD_GITEM_UPDATE_TYPE __UINT64_C(0x0080)
86 #define ZBX_FLAG_LLD_GITEM_UPDATE \
87 (ZBX_FLAG_LLD_GITEM_UPDATE_ITEMID | ZBX_FLAG_LLD_GITEM_UPDATE_DRAWTYPE | \
88 ZBX_FLAG_LLD_GITEM_UPDATE_SORTORDER | ZBX_FLAG_LLD_GITEM_UPDATE_COLOR | \
89 ZBX_FLAG_LLD_GITEM_UPDATE_YAXISSIDE | ZBX_FLAG_LLD_GITEM_UPDATE_CALC_FNC | \
90 ZBX_FLAG_LLD_GITEM_UPDATE_TYPE)
91 #define ZBX_FLAG_LLD_GITEM_DELETE __UINT64_C(0x0100)
92 zbx_uint64_t flags;
93 }
94 zbx_lld_gitem_t;
95
96 typedef struct
97 {
98 zbx_uint64_t itemid;
99 unsigned char flags;
100 }
101 zbx_lld_item_t;
102
lld_item_free(zbx_lld_item_t * item)103 static void lld_item_free(zbx_lld_item_t *item)
104 {
105 zbx_free(item);
106 }
107
lld_items_free(zbx_vector_ptr_t * items)108 static void lld_items_free(zbx_vector_ptr_t *items)
109 {
110 while (0 != items->values_num)
111 lld_item_free((zbx_lld_item_t *)items->values[--items->values_num]);
112 }
113
lld_gitem_free(zbx_lld_gitem_t * gitem)114 static void lld_gitem_free(zbx_lld_gitem_t *gitem)
115 {
116 zbx_free(gitem->color);
117 zbx_free(gitem);
118 }
119
lld_gitems_free(zbx_vector_ptr_t * gitems)120 static void lld_gitems_free(zbx_vector_ptr_t *gitems)
121 {
122 while (0 != gitems->values_num)
123 lld_gitem_free((zbx_lld_gitem_t *)gitems->values[--gitems->values_num]);
124 }
125
lld_graph_free(zbx_lld_graph_t * graph)126 static void lld_graph_free(zbx_lld_graph_t *graph)
127 {
128 lld_gitems_free(&graph->gitems);
129 zbx_vector_ptr_destroy(&graph->gitems);
130 zbx_free(graph->name_orig);
131 zbx_free(graph->name);
132 zbx_free(graph);
133 }
134
lld_graphs_free(zbx_vector_ptr_t * graphs)135 static void lld_graphs_free(zbx_vector_ptr_t *graphs)
136 {
137 while (0 != graphs->values_num)
138 lld_graph_free((zbx_lld_graph_t *)graphs->values[--graphs->values_num]);
139 }
140
141 /******************************************************************************
142 * *
143 * Function: lld_graphs_get *
144 * *
145 * Purpose: retrieve graphs which were created by the specified graph *
146 * prototype *
147 * *
148 * Parameters: parent_graphid - [IN] graph prototype identificator *
149 * graphs - [OUT] sorted list of graphs *
150 * *
151 ******************************************************************************/
lld_graphs_get(zbx_uint64_t parent_graphid,zbx_vector_ptr_t * graphs,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)152 static void lld_graphs_get(zbx_uint64_t parent_graphid, zbx_vector_ptr_t *graphs, int width, int height,
153 double yaxismin, double yaxismax, unsigned char show_work_period, unsigned char show_triggers,
154 unsigned char graphtype, unsigned char show_legend, unsigned char show_3d, double percent_left,
155 double percent_right, unsigned char ymin_type, unsigned char ymax_type)
156 {
157 DB_RESULT result;
158 DB_ROW row;
159 zbx_lld_graph_t *graph;
160
161 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
162
163 result = DBselect(
164 "select g.graphid,g.name,g.width,g.height,g.yaxismin,g.yaxismax,g.show_work_period,"
165 "g.show_triggers,g.graphtype,g.show_legend,g.show_3d,g.percent_left,g.percent_right,"
166 "g.ymin_type,g.ymin_itemid,g.ymax_type,g.ymax_itemid,gd.lastcheck,gd.ts_delete"
167 " from graphs g,graph_discovery gd"
168 " where g.graphid=gd.graphid"
169 " and gd.parent_graphid=" ZBX_FS_UI64,
170 parent_graphid);
171
172 while (NULL != (row = DBfetch(result)))
173 {
174 graph = (zbx_lld_graph_t *)zbx_malloc(NULL, sizeof(zbx_lld_graph_t));
175
176 ZBX_STR2UINT64(graph->graphid, row[0]);
177 graph->name = zbx_strdup(NULL, row[1]);
178 graph->name_orig = NULL;
179
180 graph->flags = ZBX_FLAG_LLD_GRAPH_UNSET;
181
182 if (atoi(row[2]) != width)
183 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_WIDTH;
184
185 if (atoi(row[3]) != height)
186 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_HEIGHT;
187
188 if (atof(row[4]) != yaxismin)
189 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMIN;
190
191 if (atof(row[5]) != yaxismax)
192 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMAX;
193
194 if ((unsigned char)atoi(row[6]) != show_work_period)
195 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_WORK_PERIOD;
196
197 if ((unsigned char)atoi(row[7]) != show_triggers)
198 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_TRIGGERS;
199
200 if ((unsigned char)atoi(row[8]) != graphtype)
201 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_GRAPHTYPE;
202
203 if ((unsigned char)atoi(row[9]) != show_legend)
204 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_LEGEND;
205
206 if ((unsigned char)atoi(row[10]) != show_3d)
207 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_3D;
208
209 if (atof(row[11]) != percent_left)
210 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_LEFT;
211
212 if (atof(row[12]) != percent_right)
213 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_RIGHT;
214
215 if ((unsigned char)atoi(row[13]) != ymin_type)
216 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_TYPE;
217
218 ZBX_DBROW2UINT64(graph->ymin_itemid, row[14]);
219
220 if ((unsigned char)atoi(row[15]) != ymax_type)
221 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_TYPE;
222
223 ZBX_DBROW2UINT64(graph->ymax_itemid, row[16]);
224
225 graph->lastcheck = atoi(row[17]);
226 graph->ts_delete = atoi(row[18]);
227
228 zbx_vector_ptr_create(&graph->gitems);
229
230 zbx_vector_ptr_append(graphs, graph);
231 }
232 DBfree_result(result);
233
234 zbx_vector_ptr_sort(graphs, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
235
236 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
237 }
238
239 /******************************************************************************
240 * *
241 * Function: lld_gitems_get *
242 * *
243 * Purpose: retrieve graphs_items which are used by the graph prototype and *
244 * by selected graphs *
245 * *
246 ******************************************************************************/
lld_gitems_get(zbx_uint64_t parent_graphid,zbx_vector_ptr_t * gitems_proto,zbx_vector_ptr_t * graphs)247 static void lld_gitems_get(zbx_uint64_t parent_graphid, zbx_vector_ptr_t *gitems_proto,
248 zbx_vector_ptr_t *graphs)
249 {
250 int i, index;
251 zbx_lld_graph_t *graph;
252 zbx_lld_gitem_t *gitem;
253 zbx_uint64_t graphid;
254 zbx_vector_uint64_t graphids;
255 DB_RESULT result;
256 DB_ROW row;
257 char *sql = NULL;
258 size_t sql_alloc = 256, sql_offset = 0;
259
260 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
261
262 zbx_vector_uint64_create(&graphids);
263 zbx_vector_uint64_append(&graphids, parent_graphid);
264
265 for (i = 0; i < graphs->values_num; i++)
266 {
267 graph = (zbx_lld_graph_t *)graphs->values[i];
268
269 zbx_vector_uint64_append(&graphids, graph->graphid);
270 }
271
272 zbx_vector_uint64_sort(&graphids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
273
274 sql = (char *)zbx_malloc(sql, sql_alloc);
275
276 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
277 "select gitemid,graphid,itemid,drawtype,sortorder,color,yaxisside,calc_fnc,type"
278 " from graphs_items"
279 " where");
280 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "graphid",
281 graphids.values, graphids.values_num);
282
283 result = DBselect("%s", sql);
284
285 zbx_free(sql);
286
287 while (NULL != (row = DBfetch(result)))
288 {
289 gitem = (zbx_lld_gitem_t *)zbx_malloc(NULL, sizeof(zbx_lld_gitem_t));
290
291 ZBX_STR2UINT64(gitem->gitemid, row[0]);
292 ZBX_STR2UINT64(graphid, row[1]);
293 ZBX_STR2UINT64(gitem->itemid, row[2]);
294 ZBX_STR2UCHAR(gitem->drawtype, row[3]);
295 gitem->sortorder = atoi(row[4]);
296 gitem->color = zbx_strdup(NULL, row[5]);
297 ZBX_STR2UCHAR(gitem->yaxisside, row[6]);
298 ZBX_STR2UCHAR(gitem->calc_fnc, row[7]);
299 ZBX_STR2UCHAR(gitem->type, row[8]);
300
301 gitem->flags = ZBX_FLAG_LLD_GITEM_UNSET;
302
303 if (graphid == parent_graphid)
304 {
305 zbx_vector_ptr_append(gitems_proto, gitem);
306 }
307 else if (FAIL != (index = zbx_vector_ptr_bsearch(graphs, &graphid,
308 ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
309 {
310 graph = (zbx_lld_graph_t *)graphs->values[index];
311
312 zbx_vector_ptr_append(&graph->gitems, gitem);
313 }
314 else
315 {
316 THIS_SHOULD_NEVER_HAPPEN;
317 lld_gitem_free(gitem);
318 }
319 }
320 DBfree_result(result);
321
322 zbx_vector_ptr_sort(gitems_proto, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
323
324 for (i = 0; i < graphs->values_num; i++)
325 {
326 graph = (zbx_lld_graph_t *)graphs->values[i];
327
328 zbx_vector_ptr_sort(&graph->gitems, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
329 }
330
331 zbx_vector_uint64_destroy(&graphids);
332
333 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
334 }
335
336 /******************************************************************************
337 * *
338 * Function: lld_items_get *
339 * *
340 * Purpose: returns the list of items which are related to the graph *
341 * prototype *
342 * *
343 * Parameters: gitems_proto - [IN] graph prototype's graphs_items *
344 * ymin_itemid_proto - [IN] graph prototype's ymin_itemid *
345 * ymax_itemid_proto - [IN] graph prototype's ymax_itemid *
346 * items - [OUT] sorted list of items *
347 * *
348 ******************************************************************************/
lld_items_get(const zbx_vector_ptr_t * gitems_proto,zbx_uint64_t ymin_itemid_proto,zbx_uint64_t ymax_itemid_proto,zbx_vector_ptr_t * items)349 static void lld_items_get(const zbx_vector_ptr_t *gitems_proto, zbx_uint64_t ymin_itemid_proto,
350 zbx_uint64_t ymax_itemid_proto, zbx_vector_ptr_t *items)
351 {
352 DB_RESULT result;
353 DB_ROW row;
354 const zbx_lld_gitem_t *gitem;
355 zbx_lld_item_t *item;
356 zbx_vector_uint64_t itemids;
357 int i;
358
359 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
360
361 zbx_vector_uint64_create(&itemids);
362
363 for (i = 0; i < gitems_proto->values_num; i++)
364 {
365 gitem = (zbx_lld_gitem_t *)gitems_proto->values[i];
366
367 zbx_vector_uint64_append(&itemids, gitem->itemid);
368 }
369
370 if (0 != ymin_itemid_proto)
371 zbx_vector_uint64_append(&itemids, ymin_itemid_proto);
372
373 if (0 != ymax_itemid_proto)
374 zbx_vector_uint64_append(&itemids, ymax_itemid_proto);
375
376 if (0 != itemids.values_num)
377 {
378 char *sql = NULL;
379 size_t sql_alloc = 256, sql_offset = 0;
380
381 zbx_vector_uint64_sort(&itemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
382
383 sql = (char *)zbx_malloc(sql, sql_alloc);
384
385 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset,
386 "select itemid,flags"
387 " from items"
388 " where");
389 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "itemid", itemids.values, itemids.values_num);
390
391 result = DBselect("%s", sql);
392
393 zbx_free(sql);
394
395 while (NULL != (row = DBfetch(result)))
396 {
397 item = (zbx_lld_item_t *)zbx_malloc(NULL, sizeof(zbx_lld_item_t));
398
399 ZBX_STR2UINT64(item->itemid, row[0]);
400 ZBX_STR2UCHAR(item->flags, row[1]);
401
402 zbx_vector_ptr_append(items, item);
403 }
404 DBfree_result(result);
405
406 zbx_vector_ptr_sort(items, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
407 }
408
409 zbx_vector_uint64_destroy(&itemids);
410
411 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
412 }
413
414 /******************************************************************************
415 * *
416 * Function: lld_graph_by_item *
417 * *
418 * Purpose: finds already existing graph, using an item *
419 * *
420 * Return value: upon successful completion return pointer to the graph *
421 * *
422 ******************************************************************************/
lld_graph_by_item(zbx_vector_ptr_t * graphs,zbx_uint64_t itemid)423 static zbx_lld_graph_t *lld_graph_by_item(zbx_vector_ptr_t *graphs, zbx_uint64_t itemid)
424 {
425 int i, j;
426 zbx_lld_graph_t *graph;
427 zbx_lld_gitem_t *gitem;
428
429 for (i = 0; i < graphs->values_num; i++)
430 {
431 graph = (zbx_lld_graph_t *)graphs->values[i];
432
433 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
434 continue;
435
436 for (j = 0; j < graph->gitems.values_num; j++)
437 {
438 gitem = (zbx_lld_gitem_t *)graph->gitems.values[j];
439
440 if (gitem->itemid == itemid)
441 return graph;
442 }
443 }
444
445 return NULL;
446 }
447
448 /******************************************************************************
449 * *
450 * Function: lld_graph_get *
451 * *
452 * Purpose: finds already existing graph, using an item prototype and items *
453 * already created by it *
454 * *
455 * Return value: upon successful completion return pointer to the graph *
456 * *
457 ******************************************************************************/
lld_graph_get(zbx_vector_ptr_t * graphs,const zbx_vector_ptr_t * item_links)458 static zbx_lld_graph_t *lld_graph_get(zbx_vector_ptr_t *graphs, const zbx_vector_ptr_t *item_links)
459 {
460 int i;
461 zbx_lld_graph_t *graph;
462
463 for (i = 0; i < item_links->values_num; i++)
464 {
465 const zbx_lld_item_link_t *item_link = (zbx_lld_item_link_t *)item_links->values[i];
466
467 if (NULL != (graph = lld_graph_by_item(graphs, item_link->itemid)))
468 return graph;
469 }
470
471 return NULL;
472 }
473
474 /******************************************************************************
475 * *
476 * Function: lld_item_get *
477 * *
478 * Purpose: finds already created item when itemid_proto is an item prototype *
479 * or return itemid_proto as itemid if it's a normal item *
480 * *
481 * Return value: SUCCEED if item successfully processed, FAIL - otherwise *
482 * *
483 ******************************************************************************/
lld_item_get(zbx_uint64_t itemid_proto,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * item_links,zbx_uint64_t * itemid)484 static int lld_item_get(zbx_uint64_t itemid_proto, const zbx_vector_ptr_t *items,
485 const zbx_vector_ptr_t *item_links, zbx_uint64_t *itemid)
486 {
487 int index;
488 zbx_lld_item_t *item_proto;
489 zbx_lld_item_link_t *item_link;
490
491 if (FAIL == (index = zbx_vector_ptr_bsearch(items, &itemid_proto, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC)))
492 return FAIL;
493
494 item_proto = (zbx_lld_item_t *)items->values[index];
495
496 if (0 != (item_proto->flags & ZBX_FLAG_DISCOVERY_PROTOTYPE))
497 {
498 index = zbx_vector_ptr_bsearch(item_links, &item_proto->itemid, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
499
500 if (FAIL == index)
501 return FAIL;
502
503 item_link = (zbx_lld_item_link_t *)item_links->values[index];
504
505 *itemid = item_link->itemid;
506 }
507 else
508 *itemid = item_proto->itemid;
509
510 return SUCCEED;
511 }
512
lld_gitems_make(const zbx_vector_ptr_t * gitems_proto,zbx_vector_ptr_t * gitems,const zbx_vector_ptr_t * items,const zbx_vector_ptr_t * item_links)513 static int lld_gitems_make(const zbx_vector_ptr_t *gitems_proto, zbx_vector_ptr_t *gitems,
514 const zbx_vector_ptr_t *items, const zbx_vector_ptr_t *item_links)
515 {
516 int i, ret = FAIL;
517 const zbx_lld_gitem_t *gitem_proto;
518 zbx_lld_gitem_t *gitem;
519 zbx_uint64_t itemid;
520
521 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
522
523 for (i = 0; i < gitems_proto->values_num; i++)
524 {
525 gitem_proto = (zbx_lld_gitem_t *)gitems_proto->values[i];
526
527 if (SUCCEED != lld_item_get(gitem_proto->itemid, items, item_links, &itemid))
528 goto out;
529
530 if (i == gitems->values_num)
531 {
532 gitem = (zbx_lld_gitem_t *)zbx_malloc(NULL, sizeof(zbx_lld_gitem_t));
533
534 gitem->gitemid = 0;
535 gitem->itemid = itemid;
536 gitem->drawtype = gitem_proto->drawtype;
537 gitem->sortorder = gitem_proto->sortorder;
538 gitem->color = zbx_strdup(NULL, gitem_proto->color);
539 gitem->yaxisside = gitem_proto->yaxisside;
540 gitem->calc_fnc = gitem_proto->calc_fnc;
541 gitem->type = gitem_proto->type;
542
543 gitem->flags = ZBX_FLAG_LLD_GITEM_DISCOVERED;
544
545 zbx_vector_ptr_append(gitems, gitem);
546 }
547 else
548 {
549 gitem = (zbx_lld_gitem_t *)gitems->values[i];
550
551 if (gitem->itemid != itemid)
552 {
553 gitem->itemid = itemid;
554 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_ITEMID;
555 }
556
557 if (gitem->drawtype != gitem_proto->drawtype)
558 {
559 gitem->drawtype = gitem_proto->drawtype;
560 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_DRAWTYPE;
561 }
562
563 if (gitem->sortorder != gitem_proto->sortorder)
564 {
565 gitem->sortorder = gitem_proto->sortorder;
566 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_SORTORDER;
567 }
568
569 if (0 != strcmp(gitem->color, gitem_proto->color))
570 {
571 gitem->color = zbx_strdup(gitem->color, gitem_proto->color);
572 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_COLOR;
573 }
574
575 if (gitem->yaxisside != gitem_proto->yaxisside)
576 {
577 gitem->yaxisside = gitem_proto->yaxisside;
578 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_YAXISSIDE;
579 }
580
581 if (gitem->calc_fnc != gitem_proto->calc_fnc)
582 {
583 gitem->calc_fnc = gitem_proto->calc_fnc;
584 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_CALC_FNC;
585 }
586
587 if (gitem->type != gitem_proto->type)
588 {
589 gitem->type = gitem_proto->type;
590 gitem->flags |= ZBX_FLAG_LLD_GITEM_UPDATE_TYPE;
591 }
592
593 gitem->flags |= ZBX_FLAG_LLD_GITEM_DISCOVERED;
594 }
595 }
596
597 for (; i < gitems->values_num; i++)
598 {
599 gitem = (zbx_lld_gitem_t *)gitems->values[i];
600
601 gitem->flags |= ZBX_FLAG_LLD_GITEM_DELETE;
602 }
603
604 ret = SUCCEED;
605 out:
606 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
607
608 return ret;
609 }
610
611 /******************************************************************************
612 * *
613 * Function: lld_graph_make *
614 * *
615 * Purpose: create a graph based on lld rule and add it to the list *
616 * *
617 ******************************************************************************/
lld_graph_make(const zbx_vector_ptr_t * gitems_proto,zbx_vector_ptr_t * graphs,zbx_vector_ptr_t * items,const char * name_proto,zbx_uint64_t ymin_itemid_proto,zbx_uint64_t ymax_itemid_proto,unsigned char discover_proto,const zbx_lld_row_t * lld_row,const zbx_vector_ptr_t * lld_macro_paths)618 static void lld_graph_make(const zbx_vector_ptr_t *gitems_proto, zbx_vector_ptr_t *graphs, zbx_vector_ptr_t *items,
619 const char *name_proto, zbx_uint64_t ymin_itemid_proto, zbx_uint64_t ymax_itemid_proto,
620 unsigned char discover_proto, const zbx_lld_row_t *lld_row, const zbx_vector_ptr_t *lld_macro_paths)
621 {
622 zbx_lld_graph_t *graph = NULL;
623 char *buffer = NULL;
624 const struct zbx_json_parse *jp_row = &lld_row->jp_row;
625 zbx_uint64_t ymin_itemid, ymax_itemid;
626
627 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
628
629 if (0 == ymin_itemid_proto)
630 ymin_itemid = 0;
631 else if (SUCCEED != lld_item_get(ymin_itemid_proto, items, &lld_row->item_links, &ymin_itemid))
632 goto out;
633
634 if (0 == ymax_itemid_proto)
635 ymax_itemid = 0;
636 else if (SUCCEED != lld_item_get(ymax_itemid_proto, items, &lld_row->item_links, &ymax_itemid))
637 goto out;
638
639 if (NULL != (graph = lld_graph_get(graphs, &lld_row->item_links)))
640 {
641 buffer = zbx_strdup(buffer, name_proto);
642 substitute_lld_macros(&buffer, jp_row, lld_macro_paths, ZBX_MACRO_SIMPLE, NULL, 0);
643 zbx_lrtrim(buffer, ZBX_WHITESPACE);
644 if (0 != strcmp(graph->name, buffer))
645 {
646 graph->name_orig = graph->name;
647 graph->name = buffer;
648 buffer = NULL;
649 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_NAME;
650 }
651
652 lld_override_graph(&lld_row->overrides, graph->name, &discover_proto);
653
654 if (ZBX_PROTOTYPE_NO_DISCOVER == discover_proto)
655 goto out;
656
657 if (graph->ymin_itemid != ymin_itemid)
658 {
659 graph->ymin_itemid = ymin_itemid;
660 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_ITEMID;
661 }
662
663 if (graph->ymax_itemid != ymax_itemid)
664 {
665 graph->ymax_itemid = ymax_itemid;
666 graph->flags |= ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_ITEMID;
667 }
668 }
669 else
670 {
671 graph = (zbx_lld_graph_t *)zbx_malloc(NULL, sizeof(zbx_lld_graph_t));
672
673 graph->graphid = 0;
674 graph->lastcheck = 0;
675 graph->ts_delete = 0;
676
677 graph->name = zbx_strdup(NULL, name_proto);
678 graph->name_orig = NULL;
679 substitute_lld_macros(&graph->name, jp_row, lld_macro_paths, ZBX_MACRO_SIMPLE, NULL, 0);
680 zbx_lrtrim(graph->name, ZBX_WHITESPACE);
681
682 lld_override_graph(&lld_row->overrides, graph->name, &discover_proto);
683
684 if (ZBX_PROTOTYPE_NO_DISCOVER == discover_proto)
685 {
686 zbx_free(graph->name);
687 zbx_free(graph);
688 goto out;
689 }
690
691 graph->ymin_itemid = ymin_itemid;
692 graph->ymax_itemid = ymax_itemid;
693
694 zbx_vector_ptr_create(&graph->gitems);
695
696 graph->flags = ZBX_FLAG_LLD_GRAPH_UNSET;
697
698 zbx_vector_ptr_append(graphs, graph);
699 }
700
701 if (SUCCEED != lld_gitems_make(gitems_proto, &graph->gitems, items, &lld_row->item_links))
702 return;
703
704 graph->flags |= ZBX_FLAG_LLD_GRAPH_DISCOVERED;
705 out:
706 zbx_free(buffer);
707 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
708 }
709
lld_graphs_make(const zbx_vector_ptr_t * gitems_proto,zbx_vector_ptr_t * graphs,zbx_vector_ptr_t * items,const char * name_proto,zbx_uint64_t ymin_itemid_proto,zbx_uint64_t ymax_itemid_proto,unsigned char discover_proto,const zbx_vector_ptr_t * lld_rows,const zbx_vector_ptr_t * lld_macro_paths)710 static void lld_graphs_make(const zbx_vector_ptr_t *gitems_proto, zbx_vector_ptr_t *graphs, zbx_vector_ptr_t *items,
711 const char *name_proto, zbx_uint64_t ymin_itemid_proto, zbx_uint64_t ymax_itemid_proto,
712 unsigned char discover_proto, const zbx_vector_ptr_t *lld_rows, const zbx_vector_ptr_t *lld_macro_paths)
713 {
714 int i;
715
716 for (i = 0; i < lld_rows->values_num; i++)
717 {
718 zbx_lld_row_t *lld_row = (zbx_lld_row_t *)lld_rows->values[i];
719
720 lld_graph_make(gitems_proto, graphs, items, name_proto, ymin_itemid_proto, ymax_itemid_proto,
721 discover_proto, lld_row, lld_macro_paths);
722 }
723
724 zbx_vector_ptr_sort(graphs, ZBX_DEFAULT_UINT64_PTR_COMPARE_FUNC);
725 }
726
727 /******************************************************************************
728 * *
729 * Function: lld_validate_graph_field *
730 * *
731 ******************************************************************************/
lld_validate_graph_field(zbx_lld_graph_t * graph,char ** field,char ** field_orig,zbx_uint64_t flag,size_t field_len,char ** error)732 static void lld_validate_graph_field(zbx_lld_graph_t *graph, char **field, char **field_orig, zbx_uint64_t flag,
733 size_t field_len, char **error)
734 {
735 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
736 return;
737
738 /* only new graphs or graphs with changed data will be validated */
739 if (0 != graph->graphid && 0 == (graph->flags & flag))
740 return;
741
742 if (SUCCEED != zbx_is_utf8(*field))
743 {
744 zbx_replace_invalid_utf8(*field);
745 *error = zbx_strdcatf(*error, "Cannot %s graph: value \"%s\" has invalid UTF-8 sequence.\n",
746 (0 != graph->graphid ? "update" : "create"), *field);
747 }
748 else if (zbx_strlen_utf8(*field) > field_len)
749 {
750 *error = zbx_strdcatf(*error, "Cannot %s graph: value \"%s\" is too long.\n",
751 (0 != graph->graphid ? "update" : "create"), *field);
752 }
753 else if (ZBX_FLAG_LLD_GRAPH_UPDATE_NAME == flag && '\0' == **field)
754 {
755 *error = zbx_strdcatf(*error, "Cannot %s graph: name is empty.\n",
756 (0 != graph->graphid ? "update" : "create"));
757 }
758 else
759 return;
760
761 if (0 != graph->graphid)
762 lld_field_str_rollback(field, field_orig, &graph->flags, flag);
763 else
764 graph->flags &= ~ZBX_FLAG_LLD_GRAPH_DISCOVERED;
765 }
766
767 /******************************************************************************
768 * *
769 * Function: lld_graphs_validate *
770 * *
771 * Parameters: graphs - [IN] sorted list of graphs *
772 * *
773 ******************************************************************************/
lld_graphs_validate(zbx_uint64_t hostid,zbx_vector_ptr_t * graphs,char ** error)774 static void lld_graphs_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *graphs, char **error)
775 {
776 int i, j;
777 zbx_lld_graph_t *graph, *graph_b;
778 zbx_vector_uint64_t graphids;
779 zbx_vector_str_t names;
780
781 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
782
783 zbx_vector_uint64_create(&graphids);
784 zbx_vector_str_create(&names); /* list of graph names */
785
786 /* checking a validity of the fields */
787
788 for (i = 0; i < graphs->values_num; i++)
789 {
790 graph = (zbx_lld_graph_t *)graphs->values[i];
791
792 lld_validate_graph_field(graph, &graph->name, &graph->name_orig,
793 ZBX_FLAG_LLD_GRAPH_UPDATE_NAME, GRAPH_NAME_LEN, error);
794 }
795
796 /* checking duplicated graph names */
797 for (i = 0; i < graphs->values_num; i++)
798 {
799 graph = (zbx_lld_graph_t *)graphs->values[i];
800
801 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
802 continue;
803
804 /* only new graphs or graphs with changed name will be validated */
805 if (0 != graph->graphid && 0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_NAME))
806 continue;
807
808 for (j = 0; j < graphs->values_num; j++)
809 {
810 graph_b = (zbx_lld_graph_t *)graphs->values[j];
811
812 if (0 == (graph_b->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED) || i == j)
813 continue;
814
815 if (0 != strcmp(graph->name, graph_b->name))
816 continue;
817
818 *error = zbx_strdcatf(*error, "Cannot %s graph:"
819 " graph with the same name \"%s\" already exists.\n",
820 (0 != graph->graphid ? "update" : "create"), graph->name);
821
822 if (0 != graph->graphid)
823 {
824 lld_field_str_rollback(&graph->name, &graph->name_orig, &graph->flags,
825 ZBX_FLAG_LLD_GRAPH_UPDATE_NAME);
826 }
827 else
828 graph->flags &= ~ZBX_FLAG_LLD_GRAPH_DISCOVERED;
829
830 break;
831 }
832 }
833
834 /* checking duplicated graphs in DB */
835
836 for (i = 0; i < graphs->values_num; i++)
837 {
838 graph = (zbx_lld_graph_t *)graphs->values[i];
839
840 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
841 continue;
842
843 if (0 != graph->graphid)
844 {
845 zbx_vector_uint64_append(&graphids, graph->graphid);
846
847 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_NAME))
848 continue;
849 }
850
851 zbx_vector_str_append(&names, graph->name);
852 }
853
854 if (0 != names.values_num)
855 {
856 DB_RESULT result;
857 DB_ROW row;
858 char *sql = NULL;
859 size_t sql_alloc = 256, sql_offset = 0;
860
861 sql = (char *)zbx_malloc(sql, sql_alloc);
862
863 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
864 "select g.name"
865 " from graphs g,graphs_items gi,items i"
866 " where g.graphid=gi.graphid"
867 " and gi.itemid=i.itemid"
868 " and i.hostid=" ZBX_FS_UI64
869 " and",
870 hostid);
871 DBadd_str_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.name",
872 (const char **)names.values, names.values_num);
873
874 if (0 != graphids.values_num)
875 {
876 zbx_vector_uint64_sort(&graphids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
877 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, " and not");
878 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "g.graphid",
879 graphids.values, graphids.values_num);
880 }
881
882 result = DBselect("%s", sql);
883
884 while (NULL != (row = DBfetch(result)))
885 {
886 for (i = 0; i < graphs->values_num; i++)
887 {
888 graph = (zbx_lld_graph_t *)graphs->values[i];
889
890 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
891 continue;
892
893 if (0 == strcmp(graph->name, row[0]))
894 {
895 *error = zbx_strdcatf(*error, "Cannot %s graph:"
896 " graph with the same name \"%s\" already exists.\n",
897 (0 != graph->graphid ? "update" : "create"), graph->name);
898
899 if (0 != graph->graphid)
900 {
901 lld_field_str_rollback(&graph->name, &graph->name_orig, &graph->flags,
902 ZBX_FLAG_LLD_GRAPH_UPDATE_NAME);
903 }
904 else
905 graph->flags &= ~ZBX_FLAG_LLD_GRAPH_DISCOVERED;
906
907 continue;
908 }
909 }
910 }
911 DBfree_result(result);
912
913 zbx_free(sql);
914 }
915
916 zbx_vector_str_destroy(&names);
917 zbx_vector_uint64_destroy(&graphids);
918
919 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
920 }
921
922 /******************************************************************************
923 * *
924 * Function: lld_graphs_save *
925 * *
926 * Purpose: add or update graphs in database based on discovery rule *
927 * *
928 * Return value: SUCCEED - if graphs were successfully saved or saving *
929 * was not necessary *
930 * FAIL - graphs cannot be saved *
931 * *
932 ******************************************************************************/
lld_graphs_save(zbx_uint64_t hostid,zbx_uint64_t parent_graphid,zbx_vector_ptr_t * graphs,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)933 static int lld_graphs_save(zbx_uint64_t hostid, zbx_uint64_t parent_graphid, zbx_vector_ptr_t *graphs, int width,
934 int height, double yaxismin, double yaxismax, unsigned char show_work_period,
935 unsigned char show_triggers, unsigned char graphtype, unsigned char show_legend, unsigned char show_3d,
936 double percent_left, double percent_right, unsigned char ymin_type, unsigned char ymax_type)
937 {
938 int ret = SUCCEED, i, j, new_graphs = 0, upd_graphs = 0, new_gitems = 0;
939 zbx_lld_graph_t *graph;
940 zbx_lld_gitem_t *gitem;
941 zbx_vector_ptr_t upd_gitems; /* the ordered list of graphs_items which will be updated */
942 zbx_vector_uint64_t del_gitemids;
943
944 zbx_uint64_t graphid = 0, gitemid = 0;
945 char *sql = NULL, *name_esc, *color_esc;
946 size_t sql_alloc = 8 * ZBX_KIBIBYTE, sql_offset = 0;
947 zbx_db_insert_t db_insert, db_insert_gdiscovery, db_insert_gitems;
948
949 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
950
951 zbx_vector_ptr_create(&upd_gitems);
952 zbx_vector_uint64_create(&del_gitemids);
953
954 for (i = 0; i < graphs->values_num; i++)
955 {
956 graph = (zbx_lld_graph_t *)graphs->values[i];
957
958 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
959 continue;
960
961 if (0 == graph->graphid)
962 new_graphs++;
963 else if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE))
964 upd_graphs++;
965
966 for (j = 0; j < graph->gitems.values_num; j++)
967 {
968 gitem = (zbx_lld_gitem_t *)graph->gitems.values[j];
969
970 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_DELETE))
971 {
972 zbx_vector_uint64_append(&del_gitemids, gitem->gitemid);
973 continue;
974 }
975
976 if (0 == (gitem->flags & ZBX_FLAG_LLD_GITEM_DISCOVERED))
977 continue;
978
979 if (0 == gitem->gitemid)
980 new_gitems++;
981 else if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE))
982 zbx_vector_ptr_append(&upd_gitems, gitem);
983 }
984 }
985
986 if (0 == new_graphs && 0 == new_gitems && 0 == upd_graphs && 0 == upd_gitems.values_num &&
987 0 == del_gitemids.values_num)
988 {
989 goto out;
990 }
991
992 DBbegin();
993
994 if (SUCCEED != (ret = DBlock_hostid(hostid)) ||
995 SUCCEED != (ret = DBlock_graphid(parent_graphid)))
996 {
997 /* the host or graph prototype was removed while processing lld rule */
998 DBrollback();
999 goto out;
1000 }
1001
1002 if (0 != new_graphs)
1003 {
1004 graphid = DBget_maxid_num("graphs", new_graphs);
1005
1006 zbx_db_insert_prepare(&db_insert, "graphs", "graphid", "name", "width", "height", "yaxismin",
1007 "yaxismax", "show_work_period", "show_triggers", "graphtype", "show_legend", "show_3d",
1008 "percent_left", "percent_right", "ymin_type", "ymin_itemid", "ymax_type",
1009 "ymax_itemid", "flags", NULL);
1010
1011 zbx_db_insert_prepare(&db_insert_gdiscovery, "graph_discovery", "graphid", "parent_graphid", NULL);
1012 }
1013
1014 if (0 != new_gitems)
1015 {
1016 gitemid = DBget_maxid_num("graphs_items", new_gitems);
1017
1018 zbx_db_insert_prepare(&db_insert_gitems, "graphs_items", "gitemid", "graphid", "itemid", "drawtype",
1019 "sortorder", "color", "yaxisside", "calc_fnc", "type", NULL);
1020 }
1021
1022 if (0 != upd_graphs || 0 != upd_gitems.values_num || 0 != del_gitemids.values_num)
1023 {
1024 sql = (char *)zbx_malloc(sql, sql_alloc);
1025 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1026 }
1027
1028 for (i = 0; i < graphs->values_num; i++)
1029 {
1030 graph = (zbx_lld_graph_t *)graphs->values[i];
1031
1032 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
1033 continue;
1034
1035 if (0 == graph->graphid)
1036 {
1037 zbx_db_insert_add_values(&db_insert, graphid, graph->name, width, height, yaxismin, yaxismax,
1038 (int)show_work_period, (int)show_triggers, (int)graphtype, (int)show_legend,
1039 (int)show_3d, percent_left, percent_right, (int)ymin_type, graph->ymin_itemid,
1040 (int)ymax_type, graph->ymax_itemid, (int)ZBX_FLAG_DISCOVERY_CREATED);
1041
1042 zbx_db_insert_add_values(&db_insert_gdiscovery, graphid, parent_graphid);
1043
1044 graph->graphid = graphid++;
1045 }
1046 else if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE))
1047 {
1048 const char *d = "";
1049
1050 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update graphs set ");
1051
1052 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_NAME))
1053 {
1054 name_esc = DBdyn_escape_string(graph->name);
1055 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", name_esc);
1056 zbx_free(name_esc);
1057 d = ",";
1058 }
1059
1060 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_WIDTH))
1061 {
1062 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%swidth=%d", d, width);
1063 d = ",";
1064 }
1065
1066 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_HEIGHT))
1067 {
1068 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sheight=%d", d, height);
1069 d = ",";
1070 }
1071
1072 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMIN))
1073 {
1074 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxismin=" ZBX_FS_DBL64_SQL, d,
1075 yaxismin);
1076 d = ",";
1077 }
1078
1079 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMAX))
1080 {
1081 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxismax=" ZBX_FS_DBL64_SQL, d,
1082 yaxismax);
1083 d = ",";
1084 }
1085
1086 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_WORK_PERIOD))
1087 {
1088 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_work_period=%d", d,
1089 (int)show_work_period);
1090 d = ",";
1091 }
1092
1093 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_TRIGGERS))
1094 {
1095 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_triggers=%d", d,
1096 (int)show_triggers);
1097 d = ",";
1098 }
1099
1100 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_GRAPHTYPE))
1101 {
1102 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sgraphtype=%d", d,
1103 (int)graphtype);
1104 d = ",";
1105 }
1106
1107 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_LEGEND))
1108 {
1109 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_legend=%d", d,
1110 (int)show_legend);
1111 d = ",";
1112 }
1113
1114 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_3D))
1115 {
1116 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_3d=%d", d, (int)show_3d);
1117 d = ",";
1118 }
1119
1120 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_LEFT))
1121 {
1122 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spercent_left=" ZBX_FS_DBL64_SQL, d,
1123 percent_left);
1124 d = ",";
1125 }
1126
1127 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_RIGHT))
1128 {
1129 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
1130 "%spercent_right=" ZBX_FS_DBL64_SQL, d, percent_right);
1131 d = ",";
1132 }
1133
1134 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_TYPE))
1135 {
1136 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symin_type=%d", d,
1137 (int)ymin_type);
1138 d = ",";
1139 }
1140
1141 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_ITEMID))
1142 {
1143 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symin_itemid=%s", d,
1144 DBsql_id_ins(graph->ymin_itemid));
1145 d = ",";
1146 }
1147
1148 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_TYPE))
1149 {
1150 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symax_type=%d", d,
1151 (int)ymax_type);
1152 d = ",";
1153 }
1154
1155 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_ITEMID))
1156 {
1157 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symax_itemid=%s", d,
1158 DBsql_id_ins(graph->ymax_itemid));
1159 }
1160
1161 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where graphid=" ZBX_FS_UI64 ";\n",
1162 graph->graphid);
1163 }
1164
1165 for (j = 0; j < graph->gitems.values_num; j++)
1166 {
1167 gitem = (zbx_lld_gitem_t *)graph->gitems.values[j];
1168
1169 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_DELETE))
1170 continue;
1171
1172 if (0 == (gitem->flags & ZBX_FLAG_LLD_GITEM_DISCOVERED))
1173 continue;
1174
1175 if (0 == gitem->gitemid)
1176 {
1177 zbx_db_insert_add_values(&db_insert_gitems, gitemid, graph->graphid, gitem->itemid,
1178 (int)gitem->drawtype, gitem->sortorder, gitem->color,
1179 (int)gitem->yaxisside, (int)gitem->calc_fnc, (int)gitem->type);
1180
1181 gitem->gitemid = gitemid++;
1182 }
1183 }
1184 }
1185
1186 for (i = 0; i < upd_gitems.values_num; i++)
1187 {
1188 const char *d = "";
1189
1190 gitem = (zbx_lld_gitem_t *)upd_gitems.values[i];
1191
1192 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update graphs_items set ");
1193
1194 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_ITEMID))
1195 {
1196 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "itemid=" ZBX_FS_UI64, gitem->itemid);
1197 d = ",";
1198 }
1199
1200 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_DRAWTYPE))
1201 {
1202 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdrawtype=%d", d, (int)gitem->drawtype);
1203 d = ",";
1204 }
1205
1206 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_SORTORDER))
1207 {
1208 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ssortorder=%d", d, gitem->sortorder);
1209 d = ",";
1210 }
1211
1212 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_COLOR))
1213 {
1214 color_esc = DBdyn_escape_string(gitem->color);
1215 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scolor='%s'", d, color_esc);
1216 zbx_free(color_esc);
1217 d = ",";
1218 }
1219
1220 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_YAXISSIDE))
1221 {
1222 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxisside=%d", d,
1223 (int)gitem->yaxisside);
1224 d = ",";
1225 }
1226
1227 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_CALC_FNC))
1228 {
1229 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scalc_fnc=%d", d, (int)gitem->calc_fnc);
1230 d = ",";
1231 }
1232
1233 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_TYPE))
1234 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%stype=%d", d, (int)gitem->type);
1235
1236 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where gitemid=" ZBX_FS_UI64 ";\n",
1237 gitem->gitemid);
1238 }
1239
1240 if (0 != del_gitemids.values_num)
1241 {
1242 zbx_vector_uint64_sort(&del_gitemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1243
1244 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from graphs_items where");
1245 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "gitemid",
1246 del_gitemids.values, del_gitemids.values_num);
1247 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1248 }
1249
1250 if (0 != upd_graphs || 0 != upd_gitems.values_num || 0 != del_gitemids.values_num)
1251 {
1252 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1253 DBexecute("%s", sql);
1254 zbx_free(sql);
1255 }
1256
1257 if (0 != new_graphs)
1258 {
1259 zbx_db_insert_execute(&db_insert);
1260 zbx_db_insert_clean(&db_insert);
1261
1262 zbx_db_insert_execute(&db_insert_gdiscovery);
1263 zbx_db_insert_clean(&db_insert_gdiscovery);
1264 }
1265
1266 if (0 != new_gitems)
1267 {
1268 zbx_db_insert_execute(&db_insert_gitems);
1269 zbx_db_insert_clean(&db_insert_gitems);
1270 }
1271
1272 DBcommit();
1273 out:
1274 zbx_vector_uint64_destroy(&del_gitemids);
1275 zbx_vector_ptr_destroy(&upd_gitems);
1276
1277 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1278
1279 return ret;
1280 }
1281
get_graph_info(const void * object,zbx_uint64_t * id,int * discovery_flag,int * lastcheck,int * ts_delete)1282 static void get_graph_info(const void *object, zbx_uint64_t *id, int *discovery_flag, int *lastcheck,
1283 int *ts_delete)
1284 {
1285 zbx_lld_graph_t *graph;
1286
1287 graph = (zbx_lld_graph_t *)object;
1288
1289 *id = graph->graphid;
1290 *discovery_flag = graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED;
1291 *lastcheck = graph->lastcheck;
1292 *ts_delete = graph->ts_delete;
1293 }
1294
1295 /******************************************************************************
1296 * *
1297 * Function: lld_update_graphs *
1298 * *
1299 * Purpose: add or update graphs for discovery item *
1300 * *
1301 * Parameters: hostid - [IN] host identificator from database *
1302 * agent - [IN] discovery item identificator from database *
1303 * jp_data - [IN] received data *
1304 * *
1305 * Return value: SUCCEED - if graphs were successfully added/updated or *
1306 * adding/updating was not necessary *
1307 * FAIL - graphs cannot be added/updated *
1308 * *
1309 * Author: Alexander Vladishev *
1310 * *
1311 ******************************************************************************/
lld_update_graphs(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,const zbx_vector_ptr_t * lld_macro_paths,char ** error,int lifetime,int lastcheck)1312 int lld_update_graphs(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows,
1313 const zbx_vector_ptr_t *lld_macro_paths, char **error, int lifetime, int lastcheck)
1314 {
1315 int ret = SUCCEED;
1316 DB_RESULT result;
1317 DB_ROW row;
1318 zbx_vector_ptr_t graphs;
1319 zbx_vector_ptr_t gitems_proto;
1320 zbx_vector_ptr_t items;
1321
1322 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
1323
1324 zbx_vector_ptr_create(&graphs); /* list of graphs which were created or will be created or */
1325 /* updated by the graph prototype */
1326 zbx_vector_ptr_create(&gitems_proto); /* list of graphs_items which are used by the graph prototype */
1327 zbx_vector_ptr_create(&items); /* list of items which are related to the graph prototype */
1328
1329 result = DBselect(
1330 "select distinct g.graphid,g.name,g.width,g.height,g.yaxismin,g.yaxismax,g.show_work_period,"
1331 "g.show_triggers,g.graphtype,g.show_legend,g.show_3d,g.percent_left,g.percent_right,"
1332 "g.ymin_type,g.ymin_itemid,g.ymax_type,g.ymax_itemid,g.discover"
1333 " from graphs g,graphs_items gi,items i,item_discovery id"
1334 " where g.graphid=gi.graphid"
1335 " and gi.itemid=i.itemid"
1336 " and i.itemid=id.itemid"
1337 " and id.parent_itemid=" ZBX_FS_UI64,
1338 lld_ruleid);
1339
1340 while (SUCCEED == ret && NULL != (row = DBfetch(result)))
1341 {
1342 zbx_uint64_t parent_graphid, ymin_itemid_proto, ymax_itemid_proto;
1343 const char *name_proto;
1344 int width, height;
1345 double yaxismin, yaxismax, percent_left, percent_right;
1346 unsigned char show_work_period, show_triggers, graphtype, show_legend, show_3d,
1347 ymin_type, ymax_type, discover_proto;
1348
1349 ZBX_STR2UINT64(parent_graphid, row[0]);
1350 name_proto = row[1];
1351 width = atoi(row[2]);
1352 height = atoi(row[3]);
1353 yaxismin = atof(row[4]);
1354 yaxismax = atof(row[5]);
1355 ZBX_STR2UCHAR(show_work_period, row[6]);
1356 ZBX_STR2UCHAR(show_triggers, row[7]);
1357 ZBX_STR2UCHAR(graphtype, row[8]);
1358 ZBX_STR2UCHAR(show_legend, row[9]);
1359 ZBX_STR2UCHAR(show_3d, row[10]);
1360 percent_left = atof(row[11]);
1361 percent_right = atof(row[12]);
1362 ZBX_STR2UCHAR(ymin_type, row[13]);
1363 ZBX_DBROW2UINT64(ymin_itemid_proto, row[14]);
1364 ZBX_STR2UCHAR(ymax_type, row[15]);
1365 ZBX_DBROW2UINT64(ymax_itemid_proto, row[16]);
1366 ZBX_STR2UCHAR(discover_proto, row[17]);
1367
1368 lld_graphs_get(parent_graphid, &graphs, width, height, yaxismin, yaxismax, show_work_period,
1369 show_triggers, graphtype, show_legend, show_3d, percent_left, percent_right,
1370 ymin_type, ymax_type);
1371 lld_gitems_get(parent_graphid, &gitems_proto, &graphs);
1372 lld_items_get(&gitems_proto, ymin_itemid_proto, ymax_itemid_proto, &items);
1373
1374 /* making graphs */
1375
1376 lld_graphs_make(&gitems_proto, &graphs, &items, name_proto, ymin_itemid_proto, ymax_itemid_proto,
1377 discover_proto, lld_rows, lld_macro_paths);
1378 lld_graphs_validate(hostid, &graphs, error);
1379 ret = lld_graphs_save(hostid, parent_graphid, &graphs, width, height, yaxismin, yaxismax,
1380 show_work_period, show_triggers, graphtype, show_legend, show_3d, percent_left,
1381 percent_right, ymin_type, ymax_type);
1382
1383 lld_remove_lost_objects("graph_discovery", "graphid", &graphs, lifetime, lastcheck, DBdelete_graphs,
1384 get_graph_info);
1385
1386 lld_items_free(&items);
1387 lld_gitems_free(&gitems_proto);
1388 lld_graphs_free(&graphs);
1389 }
1390 DBfree_result(result);
1391
1392 zbx_vector_ptr_destroy(&items);
1393 zbx_vector_ptr_destroy(&gitems_proto);
1394 zbx_vector_ptr_destroy(&graphs);
1395
1396 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
1397
1398 return ret;
1399 }
1400