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_t 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 int i;
144 ZBX_SINGLE_DISKDEVICE_DATA *device = NULL;
145
146 assert(devname);
147
148 zabbix_log(LOG_LEVEL_DEBUG, "In %s() devname:'%s'", __func__, devname);
149
150 LOCK_DISKSTATS;
151 if (0 == DISKDEVICE_COLLECTOR_STARTED(collector))
152 diskstat_shm_init();
153 else
154 diskstat_shm_reattach();
155
156 for (i = 0; i < diskdevices->count; i++)
157 {
158 if (0 == strcmp(devname, diskdevices->device[i].name))
159 {
160 device = &diskdevices->device[i];
161 device->ticks_since_polled = 0;
162 zabbix_log(LOG_LEVEL_DEBUG, "%s() device '%s' found", __func__, devname);
163 break;
164 }
165 }
166 UNLOCK_DISKSTATS;
167
168 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __func__, (void *)device);
169
170 return device;
171 }
172
collector_diskdevice_add(const char * devname)173 ZBX_SINGLE_DISKDEVICE_DATA *collector_diskdevice_add(const char *devname)
174 {
175 ZBX_SINGLE_DISKDEVICE_DATA *device = NULL;
176
177 assert(devname);
178
179 zabbix_log(LOG_LEVEL_DEBUG, "In %s() devname:'%s'", __func__, devname);
180
181 LOCK_DISKSTATS;
182 if (0 == DISKDEVICE_COLLECTOR_STARTED(collector))
183 diskstat_shm_init();
184 else
185 diskstat_shm_reattach();
186
187 if (diskdevices->count == MAX_DISKDEVICES)
188 {
189 zabbix_log(LOG_LEVEL_DEBUG, "%s() collector is full", __func__);
190 goto end;
191 }
192
193 if (diskdevices->count == diskdevices->max_diskdev)
194 diskstat_shm_extend();
195
196 device = &(diskdevices->device[diskdevices->count]);
197 memset(device, 0, sizeof(ZBX_SINGLE_DISKDEVICE_DATA));
198 zbx_strlcpy(device->name, devname, sizeof(device->name));
199 device->index = -1;
200 device->ticks_since_polled = 0;
201 (diskdevices->count)++;
202
203 process_diskstat(device);
204 end:
205 UNLOCK_DISKSTATS;
206
207 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%p", __func__, (void *)device);
208
209 return device;
210 }
211
212 #endif /* _WINDOWS */
213