Initial commit
[mono.git] / mcs / class / referencesource / System.Core / System / Diagnostics / PerformanceData / CounterSetInstance.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="CounterSetInstance.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 namespace System.Diagnostics.PerformanceData {
8     using System;
9     using System.Threading;
10     using System.Runtime.InteropServices;
11     using System.ComponentModel;
12     using System.Diagnostics;
13     using System.Diagnostics.CodeAnalysis;
14     using System.Security;
15     using Microsoft.Win32;
16
17     /// <summary>
18     /// CounterSetInstance class maps to "Instace" in native performance counter implementation.
19     /// </summary>
20     [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
21     public sealed class CounterSetInstance : IDisposable {
22         internal        CounterSet                                         m_counterSet;
23         internal        String                                             m_instName;
24         private         Int32                                              m_active;
25         private         CounterSetInstanceCounterDataSet                   m_counters;
26         [SecurityCritical]
27         unsafe internal UnsafeNativeMethods.PerfCounterSetInstanceStruct * m_nativeInst;
28
29         [System.Security.SecurityCritical]
30         [SuppressMessage("Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly")]
31         internal CounterSetInstance(CounterSet counterSetDefined, String instanceName) {
32             if (counterSetDefined == null) {
33                 throw new ArgumentNullException("counterSetDefined");
34             }
35             if (instanceName == null) {
36                 throw new ArgumentNullException("InstanceName");
37             }
38             if (instanceName.Length == 0) {
39                 throw new ArgumentException(SR.GetString(SR.Perflib_Argument_EmptyInstanceName), "InstanceName");
40             }
41
42             m_counterSet = counterSetDefined;
43             m_instName   = instanceName;
44             unsafe {
45                 m_nativeInst = UnsafeNativeMethods.PerfCreateInstance(
46                         m_counterSet.m_provider.m_hProvider, ref m_counterSet.m_counterSet, m_instName, 0);
47                 int Status = (int) ((m_nativeInst != null) ? UnsafeNativeMethods.ERROR_SUCCESS : Marshal.GetLastWin32Error());
48                 if (m_nativeInst != null) {
49                     m_counters = new CounterSetInstanceCounterDataSet(this);
50                 }
51                 else {
52                     // ERROR_INVALID_PARAMETER,
53                     // ERROR_NOT_FOUND (cannot find installed CounterSet),
54                     // ERROR_ALREADY_EXISTS,
55                     // ERROR_NOT_ENOUGH_MEMORY
56
57                     switch (Status) {
58                         case (int) UnsafeNativeMethods.ERROR_ALREADY_EXISTS:
59                             throw new ArgumentException(SR.GetString(SR.Perflib_Argument_InstanceAlreadyExists, m_instName, m_counterSet.m_counterSet), "InstanceName");
60
61                         case (int) UnsafeNativeMethods.ERROR_NOT_FOUND:
62                             throw new InvalidOperationException( SR.GetString(SR.Perflib_InvalidOperation_CounterSetNotInstalled, m_counterSet.m_counterSet));
63
64                         case (int) UnsafeNativeMethods.ERROR_INVALID_PARAMETER:
65                             if (m_counterSet.m_instType == CounterSetInstanceType.Single) {
66                                 throw new ArgumentException(SR.GetString(SR.Perflib_Argument_InvalidInstance, m_counterSet.m_counterSet), "InstanceName");
67                             }
68                             else {
69                                 throw new Win32Exception(Status);
70                             }
71
72                         default:
73                             throw new Win32Exception(Status);
74                     }
75                 }
76             }
77
78             m_active = 1;
79         }
80
81         [System.Security.SecurityCritical]
82         public void Dispose() {
83             Dispose(true);
84             GC.SuppressFinalize(this);
85         }
86         [System.Security.SecurityCritical]
87         ~CounterSetInstance() {
88             Dispose(false);
89         }
90         [System.Security.SecurityCritical]
91         private void Dispose(bool disposing) {
92             if (disposing) {
93                 if (m_counters != null) {
94                     m_counters.Dispose();
95                     m_counters = null;
96                 }
97             }
98             unsafe {
99                 if (m_nativeInst != null) {
100                     if (Interlocked.Exchange(ref m_active, 0) != 0) {
101                         if (m_nativeInst != null) {
102                             lock(m_counterSet) {
103                                 if (m_counterSet.m_provider != null) {
104                                     uint Status = UnsafeNativeMethods.PerfDeleteInstance(m_counterSet.m_provider.m_hProvider, m_nativeInst);
105                                 }
106                                 m_nativeInst = null;
107                             }
108                         }
109                     }
110                 }
111             }            
112         }
113
114         /// <summary>
115         /// Access CounterSetInstanceCounterDataSet property. Developers can then use defined indexer to access
116         /// specific CounterData object to query/update raw counter data.
117         /// </summary>
118         public CounterSetInstanceCounterDataSet Counters {
119             get { return m_counters; }
120         }
121     }
122 }
123