6bdd276d05
Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
367 lines
10 KiB
C#
367 lines
10 KiB
C#
//
|
|
// System.Diagnostics.PerformanceCounter.cs
|
|
//
|
|
// Authors:
|
|
// Jonathan Pryor (jonpryor@vt.edu)
|
|
// Andreas Nahr (ClassDevelopment@A-SoftTech.com)
|
|
//
|
|
// (C) 2002
|
|
// (C) 2003 Andreas Nahr
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
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
|
|
[InstallerType (typeof (PerformanceCounterInstaller))]
|
|
public sealed class PerformanceCounter : Component, ISupportInitialize
|
|
{
|
|
|
|
private string categoryName;
|
|
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 "."
|
|
public PerformanceCounter ()
|
|
{
|
|
categoryName = counterName = instanceName = "";
|
|
machineName = ".";
|
|
}
|
|
|
|
// throws: InvalidOperationException (if catName or countName
|
|
// is ""); ArgumentNullException if either is null
|
|
// sets instName to "", machname to "."
|
|
public PerformanceCounter (String categoryName,
|
|
string counterName)
|
|
: this (categoryName, counterName, false)
|
|
{
|
|
}
|
|
|
|
public PerformanceCounter (string categoryName,
|
|
string counterName,
|
|
bool readOnly)
|
|
: this (categoryName, counterName, "", readOnly)
|
|
{
|
|
}
|
|
|
|
public PerformanceCounter (string categoryName,
|
|
string counterName,
|
|
string instanceName)
|
|
: this (categoryName, counterName, instanceName, false)
|
|
{
|
|
}
|
|
|
|
public PerformanceCounter (string categoryName,
|
|
string counterName,
|
|
string instanceName,
|
|
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;
|
|
|
|
if (categoryName == "" || counterName == "")
|
|
throw new InvalidOperationException ();
|
|
|
|
InstanceName = instanceName;
|
|
this.instanceName = instanceName;
|
|
this.machineName = ".";
|
|
this.readOnly = readOnly;
|
|
changed = true;
|
|
}
|
|
|
|
public PerformanceCounter (string categoryName,
|
|
string counterName,
|
|
string instanceName,
|
|
string machineName)
|
|
: this (categoryName, counterName, instanceName, false)
|
|
{
|
|
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), SettingsBindable (true)]
|
|
[TypeConverter ("System.Diagnostics.Design.CategoryValueConverter, " + Consts.AssemblySystem_Design)]
|
|
[SRDescription ("The category name for this performance counter.")]
|
|
public string CategoryName {
|
|
get {return categoryName;}
|
|
set {
|
|
if (value == null)
|
|
throw new ArgumentNullException ("categoryName");
|
|
categoryName = value;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
// may throw InvalidOperationException
|
|
[MonoTODO]
|
|
[ReadOnly (true), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
[MonitoringDescription ("A description describing the counter.")]
|
|
public string CounterHelp {
|
|
get {return "";}
|
|
}
|
|
|
|
// may throw ArgumentNullException
|
|
[DefaultValue (""), ReadOnly (true), SettingsBindable (true)]
|
|
[TypeConverter ("System.Diagnostics.Design.CounterNameConverter, " + Consts.AssemblySystem_Design)]
|
|
[SRDescription ("The name of this performance counter.")]
|
|
public string CounterName
|
|
{
|
|
get {return counterName;}
|
|
set {
|
|
if (value == null)
|
|
throw new ArgumentNullException ("counterName");
|
|
counterName = value;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
[MonitoringDescription ("The type of the counter.")]
|
|
public PerformanceCounterType CounterType {
|
|
get {
|
|
if (changed)
|
|
UpdateInfo ();
|
|
return type;
|
|
}
|
|
}
|
|
|
|
[MonoTODO]
|
|
[DefaultValue (PerformanceCounterInstanceLifetime.Global)]
|
|
public PerformanceCounterInstanceLifetime InstanceLifetime {
|
|
get { return lifetime; }
|
|
set { lifetime = value; }
|
|
}
|
|
|
|
[DefaultValue (""), ReadOnly (true), SettingsBindable (true)]
|
|
[TypeConverter ("System.Diagnostics.Design.InstanceNameConverter, " + Consts.AssemblySystem_Design)]
|
|
[SRDescription ("The instance name for this performance counter.")]
|
|
public string InstanceName {
|
|
get {return instanceName;}
|
|
set {
|
|
if (value == null)
|
|
throw new ArgumentNullException ("value");
|
|
instanceName = value;
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
// may throw ArgumentException if machine name format is wrong
|
|
[MonoTODO("What's the machine name format?")]
|
|
[DefaultValue ("."), Browsable (false), SettingsBindable (true)]
|
|
[SRDescription ("The machine where this performance counter resides.")]
|
|
public string MachineName {
|
|
get {return machineName;}
|
|
set {
|
|
if (value == null)
|
|
throw new ArgumentNullException ("value");
|
|
if (value == "" || value == ".") {
|
|
machineName = ".";
|
|
changed = true;
|
|
return;
|
|
}
|
|
throw new PlatformNotSupportedException ();
|
|
}
|
|
}
|
|
|
|
// may throw InvalidOperationException, Win32Exception
|
|
[Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
[MonitoringDescription ("The raw value of the counter.")]
|
|
public long RawValue {
|
|
get {
|
|
CounterSample sample;
|
|
if (changed)
|
|
UpdateInfo ();
|
|
GetSample (impl, true, out sample);
|
|
// should this update old_sample as well?
|
|
return sample.RawValue;
|
|
}
|
|
set {
|
|
if (changed)
|
|
UpdateInfo ();
|
|
if (readOnly)
|
|
throw new InvalidOperationException ();
|
|
UpdateValue (impl, false, value);
|
|
}
|
|
}
|
|
|
|
[Browsable (false), DefaultValue (true)]
|
|
[MonitoringDescription ("The accessability level of the counter.")]
|
|
public bool ReadOnly {
|
|
get {return readOnly;}
|
|
set {readOnly = value;}
|
|
}
|
|
|
|
public void BeginInit ()
|
|
{
|
|
// we likely don't need to do anything significant here
|
|
}
|
|
|
|
public void EndInit ()
|
|
{
|
|
// we likely don't need to do anything significant here
|
|
}
|
|
|
|
public void Close ()
|
|
{
|
|
IntPtr p = impl;
|
|
impl = IntPtr.Zero;
|
|
if (p != IntPtr.Zero)
|
|
FreeData (p);
|
|
}
|
|
|
|
public static void CloseSharedResources ()
|
|
{
|
|
// we likely don't need to do anything significant here
|
|
}
|
|
|
|
// may throw InvalidOperationException, Win32Exception
|
|
public long Decrement ()
|
|
{
|
|
return IncrementBy (-1);
|
|
}
|
|
|
|
protected override void Dispose (bool disposing)
|
|
{
|
|
Close ();
|
|
}
|
|
|
|
// may throw InvalidOperationException, Win32Exception
|
|
public long Increment ()
|
|
{
|
|
return IncrementBy (1);
|
|
}
|
|
|
|
// may throw InvalidOperationException, Win32Exception
|
|
[ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
|
|
public long IncrementBy (long value)
|
|
{
|
|
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
|
|
public CounterSample NextSample ()
|
|
{
|
|
CounterSample sample;
|
|
if (changed)
|
|
UpdateInfo ();
|
|
GetSample (impl, false, out sample);
|
|
valid_old = true;
|
|
old_sample = sample;
|
|
return sample;
|
|
}
|
|
|
|
// may throw InvalidOperationException, Win32Exception
|
|
public float NextValue ()
|
|
{
|
|
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 ();
|
|
}
|
|
}
|
|
}
|
|
|