Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mcs / class / System / System.Diagnostics / PerformanceCounter.cs
index cda6f61a873e01b058097458381f06a7eff80fe1..f76f0950f459bbf951ebbf0ebba82e30b0f097bf 100644 (file)
@@ -34,11 +34,13 @@ using System;
 using System.ComponentModel;
 using System.ComponentModel.Design;
 using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
 
 namespace System.Diagnostics {
 
        // must be safe for multithreaded operations
-       [Designer ("Microsoft.VisualStudio.Install.PerformanceCounterDesigner, Microsoft.VisualStudio, " + Consts.AssemblyMicrosoft_VisualStudio, typeof (IDesigner))]
        [InstallerType (typeof (PerformanceCounterInstaller))]
        public sealed class PerformanceCounter : Component, ISupportInitialize 
        {
@@ -47,8 +49,16 @@ namespace System.Diagnostics {
                private string counterName;
                private string instanceName;
                private string machineName;
+               IntPtr impl;
+               PerformanceCounterType type;
+               CounterSample old_sample;
                private bool readOnly;
+               bool valid_old;
+               bool changed;
+               bool is_custom;
+               private PerformanceCounterInstanceLifetime lifetime;
 
+               [Obsolete]
                public static int DefaultFileMappingSize = 524288;
 
                // set catname, countname, instname to "", machname to "."
@@ -87,6 +97,12 @@ namespace System.Diagnostics {
                        bool readOnly)
                {
 
+                       if (categoryName == null)
+                               throw new ArgumentNullException ("categoryName");
+                       if (counterName == null)
+                               throw new ArgumentNullException ("counterName");
+                       if (instanceName == null)
+                               throw new ArgumentNullException ("instanceName");
                        CategoryName = categoryName;
                        CounterName = counterName;
 
@@ -97,6 +113,7 @@ namespace System.Diagnostics {
                        this.instanceName = instanceName;
                        this.machineName = ".";
                        this.readOnly = readOnly;
+                       changed = true;
                }
 
                public PerformanceCounter (string categoryName,
@@ -108,6 +125,39 @@ namespace System.Diagnostics {
                        this.machineName = machineName;
                }
 
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern IntPtr GetImpl (string category, string counter,
+                               string instance, string machine, out PerformanceCounterType ctype, out bool custom);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern bool GetSample (IntPtr impl, bool only_value, out CounterSample sample);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern long UpdateValue (IntPtr impl, bool do_incr, long value);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               static extern void FreeData (IntPtr impl);
+
+               /* the perf counter has changed, ensure it's valid and setup it to
+                * be able to collect/update data
+                */
+               void UpdateInfo ()
+               {
+                       // need to free the previous info
+                       if (impl != IntPtr.Zero)
+                               Close ();
+                       impl = GetImpl (categoryName, counterName, instanceName, machineName, out type, out is_custom);
+                       // system counters are always readonly
+                       if (!is_custom)
+                               readOnly = true;
+                       // invalid counter, need to handle out of mem
+
+                       // TODO: reenable this
+                       //if (impl == IntPtr.Zero)
+                       //      throw new InvalidOperationException ();
+                       changed = false;
+               }
+
                // may throw ArgumentNullException
                [DefaultValue (""), ReadOnly (true), RecommendedAsConfigurable (true)]
                [TypeConverter ("System.Diagnostics.Design.CategoryValueConverter, " + Consts.AssemblySystem_Design)]
@@ -118,6 +168,7 @@ namespace System.Diagnostics {
                                if (value == null)
                                        throw new ArgumentNullException ("categoryName");
                                categoryName = value;
+                               changed = true;
                        }
                }
 
@@ -140,24 +191,38 @@ namespace System.Diagnostics {
                                if (value == null)
                                        throw new ArgumentNullException ("counterName");
                                counterName = value;
+                               changed = true;
                        }
                }
 
-               // may throw InvalidOperationException
-               [MonoTODO]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The type of the counter.")]
                public PerformanceCounterType CounterType {
-                       get {return 0;}
+                       get {
+                               if (changed)
+                                       UpdateInfo ();
+                               return type;
+                       }
+               }
+
+               [MonoTODO]
+               [DefaultValue (PerformanceCounterInstanceLifetime.Global)]
+               public PerformanceCounterInstanceLifetime InstanceLifetime {
+                       get { return lifetime; }
+                       set { lifetime = value; }
                }
 
                [DefaultValue (""), ReadOnly (true), RecommendedAsConfigurable (true)]
                [TypeConverter ("System.Diagnostics.Design.InstanceNameConverter, " + Consts.AssemblySystem_Design)]
                [SRDescription ("The instance name for this performance counter.")]
-               public string InstanceName 
-                       {
+               public string InstanceName {
                        get {return instanceName;}
-                       set {instanceName = value;}
+                       set {
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+                               instanceName = value;
+                               changed = true;
+                       }
                }
 
                // may throw ArgumentException if machine name format is wrong
@@ -166,17 +231,36 @@ namespace System.Diagnostics {
                [SRDescription ("The machine where this performance counter resides.")]
                public string MachineName {
                        get {return machineName;}
-                       set {machineName = value;}
+                       set {
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+                               if (value == "" || value == ".") {
+                                       machineName = ".";
+                                       changed = true;
+                                       return;
+                               }
+                               throw new PlatformNotSupportedException ();
+                       }
                }
 
                // may throw InvalidOperationException, Win32Exception
-               [MonoTODO]
                [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                [MonitoringDescription ("The raw value of the counter.")]
                public long RawValue {
-                       get {return 0;}
+                       get {
+                               CounterSample sample;
+                               if (changed)
+                                       UpdateInfo ();
+                               GetSample (impl, true, out sample);
+                               // should this update old_sample as well?
+                               return sample.RawValue;
+                       }
                        set {
-                               throw new NotImplementedException ();
+                               if (changed)
+                                       UpdateInfo ();
+                               if (readOnly)
+                                       throw new InvalidOperationException ();
+                               UpdateValue (impl, false, value);
                        }
                }
 
@@ -187,73 +271,92 @@ namespace System.Diagnostics {
                        set {readOnly = value;}
                }
 
-               [MonoTODO]
                public void BeginInit ()
                {
-                       throw new NotImplementedException ();
+                       // we likely don't need to do anything significant here
+               }
+
+               public void EndInit ()
+               {
+                       // we likely don't need to do anything significant here
                }
 
-               [MonoTODO]
                public void Close ()
                {
-                       throw new NotImplementedException ();
+                       IntPtr p = impl;
+                       impl = IntPtr.Zero;
+                       if (p != IntPtr.Zero)
+                               FreeData (p);
                }
 
-               [MonoTODO]
                public static void CloseSharedResources ()
                {
-                       throw new NotImplementedException ();
+                       // we likely don't need to do anything significant here
                }
 
                // may throw InvalidOperationException, Win32Exception
-               [MonoTODO]
                public long Decrement ()
                {
-                       throw new NotImplementedException ();
+                       return IncrementBy (-1);
                }
 
-               [MonoTODO]
                protected override void Dispose (bool disposing)
                {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void EndInit ()
-               {
-                       throw new NotImplementedException ();
+                       Close ();
                }
 
                // may throw InvalidOperationException, Win32Exception
-               [MonoTODO]
                public long Increment ()
                {
-                       throw new NotImplementedException ();
+                       return IncrementBy (1);
                }
 
                // may throw InvalidOperationException, Win32Exception
-               [MonoTODO]
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                public long IncrementBy (long value)
                {
-                       throw new NotImplementedException ();
+                       if (changed)
+                               UpdateInfo ();
+                       if (readOnly) {
+                               // FIXME: This should really throw, but by now set this workaround in place.
+                               //throw new InvalidOperationException ();
+                               return 0;
+                       }
+                       return UpdateValue (impl, true, value);
                }
 
                // may throw InvalidOperationException, Win32Exception
-               [MonoTODO]
                public CounterSample NextSample ()
                {
-                       throw new NotImplementedException ();
+                       CounterSample sample;
+                       if (changed)
+                               UpdateInfo ();
+                       GetSample (impl, false, out sample);
+                       valid_old = true;
+                       old_sample = sample;
+                       return sample;
                }
 
                // may throw InvalidOperationException, Win32Exception
-               [MonoTODO]
                public float NextValue ()
                {
-                       throw new NotImplementedException ();
+                       CounterSample sample;
+                       if (changed)
+                               UpdateInfo ();
+                       GetSample (impl, false, out sample);
+                       float val;
+                       if (valid_old)
+                               val = CounterSampleCalculator.ComputeCounterValue (old_sample, sample);
+                       else
+                               val = CounterSampleCalculator.ComputeCounterValue (sample);
+                       valid_old = true;
+                       old_sample = sample;
+                       return val;
                }
 
                // may throw InvalidOperationException, Win32Exception
                [MonoTODO]
+               [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                public void RemoveInstance ()
                {
                        throw new NotImplementedException ();