Sorry for the combined patch. The changes became too inter-dependent.
[beagle.git] / Util / SystemInformation.cs
blobaeff23b638197ade4e85326c1ace13e2529b4ad6
1 //
2 // SystemInformation.cs
3 //
4 // Copyright (C) 2004-2006 Novell, Inc.
5 //
7 //
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.
27 using System;
28 using System.Collections;
29 using System.Diagnostics;
30 using System.Globalization;
31 using System.IO;
32 using System.Reflection;
33 using System.Runtime.InteropServices;
34 using System.Text;
35 using System.Text.RegularExpressions;
37 namespace Beagle.Util {
39 public class SystemInformation {
41 [DllImport ("libc", SetLastError=true)]
42 static extern int getloadavg (double[] loadavg, int nelem);
44 const double loadavg_poll_delay = 3;
45 private static DateTime proc_loadavg_time = DateTime.MinValue;
46 private static double cached_loadavg_1min = -1;
47 private static double cached_loadavg_5min = -1;
48 private static double cached_loadavg_15min = -1;
50 private static void CheckLoadAverage ()
52 // Only call getloadavg() at most once every 10 seconds
53 if ((DateTime.Now - proc_loadavg_time).TotalSeconds < loadavg_poll_delay)
54 return;
56 double [] loadavg = new double [3];
57 int retval = getloadavg (loadavg, 3);
59 if (retval == -1)
60 throw new IOException ("Could not get system load average: " + Mono.Unix.Native.Stdlib.strerror (Mono.Unix.Native.Stdlib.GetLastError ()));
61 else if (retval != 3)
62 throw new IOException ("Could not get system load average: getloadavg() returned an unexpected number of samples");
64 cached_loadavg_1min = loadavg [0];
65 cached_loadavg_5min = loadavg [1];
66 cached_loadavg_15min = loadavg [2];
68 proc_loadavg_time = DateTime.Now;
71 public static double LoadAverageOneMinute {
72 get {
73 CheckLoadAverage ();
74 return cached_loadavg_1min;
78 public static double LoadAverageFiveMinute {
79 get {
80 CheckLoadAverage ();
81 return cached_loadavg_5min;
85 public static double LoadAverageFifteenMinute {
86 get {
87 CheckLoadAverage ();
88 return cached_loadavg_15min;
92 ///////////////////////////////////////////////////////////////
94 private static bool use_screensaver = false;
95 const double screensaver_poll_delay = 1;
96 private static DateTime screensaver_time = DateTime.MinValue;
97 private static bool cached_screensaver_running = false;
98 private static double cached_screensaver_idle_time = 0;
100 private enum ScreenSaverState {
101 Off = 0,
102 On = 1,
103 Cycle = 2,
104 Disabled = 3
107 private enum ScreenSaverKind {
108 Blanked = 0,
109 Internal = 1,
110 External = 2
113 [DllImport ("libbeagleglue.so")]
114 extern static unsafe int screensaver_glue_init ();
116 public static bool XssInit ()
118 return XssInit (false);
121 public static bool XssInit (bool actually_init_xss)
123 int has_xss = screensaver_glue_init ();
124 use_screensaver = (has_xss == 1);
125 return use_screensaver;
128 [DllImport ("libbeagleglue.so")]
129 extern static unsafe int screensaver_info (ScreenSaverState *state,
130 ScreenSaverKind *kind,
131 ulong *til_or_since,
132 ulong *idle);
134 private static void CheckScreenSaver ()
136 if (! use_screensaver)
137 return;
139 if ((DateTime.Now - screensaver_time).TotalSeconds < screensaver_poll_delay)
140 return;
142 ScreenSaverState state;
143 ScreenSaverKind kind;
144 ulong til_or_since = 0, idle = 0;
145 int retval;
147 unsafe {
148 retval = screensaver_info (&state, &kind, &til_or_since, &idle);
151 if (retval != 0) {
152 cached_screensaver_running = (state == ScreenSaverState.On);
153 cached_screensaver_idle_time = idle / 1000.0;
154 } else {
155 cached_screensaver_running = false;
156 cached_screensaver_idle_time = 0;
159 screensaver_time = DateTime.Now;
162 public static bool ScreenSaverRunning {
163 get {
164 CheckScreenSaver ();
165 return cached_screensaver_running;
169 // returns number of seconds since input was received
170 // from the user on any input device
171 public static double InputIdleTime {
172 get {
173 CheckScreenSaver ();
174 return cached_screensaver_idle_time;
178 ///////////////////////////////////////////////////////////////
180 const double acpi_poll_delay = 30;
181 const string proc_ac_state_filename = "/proc/acpi/ac_adapter/AC/state";
182 const string ac_present_string = "on-line";
183 private static bool proc_ac_state_exists = true;
184 private static DateTime using_battery_time = DateTime.MinValue;
185 private static bool using_battery;
187 public static void CheckAcpi ()
189 if (! proc_ac_state_exists)
190 return;
192 if ((DateTime.Now - using_battery_time).TotalSeconds < acpi_poll_delay)
193 return;
195 if (! File.Exists (proc_ac_state_filename)) {
196 proc_ac_state_exists = false;
197 using_battery = false;
198 return;
201 Stream stream = new FileStream (proc_ac_state_filename,
202 System.IO.FileMode.Open,
203 FileAccess.Read,
204 FileShare.Read);
205 TextReader reader = new StreamReader (stream);
207 string line = reader.ReadLine ();
208 using_battery = (line != null) && (line.IndexOf (ac_present_string) == -1);
210 reader.Close ();
211 stream.Close ();
213 using_battery_time = DateTime.Now;
216 public static bool UsingBattery {
217 get {
218 CheckAcpi ();
219 return using_battery;
223 ///////////////////////////////////////////////////////////////
225 [DllImport ("libbeagleglue")]
226 extern static int get_vmsize ();
228 [DllImport ("libbeagleglue")]
229 extern static int get_vmrss ();
231 public static int VmSize {
232 get { return get_vmsize (); }
235 public static int VmRss {
236 get { return get_vmrss (); }
239 ///////////////////////////////////////////////////////////////
241 private static int disk_stats_read_reqs;
242 private static int disk_stats_write_reqs;
243 private static int disk_stats_read_bytes;
244 private static int disk_stats_write_bytes;
246 private static DateTime disk_stats_time = DateTime.MinValue;
247 private static double disk_stats_delay = 1.0;
249 private static uint major, minor;
251 // Update the disk statistics with data for block device on the (major,minor) pair.
252 private static void UpdateDiskStats ()
254 string buffer;
256 if (major == 0)
257 return;
259 // We only refresh the stats once per second
260 if ((DateTime.Now - disk_stats_time).TotalSeconds < disk_stats_delay)
261 return;
263 // Read in all of the disk stats
264 using (StreamReader stream = new StreamReader ("/proc/diskstats"))
265 buffer = stream.ReadToEnd ();
267 // Find our partition and parse it
268 const string REGEX = "[\\s]+{0}[\\s]+{1}[\\s]+[a-zA-Z0-9]+[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([0-9]+)";
269 string regex = String.Format (REGEX, major, minor);
270 Regex r = new Regex (regex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
271 for (System.Text.RegularExpressions.Match m = r.Match (buffer); m.Success; m = m.NextMatch ()) {
272 disk_stats_read_reqs = Convert.ToInt32 (m.Groups[1].ToString ());
273 disk_stats_read_bytes = Convert.ToInt32 (m.Groups[2].ToString ());
274 disk_stats_write_reqs = Convert.ToInt32 (m.Groups[3].ToString ());
275 disk_stats_write_bytes = Convert.ToInt32 (m.Groups[4].ToString ());
278 disk_stats_time = DateTime.Now;
281 // Get the (major,minor) pair for the block device from which the index is mounted.
282 private static void GetIndexDev ()
284 Mono.Unix.Native.Stat stat;
285 if (Mono.Unix.Native.Syscall.stat (PathFinder.StorageDir, out stat) != 0)
286 return;
288 major = (uint) stat.st_dev >> 8;
289 minor = (uint) stat.st_dev & 0xff;
292 public static int DiskStatsReadReqs {
293 get {
294 if (major == 0)
295 GetIndexDev ();
296 UpdateDiskStats ();
297 return disk_stats_read_reqs;
301 public static int DiskStatsReadBytes {
302 get {
303 if (major == 0)
304 GetIndexDev ();
305 UpdateDiskStats ();
306 return disk_stats_read_bytes;
310 public static int DiskStatsWriteReqs {
311 get {
312 if (major == 0)
313 GetIndexDev ();
314 UpdateDiskStats ();
315 return disk_stats_write_reqs;
319 public static int DiskStatsWriteBytes {
320 get {
321 if (major == 0)
322 GetIndexDev ();
323 UpdateDiskStats ();
324 return disk_stats_write_bytes;
328 public static bool IsPathOnBlockDevice (string path)
330 Mono.Unix.Native.Stat stat;
331 if (Mono.Unix.Native.Syscall.stat (path, out stat) != 0)
332 return false;
334 return (stat.st_dev >> 8 != 0);
337 ///////////////////////////////////////////////////////////////
339 [DllImport("libc")]
340 private static extern int prctl (int option, byte [] arg2, ulong arg3, ulong arg4, ulong arg5);
342 // From /usr/include/linux/prctl.h
343 private const int PR_SET_NAME = 15;
345 public static void SetProcessName(string name)
347 #if OS_LINUX
348 if (prctl (PR_SET_NAME, Encoding.ASCII.GetBytes (name + '\0'), 0, 0, 0) < 0) {
349 Logger.Log.Warn ("Couldn't set process name to '{0}': {1}", name,
350 Mono.Unix.Native.Stdlib.GetLastError ());
352 #endif
355 ///////////////////////////////////////////////////////////////
357 public static string MonoRuntimeVersion {
358 get {
359 Type t = typeof (object).Assembly.GetType ("Mono.Runtime");
361 string ver = (string) t.InvokeMember ("GetDisplayName",
362 BindingFlags.InvokeMethod
363 | BindingFlags.NonPublic
364 | BindingFlags.Static
365 | BindingFlags.DeclaredOnly
366 | BindingFlags.ExactBinding,
367 null, null, null);
369 return ver;
373 ///////////////////////////////////////////////////////////////
375 #if false
376 public static void Main ()
378 while (true) {
379 Console.WriteLine ("{0} {1} {2} {3} {4} {5} {6} {7}",
380 LoadAverageOneMinute,
381 LoadAverageFiveMinute,
382 LoadAverageFifteenMinute,
383 ScreenSaverRunning,
384 InputIdleTime,
385 UsingBattery,
386 DiskStatsReadReqs,
387 VmSize);
388 System.Threading.Thread.Sleep (1000);
391 #endif