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 "log.h"
22 #include "db.h"
23 
24 /******************************************************************************
25  *                                                                            *
26  * Function: lld_field_str_rollback                                           *
27  *                                                                            *
28  * Author: Alexander Vladishev                                                *
29  *                                                                            *
30  ******************************************************************************/
lld_field_str_rollback(char ** field,char ** field_orig,zbx_uint64_t * flags,zbx_uint64_t flag)31 void	lld_field_str_rollback(char **field, char **field_orig, zbx_uint64_t *flags, zbx_uint64_t flag)
32 {
33 	if (0 == (*flags & flag))
34 		return;
35 
36 	zbx_free(*field);
37 	*field = *field_orig;
38 	*field_orig = NULL;
39 	*flags &= ~flag;
40 }
41 
42 /******************************************************************************
43  *                                                                            *
44  * Function: lld_field_uint64_rollback                                        *
45  *                                                                            *
46  * Author: Alexander Vladishev                                                *
47  *                                                                            *
48  ******************************************************************************/
lld_field_uint64_rollback(zbx_uint64_t * field,zbx_uint64_t * field_orig,zbx_uint64_t * flags,zbx_uint64_t flag)49 void	lld_field_uint64_rollback(zbx_uint64_t *field, zbx_uint64_t *field_orig, zbx_uint64_t *flags, zbx_uint64_t flag)
50 {
51 	if (0 == (*flags & flag))
52 		return;
53 
54 	*field = *field_orig;
55 	*field_orig = 0;
56 	*flags &= ~flag;
57 }
58 
59 /******************************************************************************
60  *                                                                            *
61  * Function: lld_end_of_life                                                  *
62  *                                                                            *
63  * Purpose: calculate when to delete lost resources in an overflow-safe way   *
64  *                                                                            *
65  ******************************************************************************/
lld_end_of_life(int lastcheck,int lifetime)66 int	lld_end_of_life(int lastcheck, int lifetime)
67 {
68 	return ZBX_JAN_2038 - lastcheck > lifetime ? lastcheck + lifetime : ZBX_JAN_2038;
69 }
70 
71 /******************************************************************************
72  *                                                                            *
73  * Function: lld_remove_lost_objects                                          *
74  *                                                                            *
75  * Purpose: updates lastcheck and ts_delete fields; removes lost resources    *
76  *                                                                            *
77  ******************************************************************************/
lld_remove_lost_objects(const char * table,const char * id_name,const zbx_vector_ptr_t * objects,int lifetime,int lastcheck,delete_ids_f cb,get_object_info_f cb_info)78 void	lld_remove_lost_objects(const char *table, const char *id_name, const zbx_vector_ptr_t *objects,
79 		int lifetime, int lastcheck, delete_ids_f cb, get_object_info_f cb_info)
80 {
81 	char				*sql = NULL;
82 	size_t				sql_alloc = 0, sql_offset = 0;
83 	zbx_vector_uint64_t		del_ids, lc_ids, ts_ids;
84 	zbx_vector_uint64_pair_t	discovery_ts;
85 	int				i;
86 
87 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
88 
89 	if (0 == objects->values_num)
90 		goto out;
91 
92 	zbx_vector_uint64_create(&del_ids);
93 	zbx_vector_uint64_create(&lc_ids);
94 	zbx_vector_uint64_create(&ts_ids);
95 	zbx_vector_uint64_pair_create(&discovery_ts);
96 
97 	for (i = 0; i < objects->values_num; i++)
98 	{
99 		zbx_uint64_t	id;
100 		int		discovery_flag, object_lastcheck, object_ts_delete;
101 
102 		cb_info(objects->values[i], &id, &discovery_flag, &object_lastcheck, &object_ts_delete);
103 
104 		if (0 == id)
105 			continue;
106 
107 		if (0 == discovery_flag)
108 		{
109 			int	ts_delete = lld_end_of_life(object_lastcheck, lifetime);
110 
111 			if (lastcheck > ts_delete)
112 			{
113 				zbx_vector_uint64_append(&del_ids, id);
114 			}
115 			else if (object_ts_delete != ts_delete)
116 			{
117 				zbx_uint64_pair_t	pair;
118 
119 				pair.first = id;
120 				pair.second = ts_delete;
121 				zbx_vector_uint64_pair_append(&discovery_ts, pair);
122 			}
123 		}
124 		else
125 		{
126 			zbx_vector_uint64_append(&lc_ids, id);
127 			if (0 != object_ts_delete)
128 				zbx_vector_uint64_append(&ts_ids, id);
129 		}
130 	}
131 
132 	if (0 == discovery_ts.values_num && 0 == lc_ids.values_num && 0 == ts_ids.values_num &&
133 			0 == del_ids.values_num)
134 	{
135 		goto clean;
136 	}
137 
138 	/* update discovery table */
139 
140 	DBbegin();
141 
142 	DBbegin_multiple_update(&sql, &sql_alloc, &sql_offset);
143 
144 	for (i = 0; i < discovery_ts.values_num; i++)
145 	{
146 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
147 				"update %s"
148 				" set ts_delete=%d"
149 				" where %s=" ZBX_FS_UI64 ";\n",
150 				table, (int)discovery_ts.values[i].second, id_name, discovery_ts.values[i].first);
151 
152 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
153 	}
154 
155 	if (0 != lc_ids.values_num)
156 	{
157 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set lastcheck=%d where",
158 				table, lastcheck);
159 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, id_name,
160 				lc_ids.values, lc_ids.values_num);
161 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
162 
163 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
164 	}
165 
166 	if (0 != ts_ids.values_num)
167 	{
168 		zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset, "update %s set ts_delete=0 where",
169 				table);
170 		DBadd_condition_alloc(&sql, &sql_alloc, &sql_offset, id_name,
171 				ts_ids.values, ts_ids.values_num);
172 		zbx_strcpy_alloc(&sql, &sql_alloc, &sql_offset, ";\n");
173 
174 		DBexecute_overflowed_sql(&sql, &sql_alloc, &sql_offset);
175 	}
176 
177 	DBend_multiple_update(&sql, &sql_alloc, &sql_offset);
178 
179 	if (16 < sql_offset)	/* in ORACLE always present begin..end; */
180 		DBexecute("%s", sql);
181 
182 	zbx_free(sql);
183 
184 	/* remove 'lost' objects */
185 	if (0 != del_ids.values_num)
186 	{
187 		zbx_vector_uint64_sort(&del_ids, ZBX_DEFAULT_UINT64_COMPARE_FUNC);
188 		cb(&del_ids);
189 	}
190 
191 	DBcommit();
192 clean:
193 	zbx_vector_uint64_pair_destroy(&discovery_ts);
194 	zbx_vector_uint64_destroy(&ts_ids);
195 	zbx_vector_uint64_destroy(&lc_ids);
196 	zbx_vector_uint64_destroy(&del_ids);
197 out:
198 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __func__);
199 }
200