2 // SystemInformation.cs
4 // Copyright (C) 2004 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
28 using System
.Collections
;
29 using System
.Diagnostics
;
30 using System
.Globalization
;
32 using System
.Runtime
.InteropServices
;
33 using System
.Text
.RegularExpressions
;
36 namespace Beagle
.Util
{
38 public class SystemInformation
{
40 [DllImport ("libc", SetLastError
=true)]
41 static extern int getloadavg (double[] loadavg
, int nelem
);
43 const double loadavg_poll_delay
= 3;
44 static DateTime proc_loadavg_time
= DateTime
.MinValue
;
45 static double cached_loadavg_1min
= -1;
46 static double cached_loadavg_5min
= -1;
47 static double cached_loadavg_15min
= -1;
49 static private void CheckLoadAverage ()
51 // Only call getloadavg() at most once every 10 seconds
52 if ((DateTime
.Now
- proc_loadavg_time
).TotalSeconds
< loadavg_poll_delay
)
55 double [] loadavg
= new double [3];
56 int retval
= getloadavg (loadavg
, 3);
59 throw new IOException ("Could not get system load average: " + Syscall
.strerror (Marshal
.GetLastWin32Error ()));
61 throw new IOException ("Could not get system load average: getloadavg() returned an unexpected number of samples");
63 cached_loadavg_1min
= loadavg
[0];
64 cached_loadavg_5min
= loadavg
[1];
65 cached_loadavg_15min
= loadavg
[2];
67 proc_loadavg_time
= DateTime
.Now
;
70 static public double LoadAverageOneMinute
{
73 return cached_loadavg_1min
;
77 static public double LoadAverageFiveMinute
{
80 return cached_loadavg_5min
;
84 static public double LoadAverageFifteenMinute
{
87 return cached_loadavg_15min
;
91 ///////////////////////////////////////////////////////////////
93 const double screensaver_poll_delay
= 1;
94 static DateTime screensaver_time
= DateTime
.MinValue
;
95 static bool cached_screensaver_running
= false;
96 static double cached_screensaver_idle_time
= 0;
98 private enum ScreenSaverState
{
105 private enum ScreenSaverKind
{
111 [DllImport ("libsysteminfoglue.so")]
112 extern static unsafe int screensaver_info (ScreenSaverState
*state
,
113 ScreenSaverKind
*kind
,
117 static private void CheckScreenSaver ()
119 if ((DateTime
.Now
- screensaver_time
).TotalSeconds
< screensaver_poll_delay
)
122 ScreenSaverState state
;
123 ScreenSaverKind kind
;
124 ulong til_or_since
= 0, idle
= 0;
128 retval
= screensaver_info (&state
, &kind
, &til_or_since
, &idle
);
132 cached_screensaver_running
= (state
== ScreenSaverState
.On
);
133 cached_screensaver_idle_time
= idle
/ 1000.0;
135 cached_screensaver_running
= false;
136 cached_screensaver_idle_time
= 0;
139 screensaver_time
= DateTime
.Now
;
142 static public bool ScreenSaverRunning
{
145 return cached_screensaver_running
;
149 // returns number of seconds since input was received
150 // from the user on any input device
151 static public double InputIdleTime
{
154 return cached_screensaver_idle_time
;
158 ///////////////////////////////////////////////////////////////
160 const double acpi_poll_delay
= 30;
161 const string proc_ac_state_filename
= "/proc/acpi/ac_adapter/AC/state";
162 const string ac_present_string
= "on-line";
163 static bool proc_ac_state_exists
= true;
164 static DateTime using_battery_time
= DateTime
.MinValue
;
165 static bool using_battery
;
167 static public void CheckAcpi ()
169 if (! proc_ac_state_exists
)
172 if ((DateTime
.Now
- using_battery_time
).TotalSeconds
< acpi_poll_delay
)
175 if (! File
.Exists (proc_ac_state_filename
)) {
176 proc_ac_state_exists
= false;
177 using_battery
= false;
181 Stream stream
= new FileStream (proc_ac_state_filename
,
182 System
.IO
.FileMode
.Open
,
185 TextReader reader
= new StreamReader (stream
);
187 string line
= reader
.ReadLine ();
188 using_battery
= (line
!= null) && (line
.IndexOf (ac_present_string
) == -1);
193 using_battery_time
= DateTime
.Now
;
196 static public bool UsingBattery
{
199 return using_battery
;
203 ///////////////////////////////////////////////////////////////
205 [DllImport ("libsysteminfoglue.so")]
206 extern static int get_vmsize ();
208 [DllImport ("libsysteminfoglue.so")]
209 extern static int get_vmrss ();
211 static public int VmSize
{
212 get { return get_vmsize (); }
215 static public int VmRss
{
216 get { return get_vmrss (); }
219 static private int disk_stats_read_reqs
;
220 static private int disk_stats_write_reqs
;
221 static private int disk_stats_read_bytes
;
222 static private int disk_stats_write_bytes
;
224 static private DateTime disk_stats_time
= DateTime
.MinValue
;
225 static private double disk_stats_delay
= 1.0;
227 static private uint major
, minor
;
229 // Update the disk statistics with data for block device on the (major,minor) pair.
230 static private void UpdateDiskStats ()
237 // We only refresh the stats once per second
238 if ((DateTime
.Now
- disk_stats_time
).TotalSeconds
< disk_stats_delay
)
241 // Read in all of the disk stats
242 using (StreamReader stream
= new StreamReader ("/proc/diskstats"))
243 buffer
= stream
.ReadToEnd ();
245 // Find our partition and parse it
246 const string REGEX
= "[\\s]+{0}[\\s]+{1}[\\s]+[a-zA-Z0-9]+[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([0-9]+)";
247 string regex
= String
.Format (REGEX
, major
, minor
);
248 Regex r
= new Regex (regex
, RegexOptions
.IgnoreCase
| RegexOptions
.Compiled
);
249 for (System
.Text
.RegularExpressions
.Match m
= r
.Match (buffer
); m
.Success
; m
= m
.NextMatch ()) {
250 disk_stats_read_reqs
= Convert
.ToInt32 (m
.Groups
[1].ToString ());
251 disk_stats_read_bytes
= Convert
.ToInt32 (m
.Groups
[2].ToString ());
252 disk_stats_write_reqs
= Convert
.ToInt32 (m
.Groups
[3].ToString ());
253 disk_stats_write_bytes
= Convert
.ToInt32 (m
.Groups
[4].ToString ());
256 disk_stats_time
= DateTime
.Now
;
259 // Get the (major,minor) pair for the block device from which the index is mounted.
260 static private void GetIndexDev ()
262 Mono
.Posix
.Stat stat
= new Mono
.Posix
.Stat ();
263 if (Mono
.Posix
.Syscall
.stat (PathFinder
.StorageDir
, out stat
) != 0)
266 major
= (uint) stat
.Device
>> 8;
267 minor
= (uint) stat
.Device
& 0xff;
270 static public int DiskStatsReadReqs
{
275 return disk_stats_read_reqs
;
279 static public int DiskStatsReadBytes
{
284 return disk_stats_read_bytes
;
288 static public int DiskStatsWriteReqs
{
293 return disk_stats_write_reqs
;
297 static public int DiskStatsWriteBytes
{
302 return disk_stats_write_bytes
;
306 static public bool IsPathOnBlockDevice (string path
)
308 Mono
.Posix
.Stat stat
;
309 if (Mono
.Posix
.Syscall
.stat (path
, out stat
) != 0)
312 return (stat
.Device
>> 8 != 0);
318 Gtk
.Application
.Init ();
320 Console
.WriteLine ("{0} {1} {2} {3} {4} {5} {6} {7}",
321 LoadAverageOneMinute
,
322 LoadAverageFiveMinute
,
323 LoadAverageFifteenMinute
,
329 System
.Threading
.Thread
.Sleep (1000);