context: using System;
  using System.Collections.Generic;
  using System.Runtime.CompilerServices;
  using System.Text;
  using System.Threading;
  
  using NHibernate.Cache;
  using NHibernate.Engine;
  using NHibernate.Util;
  using System.Linq;
  
  namespace NHibernate.Stat
  {
  	public class StatisticsImpl : IStatistics, IStatisticsImplementor
  	{
  		private object _syncRoot;
  
  		private static readonly INHibernateLogger log = NHibernateLogger.For(typeof(StatisticsImpl));
  		private readonly ISessionFactoryImplementor sessionFactory;
  		private long entityDeleteCount;
  		private long entityInsertCount;
  		private long entityLoadCount;
  		private long entityFetchCount;
  		private long entityUpdateCount;
  		// log operations that take longer than this value
  		private TimeSpan operationThreshold = TimeSpan.MaxValue; 
  		private long queryExecutionCount;
  		private TimeSpan queryExecutionMaxTime;
  		private string queryExecutionMaxTimeQueryString;
  		private long queryCacheHitCount;
  		private long queryCacheMissCount;
  		private long queryCachePutCount;
  		private long flushCount;
  		private long connectCount;
  		private long secondLevelCacheHitCount;
  		private long secondLevelCacheMissCount;
  		private long secondLevelCachePutCount;
  		private long sessionCloseCount;
  		private long sessionOpenCount;
  		private long collectionLoadCount;
  		private long collectionFetchCount;
  		private long collectionUpdateCount;
  		private long collectionRemoveCount;
  		private long collectionRecreateCount;
  		private DateTime startTime;
  		private long commitedTransactionCount;
  		private long transactionCount;
  		private long prepareStatementCount;
  		private long closeStatementCount;
  		private long optimisticFailureCount;
  		// second level cache statistics per region 
  		private readonly Dictionary<string, SecondLevelCacheStatistics> secondLevelCacheStatistics = new Dictionary<string, SecondLevelCacheStatistics>();
  		// entity statistics per name 
  		private readonly Dictionary<string, EntityStatistics> entityStatistics = new Dictionary<string, EntityStatistics>();
  		// collection statistics per name 
  		private readonly Dictionary<string, CollectionStatistics> collectionStatistics = new Dictionary<string, CollectionStatistics>();
  		// entity statistics per query string (HQL or SQL) 
  		private readonly Dictionary<string, QueryStatistics> queryStatistics = new Dictionary<string, QueryStatistics>();
  
  		internal const string OperationLoad = "load ";
  		internal const string OperationFetch = "fetch ";
  		internal const string OperationUpdate = "update ";
  		internal const string OperationInsert = "insert ";
  		internal const string OperationDelete = "delete ";
  		internal const string OperationLoadCollection = "loadCollection ";
  		internal const string OperationFetchCollection = "fetchCollection ";
  		internal const string OperationUpdateCollection = "updateCollection ";
  		internal const string OperationRecreateCollection = "recreateCollection ";
  		internal const string OperationRemoveCollection = "removeCollection ";
  		internal const string OperationExecuteQuery = "executeQuery ";
  		internal const string OperationEndTransaction = "endTransaction ";
  
  		public StatisticsImpl()
  		{
  			Clear();
  		}
  
  		public StatisticsImpl(ISessionFactoryImplementor sessionFactory)
  			: this()
  		{
  			this.sessionFactory = sessionFactory;
  		}
  
  		private object SyncRoot
  		{
  			get
  			{
  				if (_syncRoot == null)
  					Interlocked.CompareExchange(ref _syncRoot, new object(), null);
  
  				return _syncRoot;
  			}
  		}
  
  		#region IStatistics Members
  
  		public long EntityDeleteCount
  		{
  			get { return entityDeleteCount; }
  		}
  
  		public long EntityInsertCount
  		{
  			get { return entityInsertCount; }
  		}
  
  		public long EntityLoadCount
  		{
  			get { return entityLoadCount; }
  		}
  
  		public long EntityFetchCount
  		{
  			get { return entityFetchCount; }
  		}
  
  		public long EntityUpdateCount
  		{
  			get { return entityUpdateCount; }
  		}
  
  		public long QueryExecutionCount
  		{
  			get { return queryExecutionCount; }
  		}
  
  		public TimeSpan QueryExecutionMaxTime
  		{
  			get { return queryExecutionMaxTime; }
  		}
  
  		public string QueryExecutionMaxTimeQueryString
  		{
  			get { return queryExecutionMaxTimeQueryString; }
  		}
  
  		public long QueryCacheHitCount
  		{
  			get { return queryCacheHitCount; }
  		}
  
  		public long QueryCacheMissCount
  		{
  			get { return queryCacheMissCount; }
  		}
  
  		public long QueryCachePutCount
  		{
  			get { return queryCachePutCount; }
  		}
  
  		public long FlushCount
  		{
  			get { return flushCount; }
  		}
  
  		public long ConnectCount
  		{
  			get { return connectCount; }
  		}
  
  		public long SecondLevelCacheHitCount
  		{
  			get { return secondLevelCacheHitCount; }
  		}
  
  		public long SecondLevelCacheMissCount
  		{
  			get { return secondLevelCacheMissCount; }
  		}
  
  		public long SecondLevelCachePutCount
  		{
  			get { return secondLevelCachePutCount; }
  		}
  
  		public long SessionCloseCount
  		{
  			get { return sessionCloseCount; }
  		}
  
  		public long SessionOpenCount
  		{
  			get { return sessionOpenCount; }
  		}
  
  		public long CollectionLoadCount
  		{
  			get { return collectionLoadCount; }
  		}
  
  		public long CollectionFetchCount
  		{
  			get { return collectionFetchCount; }
  		}
  
  		public long CollectionUpdateCount
  		{
  			get { return collectionUpdateCount; }
  		}
  
  		public long CollectionRemoveCount
  		{
  			get { return collectionRemoveCount; }
  		}
  
  		public long CollectionRecreateCount
  		{
  			get { return collectionRecreateCount; }
  		}
  
  		public DateTime StartTime
  		{
  			get { return startTime; }
  		}
  
  		public bool IsStatisticsEnabled { get; set; }
  
  		public string[] Queries
  		{
  			get
  			{
  				var result = new string[queryStatistics.Keys.Count];
  				queryStatistics.Keys.CopyTo(result,0);
  				return result;
  			}
  		}
  
  		public string[] EntityNames
  		{
  			get
  			{
  				if (sessionFactory == null)
  				{
  					var result = new string[entityStatistics.Keys.Count];
  					entityStatistics.Keys.CopyTo(result, 0);
  					return result;
  				}
  				else
  				{
  					return sessionFactory.GetAllClassMetadata().Keys.ToArray();
  				}
  			}
  		}
  
  		public string[] CollectionRoleNames
  		{
  			get
  			{
  				if (sessionFactory == null)
  				{
  					var result = new string[collectionStatistics.Keys.Count];
  					collectionStatistics.Keys.CopyTo(result, 0);
  					return result;
  				}
  				else
  				{
  					ICollection<string> kc = sessionFactory.GetAllCollectionMetadata().Keys;
  
gt: 					var result = new string[kc.Count];