@@ -21,15 +21,27 @@ in the source distribution for its full text.
2121#include "XUtils.h"
2222
2323
24+ static const int DiskIORateMeter_attributes [] = {
25+ METER_VALUE_IOREAD ,
26+ METER_VALUE_IOWRITE ,
27+ };
28+
29+ static const int DiskIOTimeMeter_attributes [] = {
30+ METER_VALUE_NOTICE ,
31+ };
32+
2433static const int DiskIOMeter_attributes [] = {
2534 METER_VALUE_NOTICE ,
2635 METER_VALUE_IOREAD ,
2736 METER_VALUE_IOWRITE ,
2837};
2938
3039static MeterRateStatus status = RATESTATUS_INIT ;
40+ static double cached_read_diff ;
3141static char cached_read_diff_str [6 ];
42+ static double cached_write_diff ;
3243static char cached_write_diff_str [6 ];
44+ static uint64_t cached_num_disks ;
3345static double cached_utilisation_diff ;
3446static double cached_utilisation_norm ;
3547
@@ -73,6 +85,7 @@ static void DiskIOUpdateCache(const Machine* host) {
7385 } else {
7486 diff = 0 ;
7587 }
88+ cached_read_diff = diff ;
7689 Meter_humanUnit (cached_read_diff_str , diff , sizeof (cached_read_diff_str ));
7790
7891 if (data .totalBytesWritten > cached_write_total ) {
@@ -82,8 +95,10 @@ static void DiskIOUpdateCache(const Machine* host) {
8295 } else {
8396 diff = 0 ;
8497 }
98+ cached_write_diff = diff ;
8599 Meter_humanUnit (cached_write_diff_str , diff , sizeof (cached_write_diff_str ));
86100
101+ cached_num_disks = data .numDisks ;
87102 cached_utilisation_diff = 0.0 ;
88103 cached_utilisation_norm = 0.0 ;
89104 if (data .totalMsTimeSpend > cached_msTimeSpend_total ) {
@@ -101,6 +116,111 @@ static void DiskIOUpdateCache(const Machine* host) {
101116 cached_msTimeSpend_total = data .totalMsTimeSpend ;
102117}
103118
119+ static void DiskIORateMeter_updateValues (Meter * this ) {
120+ DiskIOUpdateCache (this -> host );
121+
122+ this -> values [0 ] = cached_read_diff * ONE_K ;
123+ this -> values [1 ] = cached_write_diff * ONE_K ;
124+
125+ switch (status ) {
126+ case RATESTATUS_NODATA :
127+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "no data" );
128+ return ;
129+ case RATESTATUS_INIT :
130+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "init" );
131+ return ;
132+ case RATESTATUS_STALE :
133+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "stale" );
134+ return ;
135+ case RATESTATUS_DATA :
136+ break ;
137+ }
138+
139+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "r:%siB/s w:%siB/s" , cached_read_diff_str , cached_write_diff_str );
140+ }
141+
142+ static void DiskIORateMeter_display (ATTR_UNUSED const Object * cast , RichString * out ) {
143+ switch (status ) {
144+ case RATESTATUS_NODATA :
145+ RichString_writeAscii (out , CRT_colors [METER_VALUE_ERROR ], "no data" );
146+ return ;
147+ case RATESTATUS_INIT :
148+ RichString_writeAscii (out , CRT_colors [METER_VALUE ], "initializing..." );
149+ return ;
150+ case RATESTATUS_STALE :
151+ RichString_writeAscii (out , CRT_colors [METER_VALUE_WARN ], "stale data" );
152+ return ;
153+ case RATESTATUS_DATA :
154+ break ;
155+ }
156+
157+ RichString_appendAscii (out , CRT_colors [METER_TEXT ], "read: " );
158+ RichString_appendAscii (out , CRT_colors [METER_VALUE_IOREAD ], cached_read_diff_str );
159+ RichString_appendAscii (out , CRT_colors [METER_VALUE_IOREAD ], "iB/s" );
160+
161+ RichString_appendAscii (out , CRT_colors [METER_TEXT ], " write: " );
162+ RichString_appendAscii (out , CRT_colors [METER_VALUE_IOWRITE ], cached_write_diff_str );
163+ RichString_appendAscii (out , CRT_colors [METER_VALUE_IOWRITE ], "iB/s" );
164+ }
165+
166+ static void DiskIOTimeMeter_updateValues (Meter * this ) {
167+ DiskIOUpdateCache (this -> host );
168+
169+ this -> values [0 ] = cached_utilisation_norm ;
170+
171+ switch (status ) {
172+ case RATESTATUS_NODATA :
173+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "no data" );
174+ return ;
175+ case RATESTATUS_INIT :
176+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "init" );
177+ return ;
178+ case RATESTATUS_STALE :
179+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "stale" );
180+ return ;
181+ case RATESTATUS_DATA :
182+ break ;
183+ }
184+
185+ char numDisksStr [12 ];
186+ numDisksStr [0 ] = '\0' ;
187+ if (cached_num_disks > 1 && cached_num_disks < 1000 ) {
188+ xSnprintf (numDisksStr , sizeof (numDisksStr ), " (%udisks)" , (unsigned int )cached_num_disks );
189+ }
190+
191+ xSnprintf (this -> txtBuffer , sizeof (this -> txtBuffer ), "%.1f%%%s" , cached_utilisation_diff , numDisksStr );
192+ }
193+
194+ static void DiskIOTimeMeter_display (ATTR_UNUSED const Object * cast , RichString * out ) {
195+ switch (status ) {
196+ case RATESTATUS_NODATA :
197+ RichString_writeAscii (out , CRT_colors [METER_VALUE_ERROR ], "no data" );
198+ return ;
199+ case RATESTATUS_INIT :
200+ RichString_writeAscii (out , CRT_colors [METER_VALUE ], "initializing..." );
201+ return ;
202+ case RATESTATUS_STALE :
203+ RichString_writeAscii (out , CRT_colors [METER_VALUE_WARN ], "stale data" );
204+ return ;
205+ case RATESTATUS_DATA :
206+ break ;
207+ }
208+
209+ char buffer [16 ];
210+
211+ int color = cached_utilisation_diff > 40.0 ? METER_VALUE_NOTICE : METER_VALUE ;
212+ int len = xSnprintf (buffer , sizeof (buffer ), "%.1f%%" , cached_utilisation_diff );
213+ RichString_appendnAscii (out , CRT_colors [color ], buffer , len );
214+ RichString_appendAscii (out , CRT_colors [METER_TEXT ], " busy" );
215+
216+ if (cached_num_disks > 1 && cached_num_disks < 1000 ) {
217+ RichString_appendAscii (out , CRT_colors [METER_TEXT ], " (" );
218+ len = xSnprintf (buffer , sizeof (buffer ), "%u" , (unsigned int )cached_num_disks );
219+ RichString_appendnAscii (out , CRT_colors [METER_VALUE ], buffer , len );
220+ RichString_appendAscii (out , CRT_colors [METER_TEXT ], " disks)" );
221+ }
222+ }
223+
104224static void DiskIOMeter_updateValues (Meter * this ) {
105225 DiskIOUpdateCache (this -> host );
106226
@@ -153,6 +273,44 @@ static void DiskIOMeter_display(ATTR_UNUSED const Object* cast, RichString* out)
153273 RichString_appendAscii (out , CRT_colors [METER_VALUE_IOWRITE ], "iB/s" );
154274}
155275
276+ const MeterClass DiskIORateMeter_class = {
277+ .super = {
278+ .extends = Class (Meter ),
279+ .delete = Meter_delete ,
280+ .display = DiskIORateMeter_display
281+ },
282+ .updateValues = DiskIORateMeter_updateValues ,
283+ .defaultMode = TEXT_METERMODE ,
284+ .supportedModes = METERMODE_DEFAULT_SUPPORTED ,
285+ .maxItems = 2 ,
286+ .isPercentChart = false,
287+ .total = 1.0 ,
288+ .attributes = DiskIORateMeter_attributes ,
289+ .name = "DiskIORate" ,
290+ .uiName = "Disk IO Rate" ,
291+ .description = "Disk IO read & write bytes per second" ,
292+ .caption = "Dsk: "
293+ };
294+
295+ const MeterClass DiskIOTimeMeter_class = {
296+ .super = {
297+ .extends = Class (Meter ),
298+ .delete = Meter_delete ,
299+ .display = DiskIOTimeMeter_display
300+ },
301+ .updateValues = DiskIOTimeMeter_updateValues ,
302+ .defaultMode = TEXT_METERMODE ,
303+ .supportedModes = METERMODE_DEFAULT_SUPPORTED ,
304+ .maxItems = 1 ,
305+ .isPercentChart = true,
306+ .total = 1.0 ,
307+ .attributes = DiskIOTimeMeter_attributes ,
308+ .name = "DiskIOTime" ,
309+ .uiName = "Disk IO Time" ,
310+ .description = "Disk percent time busy" ,
311+ .caption = "Dsk: "
312+ };
313+
156314const MeterClass DiskIOMeter_class = {
157315 .super = {
158316 .extends = Class (Meter ),
0 commit comments