Remove debug statements from KCal backends.
[beagle.git] / Util / SystemInformation.cs
blob870819188d3d947e28efde5a24787005b6847fb0
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.CompilerServices;
34 using System.Runtime.InteropServices;
35 using System.Text;
36 using System.Text.RegularExpressions;
38 namespace Beagle.Util {
40 public class SystemInformation {
42 [DllImport ("libc", SetLastError=true)]
43 static extern int getloadavg (double[] loadavg, int nelem);
45 const double loadavg_poll_delay = 3;
46 private static DateTime proc_loadavg_time = DateTime.MinValue;
47 private static double cached_loadavg_1min = -1;
48 private static double cached_loadavg_5min = -1;
49 private static double cached_loadavg_15min = -1;
51 private static void CheckLoadAverage ()
53 // Only call getloadavg() at most once every 10 seconds
54 if ((DateTime.Now - proc_loadavg_time).TotalSeconds < loadavg_poll_delay)
55 return;
57 double [] loadavg = new double [3];
58 int retval = getloadavg (loadavg, 3);
60 if (retval == -1)
61 throw new IOException ("Could not get system load average: " + Mono.Unix.Native.Stdlib.strerror (Mono.Unix.Native.Stdlib.GetLastError ()));
62 else if (retval != 3)
63 throw new IOException ("Could not get system load average: getloadavg() returned an unexpected number of samples");
65 cached_loadavg_1min = loadavg [0];
66 cached_loadavg_5min = loadavg [1];
67 cached_loadavg_15min = loadavg [2];
69 proc_loadavg_time = DateTime.Now;
72 public static double LoadAverageOneMinute {
73 get {
74 CheckLoadAverage ();
75 return cached_loadavg_1min;
79 public static double LoadAverageFiveMinute {
80 get {
81 CheckLoadAverage ();
82 return cached_loadavg_5min;
86 public static double LoadAverageFifteenMinute {
87 get {
88 CheckLoadAverage ();
89 return cached_loadavg_15min;
93 ///////////////////////////////////////////////////////////////
95 private static bool use_screensaver = false;
96 const double screensaver_poll_delay = 1;
97 private static DateTime screensaver_time = DateTime.MinValue;
98 private static bool cached_screensaver_running = false;
99 private static double cached_screensaver_idle_time = 0;
101 private enum ScreenSaverState {
102 Off = 0,
103 On = 1,
104 Cycle = 2,
105 Disabled = 3
108 private enum ScreenSaverKind {
109 Blanked = 0,
110 Internal = 1,
111 External = 2
114 [DllImport ("libbeagleglue.so")]
115 extern static unsafe int screensaver_glue_init ();
117 public static bool XssInit ()
119 return XssInit (false);
122 public static bool XssInit (bool actually_init_xss)
124 int has_xss = screensaver_glue_init ();
125 use_screensaver = (has_xss == 1);
126 return use_screensaver;
129 [DllImport ("libbeagleglue.so")]
130 extern static unsafe int screensaver_info (ScreenSaverState *state,
131 ScreenSaverKind *kind,
132 ulong *til_or_since,
133 ulong *idle);
135 private static void CheckScreenSaver ()
137 if (! use_screensaver)
138 return;
140 if ((DateTime.Now - screensaver_time).TotalSeconds < screensaver_poll_delay)
141 return;
143 ScreenSaverState state;
144 ScreenSaverKind kind;
145 ulong til_or_since = 0, idle = 0;
146 int retval;
148 unsafe {
149 retval = screensaver_info (&state, &kind, &til_or_since, &idle);
152 if (retval != 0) {
153 cached_screensaver_running = (state == ScreenSaverState.On);
154 cached_screensaver_idle_time = idle / 1000.0;
155 } else {
156 cached_screensaver_running = false;
157 cached_screensaver_idle_time = 0;
160 screensaver_time = DateTime.Now;
163 public static bool ScreenSaverRunning {
164 get {
165 CheckScreenSaver ();
166 return cached_screensaver_running;
170 // returns number of seconds since input was received
171 // from the user on any input device
172 public static double InputIdleTime {
173 get {
174 CheckScreenSaver ();
175 return cached_screensaver_idle_time;
179 ///////////////////////////////////////////////////////////////
181 const double acpi_poll_delay = 30;
182 const string ac_present_string = "on-line";
184 private static readonly string[] proc_ac_state_filenames = new string[] {
185 "/proc/acpi/ac_adapter/AC/state",
186 "/proc/acpi/ac_adapter/AC0/state",
187 "/proc/acpi/ac_adapter/ADp1/state"
190 private static string proc_ac_state_filename = null;
191 private static bool proc_ac_state_exists = true;
192 private static DateTime using_battery_time = DateTime.MinValue;
193 private static bool using_battery;
195 public static void CheckAcpi ()
197 if (! proc_ac_state_exists)
198 return;
200 if ((DateTime.Now - using_battery_time).TotalSeconds < acpi_poll_delay)
201 return;
203 if (proc_ac_state_filename == null) {
204 foreach (string s in proc_ac_state_filenames) {
205 if (File.Exists (s)) {
206 proc_ac_state_filename = s;
207 break;
212 if (proc_ac_state_filename == null || ! File.Exists (proc_ac_state_filename)) {
213 proc_ac_state_exists = false;
214 using_battery = false;
215 return;
218 Stream stream = new FileStream (proc_ac_state_filename,
219 System.IO.FileMode.Open,
220 FileAccess.Read,
221 FileShare.Read);
222 TextReader reader = new StreamReader (stream);
224 string line = reader.ReadLine ();
225 using_battery = (line != null) && (line.IndexOf (ac_present_string) == -1);
227 reader.Close ();
228 stream.Close ();
230 using_battery_time = DateTime.Now;
233 public static bool UsingBattery {
234 get {
235 CheckAcpi ();
236 return using_battery;
240 ///////////////////////////////////////////////////////////////
242 [DllImport ("libbeagleglue")]
243 extern static int get_vmsize ();
245 [DllImport ("libbeagleglue")]
246 extern static int get_vmrss ();
248 public static int VmSize {
249 get { return get_vmsize (); }
252 public static int VmRss {
253 get { return get_vmrss (); }
256 public static void LogMemoryUsage ()
258 int vm_size = VmSize;
259 int vm_rss = VmRss;
261 Logger.Log.Debug ("Memory usage: VmSize={0:.0} MB, VmRSS={1:.0} MB, GC.GetTotalMemory={2}",
262 vm_size/1024.0, vm_rss/1024.0, GC.GetTotalMemory (false));
265 ///////////////////////////////////////////////////////////////
267 // Internal calls have to be installed before mono accesses the
268 // class that uses them. That's why we have this retarded extra
269 // class and initializer function. Paolo says this is a *HUGE*
270 // unsupported hack and not to be surprised if it doesn't work.
271 public class InternalCallInitializer {
272 [DllImport ("libbeagleglue", EntryPoint="mono_glue_install_icall")]
273 public extern static void Init ();
276 [MethodImplAttribute (MethodImplOptions.InternalCall)]
277 public extern static int GetObjectSizeIcall (object o);
279 public static int GetObjectSize (object o)
281 try {
282 return GetObjectSizeIcall (o);
283 } catch (MissingMethodException) {
284 return -1;
288 [MethodImplAttribute (MethodImplOptions.InternalCall)]
289 public extern static int GetObjectPointerIcall (object o);
291 public static long GetObjectPointer (object o)
293 try {
294 return GetObjectPointerIcall (o);
295 } catch (MissingMethodException) {
296 return -1;
300 ///////////////////////////////////////////////////////////////
302 private static int disk_stats_read_reqs;
303 private static int disk_stats_write_reqs;
304 private static int disk_stats_read_bytes;
305 private static int disk_stats_write_bytes;
307 private static DateTime disk_stats_time = DateTime.MinValue;
308 private static double disk_stats_delay = 1.0;
310 private static uint major, minor;
312 // Update the disk statistics with data for block device on the (major,minor) pair.
313 private static void UpdateDiskStats ()
315 string buffer;
317 if (major == 0)
318 return;
320 // We only refresh the stats once per second
321 if ((DateTime.Now - disk_stats_time).TotalSeconds < disk_stats_delay)
322 return;
324 // Read in all of the disk stats
325 using (StreamReader stream = new StreamReader ("/proc/diskstats"))
326 buffer = stream.ReadToEnd ();
328 // Find our partition and parse it
329 const string REGEX = "[\\s]+{0}[\\s]+{1}[\\s]+[a-zA-Z0-9]+[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([0-9]+)[\\s]+([0-9]+)";
330 string regex = String.Format (REGEX, major, minor);
331 Regex r = new Regex (regex, RegexOptions.IgnoreCase | RegexOptions.Compiled);
332 for (System.Text.RegularExpressions.Match m = r.Match (buffer); m.Success; m = m.NextMatch ()) {
333 disk_stats_read_reqs = Convert.ToInt32 (m.Groups[1].ToString ());
334 disk_stats_read_bytes = Convert.ToInt32 (m.Groups[2].ToString ());
335 disk_stats_write_reqs = Convert.ToInt32 (m.Groups[3].ToString ());
336 disk_stats_write_bytes = Convert.ToInt32 (m.Groups[4].ToString ());
339 disk_stats_time = DateTime.Now;
342 // Get the (major,minor) pair for the block device from which the index is mounted.
343 private static void GetIndexDev ()
345 Mono.Unix.Native.Stat stat;
346 if (Mono.Unix.Native.Syscall.stat (PathFinder.StorageDir, out stat) != 0)
347 return;
349 major = (uint) stat.st_dev >> 8;
350 minor = (uint) stat.st_dev & 0xff;
353 public static int DiskStatsReadReqs {
354 get {
355 if (major == 0)
356 GetIndexDev ();
357 UpdateDiskStats ();
358 return disk_stats_read_reqs;
362 public static int DiskStatsReadBytes {
363 get {
364 if (major == 0)
365 GetIndexDev ();
366 UpdateDiskStats ();
367 return disk_stats_read_bytes;
371 public static int DiskStatsWriteReqs {
372 get {
373 if (major == 0)
374 GetIndexDev ();
375 UpdateDiskStats ();
376 return disk_stats_write_reqs;
380 public static int DiskStatsWriteBytes {
381 get {
382 if (major == 0)
383 GetIndexDev ();
384 UpdateDiskStats ();
385 return disk_stats_write_bytes;
389 public static bool IsPathOnBlockDevice (string path)
391 Mono.Unix.Native.Stat stat;
392 if (Mono.Unix.Native.Syscall.stat (path, out stat) != 0)
393 return false;
395 return (stat.st_dev >> 8 != 0);
398 ///////////////////////////////////////////////////////////////
400 [DllImport("libc")]
401 private static extern int prctl (int option, byte [] arg2, ulong arg3, ulong arg4, ulong arg5);
403 // From /usr/include/linux/prctl.h
404 private const int PR_SET_NAME = 15;
406 public static void SetProcessName(string name)
408 #if OS_LINUX
409 if (prctl (PR_SET_NAME, Encoding.ASCII.GetBytes (name + '\0'), 0, 0, 0) < 0) {
410 Logger.Log.Warn ("Couldn't set process name to '{0}': {1}", name,
411 Mono.Unix.Native.Stdlib.GetLastError ());
413 #endif
416 ///////////////////////////////////////////////////////////////
418 public static string MonoRuntimeVersion {
419 get {
420 Type t = typeof (object).Assembly.GetType ("Mono.Runtime");
422 string ver = (string) t.InvokeMember ("GetDisplayName",
423 BindingFlags.InvokeMethod
424 | BindingFlags.NonPublic
425 | BindingFlags.Static
426 | BindingFlags.DeclaredOnly
427 | BindingFlags.ExactBinding,
428 null, null, null);
430 return ver;
434 ///////////////////////////////////////////////////////////////
436 #if false
437 public static void Main ()
439 while (true) {
440 Console.WriteLine ("{0} {1} {2} {3} {4} {5} {6} {7}",
441 LoadAverageOneMinute,
442 LoadAverageFiveMinute,
443 LoadAverageFifteenMinute,
444 ScreenSaverRunning,
445 InputIdleTime,
446 UsingBattery,
447 DiskStatsReadReqs,
448 VmSize);
449 System.Threading.Thread.Sleep (1000);
452 #endif