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