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 #ifndef _WINDOWS
21
22 #include "common.h"
23 #include "diskdevices.h"
24 #include "stats.h"
25 #include "log.h"
26 #include "mutexs.h"
27
28 extern ZBX_MUTEX diskstats_lock;
29 #define LOCK_DISKSTATS zbx_mutex_lock(&diskstats_lock)
30 #define UNLOCK_DISKSTATS zbx_mutex_unlock(&diskstats_lock)
31
apply_diskstat(ZBX_SINGLE_DISKDEVICE_DATA * device,time_t now,zbx_uint64_t * dstat)32 static void apply_diskstat(ZBX_SINGLE_DISKDEVICE_DATA *device, time_t now, zbx_uint64_t *dstat)
33 {
34 register int i;
35 time_t clock[ZBX_AVG_COUNT], sec;
36 int index[ZBX_AVG_COUNT];
37
38 assert(device);
39
40 device->index++;
41
42 if (MAX_COLLECTOR_HISTORY == device->index)
43 device->index = 0;
44
45 device->clock[device->index] = now;
46 device->r_sect[device->index] = dstat[ZBX_DSTAT_R_SECT];
47 device->r_oper[device->index] = dstat[ZBX_DSTAT_R_OPER];
48 device->r_byte[device->index] = dstat[ZBX_DSTAT_R_BYTE];
49 device->w_sect[device->index] = dstat[ZBX_DSTAT_W_SECT];
50 device->w_oper[device->index] = dstat[ZBX_DSTAT_W_OPER];
51 device->w_byte[device->index] = dstat[ZBX_DSTAT_W_BYTE];
52
53 clock[ZBX_AVG1] = clock[ZBX_AVG5] = clock[ZBX_AVG15] = now + 1;
54 index[ZBX_AVG1] = index[ZBX_AVG5] = index[ZBX_AVG15] = -1;
55
56 for (i = 0; i < MAX_COLLECTOR_HISTORY; i++)
57 {
58 if (0 == device->clock[i])
59 continue;
60
61 #define DISKSTAT(t)\
62 if ((device->clock[i] >= (now - (t * 60))) && (clock[ZBX_AVG ## t] > device->clock[i]))\
63 {\
64 clock[ZBX_AVG ## t] = device->clock[i];\
65 index[ZBX_AVG ## t] = i;\
66 }
67
68 DISKSTAT(1);
69 DISKSTAT(5);
70 DISKSTAT(15);
71 }
72
73 #define SAVE_DISKSTAT(t)\
74 if (-1 == index[ZBX_AVG ## t] || 0 == now - device->clock[index[ZBX_AVG ## t]])\
75 {\
76 device->r_sps[ZBX_AVG ## t] = 0;\
77 device->r_ops[ZBX_AVG ## t] = 0;\
78 device->r_bps[ZBX_AVG ## t] = 0;\
79 device->w_sps[ZBX_AVG ## t] = 0;\
80 device->w_ops[ZBX_AVG ## t] = 0;\
81 device->w_bps[ZBX_AVG ## t] = 0;\
82 }\
83 else\
84 {\
85 sec = now - device->clock[index[ZBX_AVG ## t]];\
86 device->r_sps[ZBX_AVG ## t] = (dstat[ZBX_DSTAT_R_SECT] - device->r_sect[index[ZBX_AVG ## t]]) / (double)sec;\
87 device->r_ops[ZBX_AVG ## t] = (dstat[ZBX_DSTAT_R_OPER] - device->r_oper[index[ZBX_AVG ## t]]) / (double)sec;\
88 device->r_bps[ZBX_AVG ## t] = (dstat[ZBX_DSTAT_R_BYTE] - device->r_byte[index[ZBX_AVG ## t]]) / (double)sec;\
89 device->w_sps[ZBX_AVG ## t] = (dstat[ZBX_DSTAT_W_SECT] - device->w_sect[index[ZBX_AVG ## t]]) / (double)sec;\
90 device->w_ops[ZBX_AVG ## t] = (dstat[ZBX_DSTAT_W_OPER] - device->w_oper[index[ZBX_AVG ## t]]) / (double)sec;\
91 device->w_bps[ZBX_AVG ## t] = (dstat[ZBX_DSTAT_W_BYTE] - device->w_byte[index[ZBX_AVG ## t]]) / (double)sec;\
92 }
93
94 SAVE_DISKSTAT(1);
95 SAVE_DISKSTAT(5);
96 SAVE_DISKSTAT(15);
97 }
98
process_diskstat(ZBX_SINGLE_DISKDEVICE_DATA * device)99 static void process_diskstat(ZBX_SINGLE_DISKDEVICE_DATA *device)
100 {
101 time_t now;
102 zbx_uint64_t dstat[ZBX_DSTAT_MAX];
103
104 now = time(NULL);
105 if (FAIL == get_diskstat(device->name, dstat))
106 return;
107
108 apply_diskstat(device, now, dstat);
109
110 device->ticks_since_polled++;
111 }
112
collect_stats_diskdevices(void)113 void collect_stats_diskdevices(void)
114 {
115 int i;
116
117 LOCK_DISKSTATS;
118 diskstat_shm_reattach();
119
120 for (i = 0; i < diskdevices->count; i++)
121 {
122 process_diskstat(&diskdevices->device[i]);
123
124 /* remove device from collector if not being polled for long time */
125 if (DISKDEVICE_TTL <= diskdevices->device[i].ticks_since_polled)
126 {
127 if ((diskdevices->count - 1) > i)
128 {
129 memcpy(diskdevices->device + i, diskdevices->device + i + 1,
130 sizeof(ZBX_SINGLE_DISKDEVICE_DATA) * (diskdevices->count - i));
131 }
132
133 diskdevices->count--;
134 i--;
135 }
136 }
137
138 UNLOCK_DISKSTATS;
139 }
140
collector_diskdevice_get(const char * devname)141 ZBX_SINGLE_DISKDEVICE_DATA *collector_diskdevice_get(const char *devname)
142 {
143 const char *__function_name = "collector_diskdevice_get";
144 int i;
145 ZBX_SINGLE_DISKDEVICE_DATA *device = NULL;
146
147 assert(devname);
148
149 zabbix_log(LOG_LEVEL_DEBUG, "In %s() devname:'%s'", __function_name, devname);
150
151 LOCK_DISKSTATS;
152 if (0 == DISKDEVICE_COLLECTOR_STARTED(collector))
153 diskstat_shm_init();
154 else
155 diskstat_shm_reattach();
156
157 for (i = 0; i < diskdevices->count; i++)
158 {
159 if (0 == strcmp(devname, diskdevices->device[i].name))
160 {
161 device = &diskdevices->device[i];
162 device->ticks_since_polled = 0;
163 zabbix_log(LOG_LEVEL_DEBUG, "%s() device '%s' found", __function_name, devname);
164 break;
165 }
166 }
167 UNLOCK_DISKSTATS;
168
169 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, device);
170
171 return device;
172 }
173
collector_diskdevice_add(const char * devname)174 ZBX_SINGLE_DISKDEVICE_DATA *collector_diskdevice_add(const char *devname)
175 {
176 const char *__function_name = "collector_diskdevice_add";
177 ZBX_SINGLE_DISKDEVICE_DATA *device = NULL;
178
179 assert(devname);
180
181 zabbix_log(LOG_LEVEL_DEBUG, "In %s() devname:'%s'", __function_name, devname);
182
183 LOCK_DISKSTATS;
184 if (0 == DISKDEVICE_COLLECTOR_STARTED(collector))
185 diskstat_shm_init();
186 else
187 diskstat_shm_reattach();
188
189 if (diskdevices->count == MAX_DISKDEVICES)
190 {
191 zabbix_log(LOG_LEVEL_DEBUG, "%s() collector is full", __function_name);
192 goto end;
193 }
194
195 if (diskdevices->count == diskdevices->max_diskdev)
196 diskstat_shm_extend();
197
198 device = &(diskdevices->device[diskdevices->count]);
199 memset(device, 0, sizeof(ZBX_SINGLE_DISKDEVICE_DATA));
200 zbx_strlcpy(device->name, devname, sizeof(device->name));
201 device->index = -1;
202 device->ticks_since_polled = 0;
203 (diskdevices->count)++;
204
205 process_diskstat(device);
206 end:
207 UNLOCK_DISKSTATS;
208
209 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __function_name, device);
210
211 return device;
212 }
213
214 #endif /* _WINDOWS */
215