You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			326 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			326 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| // <copyright file="DbConnectionPoolCounters.cs" company="Microsoft">
 | |
| //      Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| // </copyright>
 | |
| // <owner current="true" primary="true">Microsoft</owner>
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| namespace System.Data.ProviderBase {
 | |
| 
 | |
|     using System;
 | |
|     using System.Collections;
 | |
|     using System.Data.Common;
 | |
|     using System.Diagnostics;
 | |
|     using System.Globalization;
 | |
|     using System.Reflection;
 | |
|     using System.Runtime.ConstrainedExecution;
 | |
|     using System.Security;
 | |
|     using System.Security.Permissions;
 | |
|     using System.Security.Principal;
 | |
|     using System.Runtime.Versioning;
 | |
| 
 | |
|     internal abstract class DbConnectionPoolCounters {
 | |
|         private static class CreationData {
 | |
| 
 | |
|             static internal readonly CounterCreationData HardConnectsPerSecond = new CounterCreationData(
 | |
|                                                                         "HardConnectsPerSecond",
 | |
|                                                                         "The number of actual connections per second that are being made to servers",
 | |
|                                                                         PerformanceCounterType.RateOfCountsPerSecond32);
 | |
| 
 | |
|             static internal readonly CounterCreationData HardDisconnectsPerSecond = new CounterCreationData(
 | |
|                                                                         "HardDisconnectsPerSecond",
 | |
|                                                                         "The number of actual disconnects per second that are being made to servers",
 | |
|                                                                         PerformanceCounterType.RateOfCountsPerSecond32);
 | |
| 
 | |
|             static internal readonly CounterCreationData SoftConnectsPerSecond = new CounterCreationData(
 | |
|                                                                         "SoftConnectsPerSecond",
 | |
|                                                                         "The number of connections we get from the pool per second",
 | |
|                                                                         PerformanceCounterType.RateOfCountsPerSecond32);
 | |
| 
 | |
|             static internal readonly CounterCreationData SoftDisconnectsPerSecond = new CounterCreationData(
 | |
|                                                                         "SoftDisconnectsPerSecond",
 | |
|                                                                         "The number of connections we return to the pool per second",
 | |
|                                                                         PerformanceCounterType.RateOfCountsPerSecond32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfNonPooledConnections = new CounterCreationData(
 | |
|                                                                         "NumberOfNonPooledConnections",
 | |
|                                                                         "The number of connections that are not using connection pooling",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfPooledConnections = new CounterCreationData(
 | |
|                                                                         "NumberOfPooledConnections",
 | |
|                                                                         "The number of connections that are managed by the connection pooler",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfActiveConnectionPoolGroups = new CounterCreationData(
 | |
|                                                                         "NumberOfActiveConnectionPoolGroups",
 | |
|                                                                         "The number of unique connection strings",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfInactiveConnectionPoolGroups = new CounterCreationData(
 | |
|                                                                         "NumberOfInactiveConnectionPoolGroups",
 | |
|                                                                         "The number of unique connection strings waiting for pruning",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfActiveConnectionPools = new CounterCreationData(
 | |
|                                                                         "NumberOfActiveConnectionPools",
 | |
|                                                                         "The number of connection pools",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfInactiveConnectionPools = new CounterCreationData(
 | |
|                                                                         "NumberOfInactiveConnectionPools",
 | |
|                                                                         "The number of connection pools",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfActiveConnections = new CounterCreationData(
 | |
|                                                                         "NumberOfActiveConnections",
 | |
|                                                                         "The number of connections currently in-use",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfFreeConnections = new CounterCreationData(
 | |
|                                                                         "NumberOfFreeConnections",
 | |
|                                                                         "The number of connections currently available for use",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfStasisConnections = new CounterCreationData(
 | |
|                                                                         "NumberOfStasisConnections",
 | |
|                                                                         "The number of connections currently waiting to be made ready for use",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
| 
 | |
|             static internal readonly CounterCreationData NumberOfReclaimedConnections = new CounterCreationData(
 | |
|                                                                         "NumberOfReclaimedConnections",
 | |
|                                                                         "The number of connections we reclaim from GC'd external connections",
 | |
|                                                                         PerformanceCounterType.NumberOfItems32);
 | |
|         };
 | |
| 
 | |
|         sealed internal class Counter {
 | |
|             private PerformanceCounter _instance;
 | |
|             
 | |
|             internal Counter (string categoryName, string instanceName, string counterName, PerformanceCounterType counterType) {
 | |
|                 if (ADP.IsPlatformNT5) {
 | |
|                     try {
 | |
|                         if (!ADP.IsEmpty(categoryName) && !ADP.IsEmpty(instanceName)) {
 | |
|                             PerformanceCounter instance = new PerformanceCounter();
 | |
|                             instance.CategoryName = categoryName;
 | |
|                             instance.CounterName = counterName;
 | |
|                             instance.InstanceName = instanceName;
 | |
|                             instance.InstanceLifetime = PerformanceCounterInstanceLifetime.Process;
 | |
|                             instance.ReadOnly = false;
 | |
|                             instance.RawValue = 0;  // make sure we start out at zero
 | |
|                             _instance = instance;
 | |
|                         }
 | |
|                     }
 | |
|                     catch (InvalidOperationException e) {
 | |
|                         ADP.TraceExceptionWithoutRethrow(e);
 | |
|                         // 
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
| 
 | |
|             internal void Decrement() {
 | |
|                 PerformanceCounter instance = _instance;
 | |
|                 if (null != instance) {
 | |
|                     instance.Decrement();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
 | |
|             internal void Dispose () { // 
 | |
|                 PerformanceCounter instance = _instance;
 | |
|                 _instance = null;
 | |
|                 if (null != instance) {
 | |
|                     instance.RemoveInstance();
 | |
|                     // should we be calling instance.Close?
 | |
|                     // if we do will it exacerbate the Dispose vs. Decrement race condition
 | |
|                     //instance.Close();
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             internal void Increment() {
 | |
|                 PerformanceCounter instance = _instance;
 | |
|                 if (null != instance) {
 | |
|                     instance.Increment();
 | |
|                 }
 | |
|             }
 | |
|         };
 | |
| 
 | |
|         const int CounterInstanceNameMaxLength = 127;
 | |
| 
 | |
|         internal readonly Counter HardConnectsPerSecond;
 | |
|         internal readonly Counter HardDisconnectsPerSecond;
 | |
|         internal readonly Counter SoftConnectsPerSecond;
 | |
|         internal readonly Counter SoftDisconnectsPerSecond;
 | |
|         internal readonly Counter NumberOfNonPooledConnections;
 | |
|         internal readonly Counter NumberOfPooledConnections;
 | |
|         internal readonly Counter NumberOfActiveConnectionPoolGroups;
 | |
|         internal readonly Counter NumberOfInactiveConnectionPoolGroups;
 | |
|         internal readonly Counter NumberOfActiveConnectionPools;
 | |
|         internal readonly Counter NumberOfInactiveConnectionPools;
 | |
|         internal readonly Counter NumberOfActiveConnections;
 | |
|         internal readonly Counter NumberOfFreeConnections;
 | |
|         internal readonly Counter NumberOfStasisConnections;
 | |
|         internal readonly Counter NumberOfReclaimedConnections;
 | |
|         
 | |
|         protected DbConnectionPoolCounters() : this(null, null) {
 | |
|         }
 | |
| 
 | |
|         protected DbConnectionPoolCounters(string categoryName, string categoryHelp) {
 | |
|             AppDomain.CurrentDomain.DomainUnload += new EventHandler(this.UnloadEventHandler);
 | |
|             AppDomain.CurrentDomain.ProcessExit += new EventHandler(this.ExitEventHandler);
 | |
|             AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(this.ExceptionEventHandler);
 | |
|             
 | |
|             string instanceName = null;
 | |
| 
 | |
|             if (!ADP.IsEmpty(categoryName)) {
 | |
|                 if (ADP.IsPlatformNT5) {
 | |
|                     instanceName = GetInstanceName();
 | |
|                 }
 | |
|             }
 | |
|             
 | |
|             // level 0-3: hard connects/disconnects, plus basic pool/pool entry statistics
 | |
|             string basicCategoryName = categoryName;            
 | |
|             HardConnectsPerSecond = new Counter(basicCategoryName, instanceName, CreationData.HardConnectsPerSecond.CounterName, CreationData.HardConnectsPerSecond.CounterType);
 | |
|             HardDisconnectsPerSecond = new Counter(basicCategoryName, instanceName, CreationData.HardDisconnectsPerSecond.CounterName, CreationData.HardDisconnectsPerSecond.CounterType);
 | |
|             NumberOfNonPooledConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfNonPooledConnections.CounterName, CreationData.NumberOfNonPooledConnections.CounterType);
 | |
|             NumberOfPooledConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfPooledConnections.CounterName, CreationData.NumberOfPooledConnections.CounterType);
 | |
|             NumberOfActiveConnectionPoolGroups = new Counter(basicCategoryName, instanceName, CreationData.NumberOfActiveConnectionPoolGroups.CounterName, CreationData.NumberOfActiveConnectionPoolGroups.CounterType);
 | |
|             NumberOfInactiveConnectionPoolGroups = new Counter(basicCategoryName, instanceName, CreationData.NumberOfInactiveConnectionPoolGroups.CounterName, CreationData.NumberOfInactiveConnectionPoolGroups.CounterType);
 | |
|             NumberOfActiveConnectionPools = new Counter(basicCategoryName, instanceName, CreationData.NumberOfActiveConnectionPools.CounterName, CreationData.NumberOfActiveConnectionPools.CounterType);
 | |
|             NumberOfInactiveConnectionPools = new Counter(basicCategoryName, instanceName, CreationData.NumberOfInactiveConnectionPools.CounterName, CreationData.NumberOfInactiveConnectionPools.CounterType);
 | |
|             NumberOfStasisConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfStasisConnections.CounterName, CreationData.NumberOfStasisConnections.CounterType);
 | |
|             NumberOfReclaimedConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfReclaimedConnections.CounterName, CreationData.NumberOfReclaimedConnections.CounterType);
 | |
|             
 | |
|             // level 4: expensive stuff
 | |
|             string verboseCategoryName = null;
 | |
|             if (!ADP.IsEmpty(categoryName)) {
 | |
|                 // don't load TraceSwitch if no categoryName so that Odbc/OleDb have a chance of not loading TraceSwitch
 | |
|                 // which are also used by System.Diagnostics.PerformanceCounter.ctor & System.Transactions.get_Current
 | |
|                 TraceSwitch perfCtrSwitch = new TraceSwitch("ConnectionPoolPerformanceCounterDetail", "level of detail to track with connection pool performance counters");
 | |
|                 if (TraceLevel.Verbose == perfCtrSwitch.Level) {
 | |
|                     verboseCategoryName = categoryName;
 | |
|                 }
 | |
|             }
 | |
|             SoftConnectsPerSecond = new Counter(verboseCategoryName, instanceName, CreationData.SoftConnectsPerSecond.CounterName, CreationData.SoftConnectsPerSecond.CounterType);
 | |
|             SoftDisconnectsPerSecond = new Counter(verboseCategoryName, instanceName, CreationData.SoftDisconnectsPerSecond.CounterName, CreationData.SoftDisconnectsPerSecond.CounterType);
 | |
|             NumberOfActiveConnections = new Counter(verboseCategoryName, instanceName, CreationData.NumberOfActiveConnections.CounterName, CreationData.NumberOfActiveConnections.CounterType);
 | |
|             NumberOfFreeConnections = new Counter(verboseCategoryName, instanceName, CreationData.NumberOfFreeConnections.CounterName, CreationData.NumberOfFreeConnections.CounterType);
 | |
|         }
 | |
| 
 | |
|         [FileIOPermission(SecurityAction.Assert, Unrestricted=true)]
 | |
|         private string GetAssemblyName() {
 | |
|             string result = null;
 | |
| 
 | |
|             // First try GetEntryAssembly name, then AppDomain.FriendlyName.
 | |
|             Assembly assembly = Assembly.GetEntryAssembly();
 | |
| 
 | |
|             if (null != assembly) {
 | |
|                 AssemblyName name = assembly.GetName();
 | |
|                 if (name != null) {
 | |
|                     result = name.Name; // MDAC 73469
 | |
|                 }
 | |
|             }
 | |
|             return result;
 | |
|         }
 | |
| 
 | |
|         // SxS: this method uses GetCurrentProcessId to construct the instance name.
 | |
|         // 
 | |
|         [ResourceExposure(ResourceScope.None)]
 | |
|         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
 | |
|         private string GetInstanceName() {
 | |
|             string result = null;
 | |
| 
 | |
|             string instanceName = GetAssemblyName(); // instance perfcounter name
 | |
| 
 | |
|             if (ADP.IsEmpty(instanceName)) {
 | |
|                 AppDomain appDomain = AppDomain.CurrentDomain;
 | |
|                 if (null != appDomain) {
 | |
|                     instanceName = appDomain.FriendlyName;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // 
 | |
|             int pid = SafeNativeMethods.GetCurrentProcessId();
 | |
| 
 | |
| 
 | |
|             // SQLBUDT #366157 -there are several characters which have special meaning
 | |
|             // to PERFMON.  They recommend that we translate them as shown below, to 
 | |
|             // prevent problems.
 | |
| 
 | |
|             result = String.Format((IFormatProvider)null, "{0}[{1}]", instanceName, pid);
 | |
|             result = result.Replace('(','[').Replace(')',']').Replace('#','_').Replace('/','_').Replace('\\','_'); 
 | |
| 
 | |
|             // SQLBUVSTS #94625 - counter instance name cannot be greater than 127
 | |
|             if (result.Length > CounterInstanceNameMaxLength) {
 | |
|                 // Replacing the middle part with "[...]"
 | |
|                 // For example: if path is c:\long_path\very_(Ax200)_long__path\perftest.exe and process ID is 1234 than the resulted instance name will be: 
 | |
|                 // c:\long_path\very_(AxM)[...](AxN)_long__path\perftest.exe[1234]
 | |
|                 // while M and N are adjusted to make each part before and after the [...] = 61 (making the total = 61 + 5 + 61 = 127)
 | |
|                 const string insertString = "[...]";
 | |
|                 int firstPartLength = (CounterInstanceNameMaxLength - insertString.Length) / 2;
 | |
|                 int lastPartLength = CounterInstanceNameMaxLength - firstPartLength - insertString.Length;
 | |
|                 result = string.Format((IFormatProvider)null, "{0}{1}{2}",
 | |
|                     result.Substring(0, firstPartLength),
 | |
|                     insertString,
 | |
|                     result.Substring(result.Length - lastPartLength, lastPartLength));
 | |
| 
 | |
|                 Debug.Assert(result.Length == CounterInstanceNameMaxLength, 
 | |
|                     string.Format((IFormatProvider)null, "wrong calculation of the instance name: expected {0}, actual: {1}", CounterInstanceNameMaxLength, result.Length));
 | |
|             }
 | |
| 
 | |
|             return result;
 | |
|         }
 | |
| 
 | |
|         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
 | |
|         public void Dispose() {
 | |
|             // ExceptionEventHandler with IsTerminiating may be called before
 | |
|             // the Connection Close is called or the variables are initialized
 | |
|             SafeDispose(HardConnectsPerSecond);
 | |
|             SafeDispose(HardDisconnectsPerSecond);
 | |
|             SafeDispose(SoftConnectsPerSecond);
 | |
|             SafeDispose(SoftDisconnectsPerSecond);
 | |
|             SafeDispose(NumberOfNonPooledConnections);
 | |
|             SafeDispose(NumberOfPooledConnections);
 | |
|             SafeDispose(NumberOfActiveConnectionPoolGroups);
 | |
|             SafeDispose(NumberOfInactiveConnectionPoolGroups);
 | |
|             SafeDispose(NumberOfActiveConnectionPools);
 | |
|             SafeDispose(NumberOfActiveConnections);
 | |
|             SafeDispose(NumberOfFreeConnections);
 | |
|             SafeDispose(NumberOfStasisConnections);
 | |
|             SafeDispose(NumberOfReclaimedConnections);
 | |
|         }
 | |
| 
 | |
|         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
 | |
|         private void SafeDispose(Counter counter) { // WebData 103603
 | |
|             if (null != counter) {
 | |
|                 counter.Dispose();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [PrePrepareMethod]
 | |
|         void ExceptionEventHandler (object sender, UnhandledExceptionEventArgs e) {
 | |
|             if ((null != e) && e.IsTerminating) {
 | |
|                 Dispose();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [PrePrepareMethod]
 | |
|         void ExitEventHandler (object sender, EventArgs e) {
 | |
|             Dispose();
 | |
|         }
 | |
| 
 | |
|         [PrePrepareMethod]
 | |
|         void UnloadEventHandler (object sender, EventArgs e) {
 | |
|             Dispose();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     sealed internal class DbConnectionPoolCountersNoCounters : DbConnectionPoolCounters {
 | |
| 
 | |
|         public static readonly DbConnectionPoolCountersNoCounters SingletonInstance = new DbConnectionPoolCountersNoCounters();
 | |
| 
 | |
|         private DbConnectionPoolCountersNoCounters() : base () {
 | |
|         }
 | |
|     }
 | |
| }
 |