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_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 = 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_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 = 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_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_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_discovery_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_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_discovery_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 = 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 {
989 /* the host was removed while processing lld rule */
990 DBrollback();
991 goto out;
992 }
993
994 if (0 != new_graphs)
995 {
996 graphid = DBget_maxid_num("graphs", new_graphs);
997
998 zbx_db_insert_prepare(&db_insert, "graphs", "graphid", "name", "width", "height", "yaxismin",
999 "yaxismax", "show_work_period", "show_triggers", "graphtype", "show_legend", "show_3d",
1000 "percent_left", "percent_right", "ymin_type", "ymin_itemid", "ymax_type",
1001 "ymax_itemid", "flags", NULL);
1002
1003 zbx_db_insert_prepare(&db_insert_gdiscovery, "graph_discovery", "graphid", "parent_graphid", NULL);
1004 }
1005
1006 if (0 != new_gitems)
1007 {
1008 gitemid = DBget_maxid_num("graphs_items", new_gitems);
1009
1010 zbx_db_insert_prepare(&db_insert_gitems, "graphs_items", "gitemid", "graphid", "itemid", "drawtype",
1011 "sortorder", "color", "yaxisside", "calc_fnc", "type", NULL);
1012 }
1013
1014 if (0 != upd_graphs || 0 != upd_gitems.values_num || 0 != del_gitemids.values_num)
1015 {
1016 sql = zbx_malloc(sql, sql_alloc);
1017 DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
1018 }
1019
1020 for (i = 0; i < graphs->values_num; i++)
1021 {
1022 graph = (zbx_lld_graph_t *)graphs->values[i];
1023
1024 if (0 == (graph->flags & ZBX_FLAG_LLD_GRAPH_DISCOVERED))
1025 continue;
1026
1027 if (0 == graph->graphid)
1028 {
1029 zbx_db_insert_add_values(&db_insert, graphid, graph->name, width, height, yaxismin, yaxismax,
1030 (int)show_work_period, (int)show_triggers, (int)graphtype, (int)show_legend,
1031 (int)show_3d, percent_left, percent_right, (int)ymin_type, graph->ymin_itemid,
1032 (int)ymax_type, graph->ymax_itemid, (int)ZBX_FLAG_DISCOVERY_CREATED);
1033
1034 zbx_db_insert_add_values(&db_insert_gdiscovery, graphid, parent_graphid);
1035
1036 graph->graphid = graphid++;
1037 }
1038 else if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE))
1039 {
1040 const char *d = "";
1041
1042 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update graphs set ");
1043
1044 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_NAME))
1045 {
1046 name_esc = DBdyn_escape_string(graph->name);
1047 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "name='%s'", name_esc);
1048 zbx_free(name_esc);
1049 d = ",";
1050 }
1051
1052 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_WIDTH))
1053 {
1054 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%swidth=%d", d, width);
1055 d = ",";
1056 }
1057
1058 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_HEIGHT))
1059 {
1060 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sheight=%d", d, height);
1061 d = ",";
1062 }
1063
1064 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMIN))
1065 {
1066 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxismin=" ZBX_FS_DBL, d,
1067 yaxismin);
1068 d = ",";
1069 }
1070
1071 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YAXISMAX))
1072 {
1073 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxismax=" ZBX_FS_DBL, d,
1074 yaxismax);
1075 d = ",";
1076 }
1077
1078 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_WORK_PERIOD))
1079 {
1080 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_work_period=%d", d,
1081 (int)show_work_period);
1082 d = ",";
1083 }
1084
1085 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_TRIGGERS))
1086 {
1087 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_triggers=%d", d,
1088 (int)show_triggers);
1089 d = ",";
1090 }
1091
1092 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_GRAPHTYPE))
1093 {
1094 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sgraphtype=%d", d,
1095 (int)graphtype);
1096 d = ",";
1097 }
1098
1099 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_LEGEND))
1100 {
1101 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_legend=%d", d,
1102 (int)show_legend);
1103 d = ",";
1104 }
1105
1106 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_SHOW_3D))
1107 {
1108 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sshow_3d=%d", d, (int)show_3d);
1109 d = ",";
1110 }
1111
1112 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_LEFT))
1113 {
1114 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spercent_left=" ZBX_FS_DBL, d,
1115 percent_left);
1116 d = ",";
1117 }
1118
1119 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_PERCENT_RIGHT))
1120 {
1121 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%spercent_right=" ZBX_FS_DBL, d,
1122 percent_right);
1123 d = ",";
1124 }
1125
1126 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_TYPE))
1127 {
1128 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symin_type=%d", d,
1129 (int)ymin_type);
1130 d = ",";
1131 }
1132
1133 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMIN_ITEMID))
1134 {
1135 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symin_itemid=%s", d,
1136 DBsql_id_ins(graph->ymin_itemid));
1137 d = ",";
1138 }
1139
1140 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_TYPE))
1141 {
1142 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symax_type=%d", d,
1143 (int)ymax_type);
1144 d = ",";
1145 }
1146
1147 if (0 != (graph->flags & ZBX_FLAG_LLD_GRAPH_UPDATE_YMAX_ITEMID))
1148 {
1149 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%symax_itemid=%s", d,
1150 DBsql_id_ins(graph->ymax_itemid));
1151 }
1152
1153 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where graphid=" ZBX_FS_UI64 ";\n",
1154 graph->graphid);
1155 }
1156
1157 for (j = 0; j < graph->gitems.values_num; j++)
1158 {
1159 gitem = (zbx_lld_gitem_t *)graph->gitems.values[j];
1160
1161 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_DELETE))
1162 continue;
1163
1164 if (0 == (gitem->flags & ZBX_FLAG_LLD_GITEM_DISCOVERED))
1165 continue;
1166
1167 if (0 == gitem->gitemid)
1168 {
1169 zbx_db_insert_add_values(&db_insert_gitems, gitemid, graph->graphid, gitem->itemid,
1170 (int)gitem->drawtype, gitem->sortorder, gitem->color,
1171 (int)gitem->yaxisside, (int)gitem->calc_fnc, (int)gitem->type);
1172
1173 gitem->gitemid = gitemid++;
1174 }
1175 }
1176 }
1177
1178 for (i = 0; i < upd_gitems.values_num; i++)
1179 {
1180 const char *d = "";
1181
1182 gitem = (zbx_lld_gitem_t *)upd_gitems.values[i];
1183
1184 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "update graphs_items set ");
1185
1186 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_ITEMID))
1187 {
1188 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "itemid=" ZBX_FS_UI64, gitem->itemid);
1189 d = ",";
1190 }
1191
1192 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_DRAWTYPE))
1193 {
1194 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%sdrawtype=%d", d, (int)gitem->drawtype);
1195 d = ",";
1196 }
1197
1198 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_SORTORDER))
1199 {
1200 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%ssortorder=%d", d, gitem->sortorder);
1201 d = ",";
1202 }
1203
1204 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_COLOR))
1205 {
1206 color_esc = DBdyn_escape_string(gitem->color);
1207 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scolor='%s'", d, color_esc);
1208 zbx_free(color_esc);
1209 d = ",";
1210 }
1211
1212 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_YAXISSIDE))
1213 {
1214 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%syaxisside=%d", d,
1215 (int)gitem->yaxisside);
1216 d = ",";
1217 }
1218
1219 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_CALC_FNC))
1220 {
1221 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%scalc_fnc=%d", d, (int)gitem->calc_fnc);
1222 d = ",";
1223 }
1224
1225 if (0 != (gitem->flags & ZBX_FLAG_LLD_GITEM_UPDATE_TYPE))
1226 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "%stype=%d", d, (int)gitem->type);
1227
1228 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, " where gitemid=" ZBX_FS_UI64 ";\n",
1229 gitem->gitemid);
1230 }
1231
1232 if (0 != del_gitemids.values_num)
1233 {
1234 zbx_vector_uint64_sort(&del_gitemids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
1235
1236 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, "delete from graphs_items where");
1237 DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, "gitemid",
1238 del_gitemids.values, del_gitemids.values_num);
1239 zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
1240 }
1241
1242 if (0 != upd_graphs || 0 != upd_gitems.values_num || 0 != del_gitemids.values_num)
1243 {
1244 DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
1245 DBexecute("%s", sql);
1246 zbx_free(sql);
1247 }
1248
1249 if (0 != new_graphs)
1250 {
1251 zbx_db_insert_execute(&db_insert);
1252 zbx_db_insert_clean(&db_insert);
1253
1254 zbx_db_insert_execute(&db_insert_gdiscovery);
1255 zbx_db_insert_clean(&db_insert_gdiscovery);
1256 }
1257
1258 if (0 != new_gitems)
1259 {
1260 zbx_db_insert_execute(&db_insert_gitems);
1261 zbx_db_insert_clean(&db_insert_gitems);
1262 }
1263
1264 DBcommit();
1265 out:
1266 zbx_vector_uint64_destroy(&del_gitemids);
1267 zbx_vector_ptr_destroy(&upd_gitems);
1268
1269 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1270
1271 return ret;
1272 }
1273
1274 /******************************************************************************
1275 * *
1276 * Function: lld_update_graphs *
1277 * *
1278 * Purpose: add or update graphs for discovery item *
1279 * *
1280 * Parameters: hostid - [IN] host identificator from database *
1281 * agent - [IN] discovery item identificator from database *
1282 * jp_data - [IN] received data *
1283 * *
1284 * Return value: SUCCEED - if graphs were successfully added/updated or *
1285 * adding/updating was not necessary *
1286 * FAIL - graphs cannot be added/updated *
1287 * *
1288 * Author: Alexander Vladishev *
1289 * *
1290 ******************************************************************************/
lld_update_graphs(zbx_uint64_t hostid,zbx_uint64_t lld_ruleid,const zbx_vector_ptr_t * lld_rows,char ** error)1291 int lld_update_graphs(zbx_uint64_t hostid, zbx_uint64_t lld_ruleid, const zbx_vector_ptr_t *lld_rows, char **error)
1292 {
1293 const char *__function_name = "lld_update_graphs";
1294
1295 int ret = SUCCEED;
1296 DB_RESULT result;
1297 DB_ROW row;
1298 zbx_vector_ptr_t graphs;
1299 zbx_vector_ptr_t gitems_proto;
1300 zbx_vector_ptr_t items;
1301
1302 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1303
1304 zbx_vector_ptr_create(&graphs); /* list of graphs which were created or will be created or */
1305 /* updated by the graph prototype */
1306 zbx_vector_ptr_create(&gitems_proto); /* list of graphs_items which are used by the graph prototype */
1307 zbx_vector_ptr_create(&items); /* list of items which are related to the graph prototype */
1308
1309 result = DBselect(
1310 "select distinct g.graphid,g.name,g.width,g.height,g.yaxismin,g.yaxismax,g.show_work_period,"
1311 "g.show_triggers,g.graphtype,g.show_legend,g.show_3d,g.percent_left,g.percent_right,"
1312 "g.ymin_type,g.ymin_itemid,g.ymax_type,g.ymax_itemid"
1313 " from graphs g,graphs_items gi,items i,item_discovery id"
1314 " where g.graphid=gi.graphid"
1315 " and gi.itemid=i.itemid"
1316 " and i.itemid=id.itemid"
1317 " and id.parent_itemid=" ZBX_FS_UI64,
1318 lld_ruleid);
1319
1320 while (SUCCEED == ret && NULL != (row = DBfetch(result)))
1321 {
1322 zbx_uint64_t parent_graphid, ymin_itemid_proto, ymax_itemid_proto;
1323 const char *name_proto;
1324 int width, height;
1325 double yaxismin, yaxismax, percent_left, percent_right;
1326 unsigned char show_work_period, show_triggers, graphtype, show_legend, show_3d,
1327 ymin_type, ymax_type;
1328
1329 ZBX_STR2UINT64(parent_graphid, row[0]);
1330 name_proto = row[1];
1331 width = atoi(row[2]);
1332 height = atoi(row[3]);
1333 yaxismin = atof(row[4]);
1334 yaxismax = atof(row[5]);
1335 ZBX_STR2UCHAR(show_work_period, row[6]);
1336 ZBX_STR2UCHAR(show_triggers, row[7]);
1337 ZBX_STR2UCHAR(graphtype, row[8]);
1338 ZBX_STR2UCHAR(show_legend, row[9]);
1339 ZBX_STR2UCHAR(show_3d, row[10]);
1340 percent_left = atof(row[11]);
1341 percent_right = atof(row[12]);
1342 ZBX_STR2UCHAR(ymin_type, row[13]);
1343 ZBX_DBROW2UINT64(ymin_itemid_proto, row[14]);
1344 ZBX_STR2UCHAR(ymax_type, row[15]);
1345 ZBX_DBROW2UINT64(ymax_itemid_proto, row[16]);
1346
1347 lld_graphs_get(parent_graphid, &graphs, width, height, yaxismin, yaxismax, show_work_period,
1348 show_triggers, graphtype, show_legend, show_3d, percent_left, percent_right,
1349 ymin_type, ymax_type);
1350 lld_gitems_get(parent_graphid, &gitems_proto, &graphs);
1351 lld_items_get(&gitems_proto, ymin_itemid_proto, ymax_itemid_proto, &items);
1352
1353 /* making graphs */
1354
1355 lld_graphs_make(&gitems_proto, &graphs, &items, name_proto, ymin_itemid_proto, ymax_itemid_proto,
1356 lld_rows);
1357 lld_graphs_validate(hostid, &graphs, error);
1358 ret = lld_graphs_save(hostid, parent_graphid, &graphs, width, height, yaxismin, yaxismax,
1359 show_work_period, show_triggers, graphtype, show_legend, show_3d, percent_left,
1360 percent_right, ymin_type, ymax_type);
1361
1362 lld_items_free(&items);
1363 lld_gitems_free(&gitems_proto);
1364 lld_graphs_free(&graphs);
1365 }
1366 DBfree_result(result);
1367
1368 zbx_vector_ptr_destroy(&items);
1369 zbx_vector_ptr_destroy(&gitems_proto);
1370 zbx_vector_ptr_destroy(&graphs);
1371
1372 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
1373
1374 return ret;
1375 }
1376