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
{
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 "."
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;
this.instanceName = instanceName;
this.machineName = ".";
this.readOnly = readOnly;
+ changed = true;
}
public PerformanceCounter (string categoryName,
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)]
if (value == null)
throw new ArgumentNullException ("categoryName");
categoryName = value;
+ changed = true;
}
}
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
[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);
}
}
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 ();