"Fossies" - the Fresh Open Source Software Archive 
Member "netxms-3.8.166/src/agent/subagents/sunos/iostat.cpp" (23 Feb 2021, 10432 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "iostat.cpp" see the
Fossies "Dox" file reference documentation.
1 /*
2 ** NetXMS subagent for SunOS/Solaris
3 ** Copyright (C) 2004-2011 Victor Kirhenshtein
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: iostat.cpp
20 **
21 **/
22
23 #include "sunos_subagent.h"
24
25
26 //
27 // Constants
28 //
29
30 #define MAX_DEVICES 255
31 #define HISTORY_SIZE 60
32
33
34 //
35 // Device I/O stats structure
36 //
37
38 struct IO_STATS
39 {
40 // device name
41 char dev[KSTAT_STRLEN];
42
43 // current values
44 QWORD currBytesRead;
45 QWORD currBytesWritten;
46 DWORD currReadOps;
47 DWORD currWriteOps;
48 DWORD currQueue;
49
50 // history - totals for queue, deltas for others
51 QWORD histBytesRead[HISTORY_SIZE];
52 QWORD histBytesWritten[HISTORY_SIZE];
53 DWORD histReadOps[HISTORY_SIZE];
54 DWORD histWriteOps[HISTORY_SIZE];
55 DWORD histQueue[HISTORY_SIZE];
56 };
57
58 /**
59 * Static data
60 */
61 static IO_STATS s_data[MAX_DEVICES + 1];
62 static int s_currSlot = 0; // current history slot
63
64 /**
65 * Process stats for single device
66 */
67 static void ProcessDeviceStats(const char *dev, kstat_io_t *kio)
68 {
69 int i;
70
71 // find device
72 for(i = 1; i <= MAX_DEVICES; i++)
73 if (!strcmp(dev, s_data[i].dev) || (s_data[i].dev[0] == 0))
74 break;
75 if (i > MAX_DEVICES)
76 return; // No more free slots
77
78 if (s_data[i].dev[0] == 0)
79 {
80 // new device
81 AgentWriteDebugLog(5, _T("SunOS: device %hs added to I/O stat collection"), dev);
82 strcpy(s_data[i].dev, dev);
83 }
84 else
85 {
86 // existing device - update history
87 s_data[i].histBytesRead[s_currSlot] = kio->nread - s_data[i].currBytesRead;
88 s_data[i].histBytesWritten[s_currSlot] = kio->nwritten - s_data[i].currBytesWritten;
89 s_data[i].histReadOps[s_currSlot] = kio->reads - s_data[i].currReadOps;
90 s_data[i].histWriteOps[s_currSlot] = kio->writes - s_data[i].currWriteOps;
91 s_data[i].histQueue[s_currSlot] = kio->wcnt + kio->rcnt;
92 }
93
94 // update current values
95 s_data[i].currBytesRead = kio->nread;
96 s_data[i].currBytesWritten = kio->nwritten;
97 s_data[i].currReadOps = kio->reads;
98 s_data[i].currWriteOps = kio->writes;
99 s_data[i].currQueue = kio->wcnt + kio->rcnt;
100 }
101
102 /**
103 * Calculate total values for all devices
104 */
105 static void CalculateTotals()
106 {
107 QWORD br = 0, bw = 0;
108 DWORD r = 0, w = 0, q = 0;
109
110 for(int i = 1; (i <= MAX_DEVICES) && (s_data[i].dev[0] != 0); i++)
111 {
112 br += s_data[i].histBytesRead[s_currSlot];
113 bw += s_data[i].histBytesWritten[s_currSlot];
114 r += s_data[i].histReadOps[s_currSlot];
115 w += s_data[i].histWriteOps[s_currSlot];
116 q += s_data[i].histQueue[s_currSlot];
117 }
118
119 s_data[0].histBytesRead[s_currSlot] = br;
120 s_data[0].histBytesWritten[s_currSlot] = bw;
121 s_data[0].histReadOps[s_currSlot] = r;
122 s_data[0].histWriteOps[s_currSlot] = w;
123 s_data[0].histQueue[s_currSlot] = q;
124 }
125
126 /**
127 * I/O stat collector
128 */
129 THREAD_RESULT THREAD_CALL IOStatCollector(void *arg)
130 {
131 kstat_ctl_t *kc;
132 kstat_t *kp;
133 kstat_io_t kio;
134
135 kstat_lock();
136 kc = kstat_open();
137 kstat_unlock();
138 if (kc == NULL)
139 {
140 AgentWriteLog(EVENTLOG_ERROR_TYPE, _T("SunOS::IOStatCollector: call to kstat_open failed (%s), I/O statistic will not be collected"), _tcserror(errno));
141 return THREAD_OK;
142 }
143
144 memset(s_data, 0, sizeof(IO_STATS) * (MAX_DEVICES + 1));
145 AgentWriteDebugLog(1, _T("SunOS: I/O stat collector thread started"));
146
147 while(!g_bShutdown)
148 {
149 kstat_lock();
150 kstat_chain_update(kc);
151 for(kp = kc->kc_chain; kp != NULL; kp = kp->ks_next)
152 {
153 if (kp->ks_type == KSTAT_TYPE_IO)
154 {
155 kstat_read(kc, kp, &kio);
156 ProcessDeviceStats(kp->ks_name, &kio);
157 }
158 }
159 kstat_unlock();
160 CalculateTotals();
161 s_currSlot++;
162 if (s_currSlot == HISTORY_SIZE)
163 s_currSlot = 0;
164 ThreadSleepMs(1000);
165 }
166
167 AgentWriteDebugLog(1, _T("SunOS: I/O stat collector thread stopped"));
168 kstat_lock();
169 kstat_close(kc);
170 kstat_unlock();
171 return THREAD_OK;
172 }
173
174 /**
175 * Calculate average value for 32bit series
176 */
177 static double CalculateAverage32(DWORD *series)
178 {
179 double sum = 0;
180 for(int i = 0; i < HISTORY_SIZE; i++)
181 sum += series[i];
182 return sum / (double)HISTORY_SIZE;
183 }
184
185 /**
186 * Calculate min value for 32bit series
187 */
188 static DWORD CalculateMin32(DWORD *series)
189 {
190 DWORD val = series[0];
191 for(int i = 1; i < HISTORY_SIZE; i++)
192 if (series[i] < val)
193 val = series[i];
194 return val;
195 }
196
197 /**
198 * Calculate max value for 32bit series
199 */
200 static DWORD CalculateMax32(DWORD *series)
201 {
202 DWORD val = series[0];
203 for(int i = 1; i < HISTORY_SIZE; i++)
204 if (series[i] > val)
205 val = series[i];
206 return val;
207 }
208
209 /**
210 * Calculate average value for 64bit series
211 */
212 static QWORD CalculateAverage64(QWORD *series)
213 {
214 QWORD sum = 0;
215 for(int i = 0; i < HISTORY_SIZE; i++)
216 sum += series[i];
217 return sum / HISTORY_SIZE;
218 }
219
220 /**
221 * Calculate min value for 64bit series
222 */
223 static QWORD CalculateMin64(QWORD *series)
224 {
225 QWORD val = series[0];
226 for(int i = 1; i < HISTORY_SIZE; i++)
227 if (series[i] < val)
228 val = series[i];
229 return val;
230 }
231
232 /**
233 * Calculate max value for 64bit series
234 */
235 static QWORD CalculateMax64(QWORD *series)
236 {
237 QWORD val = series[0];
238 for(int i = 1; i < HISTORY_SIZE; i++)
239 if (series[i] > val)
240 val = series[i];
241 return val;
242 }
243
244 /**
245 * Get total I/O stat value
246 */
247 LONG H_IOStatsTotal(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
248 {
249 LONG rc = SYSINFO_RC_SUCCESS;
250
251 switch(CAST_FROM_POINTER(arg, int))
252 {
253 case IOSTAT_NUM_READS:
254 ret_double(value, CalculateAverage32(s_data[0].histReadOps));
255 break;
256 case IOSTAT_NUM_READS_MIN:
257 ret_uint(value, CalculateMin32(s_data[0].histReadOps));
258 break;
259 case IOSTAT_NUM_READS_MAX:
260 ret_uint(value, CalculateMax32(s_data[0].histReadOps));
261 break;
262 case IOSTAT_NUM_WRITES:
263 ret_double(value, CalculateAverage32(s_data[0].histWriteOps));
264 break;
265 case IOSTAT_NUM_WRITES_MIN:
266 ret_uint(value, CalculateMin32(s_data[0].histWriteOps));
267 break;
268 case IOSTAT_NUM_WRITES_MAX:
269 ret_uint(value, CalculateMax32(s_data[0].histWriteOps));
270 break;
271 case IOSTAT_QUEUE:
272 ret_double(value, CalculateAverage32(s_data[0].histQueue));
273 break;
274 case IOSTAT_QUEUE_MIN:
275 ret_uint(value, CalculateMin32(s_data[0].histQueue));
276 break;
277 case IOSTAT_QUEUE_MAX:
278 ret_uint(value, CalculateMax32(s_data[0].histQueue));
279 break;
280 case IOSTAT_NUM_RBYTES:
281 ret_uint64(value, CalculateAverage64(s_data[0].histBytesRead));
282 break;
283 case IOSTAT_NUM_RBYTES_MIN:
284 ret_uint64(value, CalculateMin64(s_data[0].histBytesRead));
285 break;
286 case IOSTAT_NUM_RBYTES_MAX:
287 ret_uint64(value, CalculateMax64(s_data[0].histBytesRead));
288 break;
289 case IOSTAT_NUM_WBYTES:
290 ret_uint64(value, CalculateAverage64(s_data[0].histBytesWritten));
291 break;
292 case IOSTAT_NUM_WBYTES_MIN:
293 ret_uint64(value, CalculateMin64(s_data[0].histBytesWritten));
294 break;
295 case IOSTAT_NUM_WBYTES_MAX:
296 ret_uint64(value, CalculateMax64(s_data[0].histBytesWritten));
297 break;
298 default:
299 rc = SYSINFO_RC_UNSUPPORTED;
300 break;
301 }
302 return rc;
303 }
304
305 /**
306 * Get I/O stat for specific device
307 */
308 LONG H_IOStats(const TCHAR *cmd, const TCHAR *arg, TCHAR *value, AbstractCommSession *session)
309 {
310 char device[KSTAT_STRLEN];
311 LONG rc = SYSINFO_RC_SUCCESS;
312 int i;
313
314 if (!AgentGetParameterArgA(cmd, 1, device, KSTAT_STRLEN))
315 return SYSINFO_RC_UNSUPPORTED;
316
317 // find device
318 for(i = 1; (i <= MAX_DEVICES) && (s_data[i].dev[0] != 0); i++)
319 if (!strcmp(device, s_data[i].dev))
320 break;
321 if ((i > MAX_DEVICES) || (s_data[i].dev[0] == 0))
322 return SYSINFO_RC_UNSUPPORTED; // unknown device
323
324 switch(CAST_FROM_POINTER(arg, int))
325 {
326 case IOSTAT_NUM_READS:
327 ret_double(value, CalculateAverage32(s_data[i].histReadOps));
328 break;
329 case IOSTAT_NUM_READS_MIN:
330 ret_uint(value, CalculateMin32(s_data[i].histReadOps));
331 break;
332 case IOSTAT_NUM_READS_MAX:
333 ret_uint(value, CalculateMax32(s_data[i].histReadOps));
334 break;
335 case IOSTAT_NUM_WRITES:
336 ret_double(value, CalculateAverage32(s_data[i].histWriteOps));
337 break;
338 case IOSTAT_NUM_WRITES_MIN:
339 ret_uint(value, CalculateMin32(s_data[i].histWriteOps));
340 break;
341 case IOSTAT_NUM_WRITES_MAX:
342 ret_uint(value, CalculateMax32(s_data[i].histWriteOps));
343 break;
344 case IOSTAT_QUEUE:
345 ret_double(value, CalculateAverage32(s_data[i].histQueue));
346 break;
347 case IOSTAT_QUEUE_MIN:
348 ret_uint(value, CalculateMin32(s_data[i].histQueue));
349 break;
350 case IOSTAT_QUEUE_MAX:
351 ret_uint(value, CalculateMax32(s_data[i].histQueue));
352 break;
353 case IOSTAT_NUM_RBYTES:
354 ret_uint64(value, CalculateAverage64(s_data[i].histBytesRead));
355 break;
356 case IOSTAT_NUM_RBYTES_MIN:
357 ret_uint64(value, CalculateMin64(s_data[i].histBytesRead));
358 break;
359 case IOSTAT_NUM_RBYTES_MAX:
360 ret_uint64(value, CalculateMax64(s_data[i].histBytesRead));
361 break;
362 case IOSTAT_NUM_WBYTES:
363 ret_uint64(value, CalculateAverage64(s_data[i].histBytesWritten));
364 break;
365 case IOSTAT_NUM_WBYTES_MIN:
366 ret_uint64(value, CalculateMin64(s_data[i].histBytesWritten));
367 break;
368 case IOSTAT_NUM_WBYTES_MAX:
369 ret_uint64(value, CalculateMax64(s_data[i].histBytesWritten));
370 break;
371 default:
372 rc = SYSINFO_RC_UNSUPPORTED;
373 break;
374 }
375 return rc;
376 }
377