f76f0950f459bbf951ebbf0ebba82e30b0f097bf
[mono.git] / mcs / class / System / System.Diagnostics / PerformanceCounter.cs
1 //
2 // System.Diagnostics.PerformanceCounter.cs
3 //
4 // Authors:
5 //   Jonathan Pryor (jonpryor@vt.edu)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8 // (C) 2002
9 // (C) 2003 Andreas Nahr
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32
33 using System;
34 using System.ComponentModel;
35 using System.ComponentModel.Design;
36 using System.Diagnostics;
37 using System.Runtime.InteropServices;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.ConstrainedExecution;
40
41 namespace System.Diagnostics {
42
43         // must be safe for multithreaded operations
44         [InstallerType (typeof (PerformanceCounterInstaller))]
45         public sealed class PerformanceCounter : Component, ISupportInitialize 
46         {
47
48                 private string categoryName;
49                 private string counterName;
50                 private string instanceName;
51                 private string machineName;
52                 IntPtr impl;
53                 PerformanceCounterType type;
54                 CounterSample old_sample;
55                 private bool readOnly;
56                 bool valid_old;
57                 bool changed;
58                 bool is_custom;
59                 private PerformanceCounterInstanceLifetime lifetime;
60
61                 [Obsolete]
62                 public static int DefaultFileMappingSize = 524288;
63
64                 // set catname, countname, instname to "", machname to "."
65                 public PerformanceCounter ()
66                 {
67                         categoryName = counterName = instanceName = "";
68                         machineName = ".";
69                 }
70
71                 // throws: InvalidOperationException (if catName or countName
72                 // is ""); ArgumentNullException if either is null
73                 // sets instName to "", machname to "."
74                 public PerformanceCounter (String categoryName, 
75                         string counterName)
76                         : this (categoryName, counterName, false)
77                 {
78                 }
79
80                 public PerformanceCounter (string categoryName, 
81                         string counterName,
82                         bool readOnly)
83                         : this (categoryName, counterName, "", readOnly)
84                 {
85                 }
86
87                 public PerformanceCounter (string categoryName,
88                         string counterName,
89                         string instanceName)
90                         : this (categoryName, counterName, instanceName, false)
91                 {
92                 }
93
94                 public PerformanceCounter (string categoryName,
95                         string counterName,
96                         string instanceName,
97                         bool readOnly)
98                 {
99
100                         if (categoryName == null)
101                                 throw new ArgumentNullException ("categoryName");
102                         if (counterName == null)
103                                 throw new ArgumentNullException ("counterName");
104                         if (instanceName == null)
105                                 throw new ArgumentNullException ("instanceName");
106                         CategoryName = categoryName;
107                         CounterName = counterName;
108
109                         if (categoryName == "" || counterName == "")
110                                 throw new InvalidOperationException ();
111
112                         InstanceName = instanceName;
113                         this.instanceName = instanceName;
114                         this.machineName = ".";
115                         this.readOnly = readOnly;
116                         changed = true;
117                 }
118
119                 public PerformanceCounter (string categoryName,
120                         string counterName,
121                         string instanceName,
122                         string machineName)
123                         : this (categoryName, counterName, instanceName, false)
124                 {
125                         this.machineName = machineName;
126                 }
127
128                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
129                 static extern IntPtr GetImpl (string category, string counter,
130                                 string instance, string machine, out PerformanceCounterType ctype, out bool custom);
131
132                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
133                 static extern bool GetSample (IntPtr impl, bool only_value, out CounterSample sample);
134
135                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
136                 static extern long UpdateValue (IntPtr impl, bool do_incr, long value);
137
138                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
139                 static extern void FreeData (IntPtr impl);
140
141                 /* the perf counter has changed, ensure it's valid and setup it to
142                  * be able to collect/update data
143                  */
144                 void UpdateInfo ()
145                 {
146                         // need to free the previous info
147                         if (impl != IntPtr.Zero)
148                                 Close ();
149                         impl = GetImpl (categoryName, counterName, instanceName, machineName, out type, out is_custom);
150                         // system counters are always readonly
151                         if (!is_custom)
152                                 readOnly = true;
153                         // invalid counter, need to handle out of mem
154
155                         // TODO: reenable this
156                         //if (impl == IntPtr.Zero)
157                         //      throw new InvalidOperationException ();
158                         changed = false;
159                 }
160
161                 // may throw ArgumentNullException
162                 [DefaultValue (""), ReadOnly (true), RecommendedAsConfigurable (true)]
163                 [TypeConverter ("System.Diagnostics.Design.CategoryValueConverter, " + Consts.AssemblySystem_Design)]
164                 [SRDescription ("The category name for this performance counter.")]
165                 public string CategoryName {
166                         get {return categoryName;}
167                         set {
168                                 if (value == null)
169                                         throw new ArgumentNullException ("categoryName");
170                                 categoryName = value;
171                                 changed = true;
172                         }
173                 }
174
175                 // may throw InvalidOperationException
176                 [MonoTODO]
177                 [ReadOnly (true), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
178                 [MonitoringDescription ("A description describing the counter.")]
179                 public string CounterHelp {
180                         get {return "";}
181                 }
182
183                 // may throw ArgumentNullException
184                 [DefaultValue (""), ReadOnly (true), RecommendedAsConfigurable (true)]
185                 [TypeConverter ("System.Diagnostics.Design.CounterNameConverter, " + Consts.AssemblySystem_Design)]
186                 [SRDescription ("The name of this performance counter.")]
187                 public string CounterName 
188                         {
189                         get {return counterName;}
190                         set {
191                                 if (value == null)
192                                         throw new ArgumentNullException ("counterName");
193                                 counterName = value;
194                                 changed = true;
195                         }
196                 }
197
198                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
199                 [MonitoringDescription ("The type of the counter.")]
200                 public PerformanceCounterType CounterType {
201                         get {
202                                 if (changed)
203                                         UpdateInfo ();
204                                 return type;
205                         }
206                 }
207
208                 [MonoTODO]
209                 [DefaultValue (PerformanceCounterInstanceLifetime.Global)]
210                 public PerformanceCounterInstanceLifetime InstanceLifetime {
211                         get { return lifetime; }
212                         set { lifetime = value; }
213                 }
214
215                 [DefaultValue (""), ReadOnly (true), RecommendedAsConfigurable (true)]
216                 [TypeConverter ("System.Diagnostics.Design.InstanceNameConverter, " + Consts.AssemblySystem_Design)]
217                 [SRDescription ("The instance name for this performance counter.")]
218                 public string InstanceName {
219                         get {return instanceName;}
220                         set {
221                                 if (value == null)
222                                         throw new ArgumentNullException ("value");
223                                 instanceName = value;
224                                 changed = true;
225                         }
226                 }
227
228                 // may throw ArgumentException if machine name format is wrong
229                 [MonoTODO("What's the machine name format?")]
230                 [DefaultValue ("."), Browsable (false), RecommendedAsConfigurable (true)]
231                 [SRDescription ("The machine where this performance counter resides.")]
232                 public string MachineName {
233                         get {return machineName;}
234                         set {
235                                 if (value == null)
236                                         throw new ArgumentNullException ("value");
237                                 if (value == "" || value == ".") {
238                                         machineName = ".";
239                                         changed = true;
240                                         return;
241                                 }
242                                 throw new PlatformNotSupportedException ();
243                         }
244                 }
245
246                 // may throw InvalidOperationException, Win32Exception
247                 [Browsable (false), DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
248                 [MonitoringDescription ("The raw value of the counter.")]
249                 public long RawValue {
250                         get {
251                                 CounterSample sample;
252                                 if (changed)
253                                         UpdateInfo ();
254                                 GetSample (impl, true, out sample);
255                                 // should this update old_sample as well?
256                                 return sample.RawValue;
257                         }
258                         set {
259                                 if (changed)
260                                         UpdateInfo ();
261                                 if (readOnly)
262                                         throw new InvalidOperationException ();
263                                 UpdateValue (impl, false, value);
264                         }
265                 }
266
267                 [Browsable (false), DefaultValue (true)]
268                 [MonitoringDescription ("The accessability level of the counter.")]
269                 public bool ReadOnly {
270                         get {return readOnly;}
271                         set {readOnly = value;}
272                 }
273
274                 public void BeginInit ()
275                 {
276                         // we likely don't need to do anything significant here
277                 }
278
279                 public void EndInit ()
280                 {
281                         // we likely don't need to do anything significant here
282                 }
283
284                 public void Close ()
285                 {
286                         IntPtr p = impl;
287                         impl = IntPtr.Zero;
288                         if (p != IntPtr.Zero)
289                                 FreeData (p);
290                 }
291
292                 public static void CloseSharedResources ()
293                 {
294                         // we likely don't need to do anything significant here
295                 }
296
297                 // may throw InvalidOperationException, Win32Exception
298                 public long Decrement ()
299                 {
300                         return IncrementBy (-1);
301                 }
302
303                 protected override void Dispose (bool disposing)
304                 {
305                         Close ();
306                 }
307
308                 // may throw InvalidOperationException, Win32Exception
309                 public long Increment ()
310                 {
311                         return IncrementBy (1);
312                 }
313
314                 // may throw InvalidOperationException, Win32Exception
315                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
316                 public long IncrementBy (long value)
317                 {
318                         if (changed)
319                                 UpdateInfo ();
320                         if (readOnly) {
321                                 // FIXME: This should really throw, but by now set this workaround in place.
322                                 //throw new InvalidOperationException ();
323                                 return 0;
324                         }
325                         return UpdateValue (impl, true, value);
326                 }
327
328                 // may throw InvalidOperationException, Win32Exception
329                 public CounterSample NextSample ()
330                 {
331                         CounterSample sample;
332                         if (changed)
333                                 UpdateInfo ();
334                         GetSample (impl, false, out sample);
335                         valid_old = true;
336                         old_sample = sample;
337                         return sample;
338                 }
339
340                 // may throw InvalidOperationException, Win32Exception
341                 public float NextValue ()
342                 {
343                         CounterSample sample;
344                         if (changed)
345                                 UpdateInfo ();
346                         GetSample (impl, false, out sample);
347                         float val;
348                         if (valid_old)
349                                 val = CounterSampleCalculator.ComputeCounterValue (old_sample, sample);
350                         else
351                                 val = CounterSampleCalculator.ComputeCounterValue (sample);
352                         valid_old = true;
353                         old_sample = sample;
354                         return val;
355                 }
356
357                 // may throw InvalidOperationException, Win32Exception
358                 [MonoTODO]
359                 [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
360                 public void RemoveInstance ()
361                 {
362                         throw new NotImplementedException ();
363                 }
364         }
365 }
366