Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Common / QueryCache / QueryCacheManager.cs / 1305376 / QueryCacheManager.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //----------------------------------------------------------------------------- namespace System.Data.Common.QueryCache { using System; using System.Collections.Generic; using System.Data.EntityClient; using System.Data.Metadata.Edm; using System.Data.Objects.Internal; using System.Diagnostics; using System.Threading; using System.Data.Common.Internal.Materialization; ////// Provides Query Execution Plan Caching Service /// ////// Thread safe. /// Dispose must be called as there is no finalizer for this class /// internal class QueryCacheManager : IDisposable { #region Constants/Default values for configuration parameters ////// Default Soft maximum number of entries in the cache /// Default value: 1000 /// const int DefaultMaxNumberOfEntries = 1000; ////// Default high mark for starting sweeping process /// default value: 80% of MaxNumberOfEntries /// const float DefaultHighMarkPercentageFactor = 0.8f; // 80% of MaxLimit ////// Recycler timer period /// const int DefaultRecyclerPeriodInMilliseconds = 60 * 1000; #endregion #region Fields ////// cache lock object /// private readonly object _cacheDataLock = new object(); ////// cache data /// private readonly Dictionary_cacheData = new Dictionary (32); /// /// soft maximum number of entries in the cache /// private readonly int _maxNumberOfEntries; ////// high mark of the number of entries to trigger the sweeping process /// private readonly int _sweepingTriggerHighMark; ////// Eviction timer /// private readonly EvictionTimer _evictionTimer; #endregion #region Construction and Initialization ////// Constructs a new Query Cache Manager instance, with default values for all 'configurable' parameters. /// ///A new instance of internal static QueryCacheManager Create() { return new QueryCacheManager(DefaultMaxNumberOfEntries, DefaultHighMarkPercentageFactor, DefaultRecyclerPeriodInMilliseconds); } ///configured with default entry count, load factor and recycle period /// Cache Constructor /// /// /// Maximum number of entries that the cache should contain. /// /// /// The number of entries that must be present, as a percentage, before entries should be removed /// according to the eviction policy. /// Must be greater than 0 and less than or equal to 1.0 /// /// /// The interval, in milliseconds, at which the number of entries will be compared to the load factor /// and eviction carried out if necessary. /// private QueryCacheManager(int maximumSize, float loadFactor, int recycleMillis) { Debug.Assert(maximumSize > 0, "Maximum size must be greater than zero"); Debug.Assert(loadFactor > 0 && loadFactor <= 1, "Load factor must be greater than 0.0 and less than or equal to 1.0"); Debug.Assert(recycleMillis >= 0, "Recycle period in milliseconds must not be negative"); // // Load hardcoded defaults // this._maxNumberOfEntries = maximumSize; // // set sweeping high mark trigger value // this._sweepingTriggerHighMark = (int)(_maxNumberOfEntries * loadFactor); // // Initialize Recycler // this._evictionTimer = new EvictionTimer(this, recycleMillis); } #endregion #region 'External' interface ////// Adds new entry to the cache using "abstract" cache context and /// value; returns an existing entry if the key is already in the /// dictionary. /// /// /// /// The existing entry in the dicitionary if already there; /// inQueryCacheEntry if none was found and inQueryCacheEntry /// was added instead. /// ///true if the output entry was already found; false if it had to be added. internal bool TryLookupAndAdd(QueryCacheEntry inQueryCacheEntry, out QueryCacheEntry outQueryCacheEntry) { Debug.Assert(null != inQueryCacheEntry, "qEntry must not be null"); outQueryCacheEntry = null; lock (_cacheDataLock) { if (!_cacheData.TryGetValue(inQueryCacheEntry.QueryCacheKey, out outQueryCacheEntry)) { // // add entry to cache data // _cacheData.Add(inQueryCacheEntry.QueryCacheKey, inQueryCacheEntry); if (_cacheData.Count > _sweepingTriggerHighMark) { _evictionTimer.Start(); } return false; } else { outQueryCacheEntry.QueryCacheKey.UpdateHit(); return true; } } } ////// Lookup service for EntityClient cache key /// /// /// ///internal bool TryCacheLookup(EntityClientCacheKey entityClientCacheKey, out EntityCommandDefinition entityCommandDefinition) { Debug.Assert(null != entityClientCacheKey, "entityClientCacheKey must not be null"); entityCommandDefinition = null; QueryCacheEntry qEntry = null; // // invoke internal lookup // bool bHit = TryInternalCacheLookup(entityClientCacheKey, out qEntry); // // if it is a hit, 'extract' the entry strong type cache value // if (bHit) { entityCommandDefinition = ((EntityClientCacheEntry)qEntry).GetTarget(); } return bHit; } /// /// Lookup service for ShaperFactoryQueryCacheKey /// ////// /// /// internal bool TryCacheLookup (ShaperFactoryQueryCacheKey key, out ShaperFactory factory) { Debug.Assert(null != key, "key null"); QueryCacheEntry cacheEntry; if (TryInternalCacheLookup(key, out cacheEntry)) { factory = (ShaperFactory )cacheEntry.GetTarget(); return true; } factory = null; return false; } /// /// Lookup service for Entity-SQL ObjectQuery cache key /// /// /// /// /// ///internal bool TryCacheLookup(EntitySqlQueryCacheKey objectQueryCacheKey, out ObjectQueryExecutionPlan execPlan) { Debug.Assert(null != objectQueryCacheKey, "objectQueryCacheKey must not be null"); execPlan = null; QueryCacheEntry qEntry = null; // // invoke internal lookup // bool bHit = TryInternalCacheLookup(objectQueryCacheKey, out qEntry); // // if it is a hit, 'extract' the entry strong type cache value // if (bHit) { execPlan = ((EntitySqlQueryCacheEntry)qEntry).ExecutionPlan; } return bHit; } /// /// Lookup service for CompiledQuery cache key /// /// /// /// /// ///internal bool TryCacheLookup(CompiledQueryCacheKey objectQueryCacheKey, out CompiledQueryCacheEntry cacheEntry) { Debug.Assert(null != objectQueryCacheKey, "objectQueryCacheKey must not be null"); cacheEntry = null; QueryCacheEntry qEntry = null; // // invoke internal lookup // bool bHit = TryInternalCacheLookup(objectQueryCacheKey, out qEntry); // // if it is a hit, 'extract' the entry strong type cache value // if (bHit) { cacheEntry = (CompiledQueryCacheEntry)qEntry; } return bHit; } /// /// Clears the Cache /// internal void Clear() { lock (_cacheDataLock) { _cacheData.Clear(); } } #endregion #region Private Members ////// lookup service /// /// /// ///true if cache hit, false if cache miss private bool TryInternalCacheLookup( QueryCacheKey queryCacheKey, out QueryCacheEntry queryCacheEntry ) { Debug.Assert(null != queryCacheKey, "queryCacheKey must not be null"); queryCacheEntry = null; bool bHit = false; // // lock the cache for the minimal possible period // lock (_cacheDataLock) { bHit = _cacheData.TryGetValue(queryCacheKey, out queryCacheEntry); } // // if cache hit // if (bHit) { // // update hit mark in cache key // queryCacheEntry.QueryCacheKey.UpdateHit(); } return bHit; } ////// Recycler handler. This method is called directly by the eviction timer. /// It should take no action beyond invoking the /// The cache manager instance on which the 'recycle' handler should be invoked private static void CacheRecyclerHandler(object state) { ((QueryCacheManager)state).SweepCache(); } ///method on the /// cache manager instance passed as . /// /// Aging factor /// private static readonly int[] _agingFactor = {1,1,2,4,8,16}; private static readonly int AgingMaxIndex = _agingFactor.Length - 1; ////// Sweeps the cache removing old unused entries. /// This method implements the query cache eviction policy. /// private void SweepCache() { if (!this._evictionTimer.Suspend()) { // Return of false from .Suspend means that the manager and timer have been disposed. return; } bool disabledEviction = false; lock (_cacheDataLock) { // // recycle only if entries exceeds the high mark factor // if (_cacheData.Count > _sweepingTriggerHighMark) { // // sweep the cache // uint evictedEntriesCount = 0; ListcacheKeys = new List (_cacheData.Count); cacheKeys.AddRange(_cacheData.Keys); for (int i = 0; i < cacheKeys.Count; i++) { // // if entry was not used in the last time window, then evict the entry // if (0 == cacheKeys[i].HitCount) { _cacheData.Remove(cacheKeys[i]); evictedEntriesCount++; } // // otherwise, age the entry in a progressive scheme // else { int agingIndex = unchecked(cacheKeys[i].AgingIndex + 1); if (agingIndex > AgingMaxIndex) { agingIndex = AgingMaxIndex; } cacheKeys[i].AgingIndex = agingIndex; cacheKeys[i].HitCount = cacheKeys[i].HitCount >> _agingFactor[agingIndex]; } } } else { _evictionTimer.Stop(); disabledEviction = true; } } if (!disabledEviction) { this._evictionTimer.Resume(); } } #endregion #region IDisposable Members /// /// Dispose instance /// ///Dispose must be called as there are no finalizers for this class public void Dispose() { // Technically, calling GC.SuppressFinalize is not required because the class does not // have a finalizer, but it does no harm, protects against the case where a finalizer is added // in the future, and prevents an FxCop warning. GC.SuppressFinalize(this); if (this._evictionTimer.Stop()) { this.Clear(); } } #endregion ////// Periodically invokes cache cleanup logic on a specified private sealed class EvictionTimer { ///instance, /// and allows this periodic callback to be suspended, resumed or stopped in a thread-safe way. /// Used to control multi-threaded accesses to this instance private readonly object _[....] = new object(); ///The required interval between invocations of the cache cleanup logic private readonly int _period; ///The underlying QueryCacheManger that the callback will act on private readonly QueryCacheManager _cacheManager; ///The underlying private Timer _timer; internal EvictionTimer(QueryCacheManager cacheManager, int recyclePeriod) { this._cacheManager = cacheManager; this._period = recyclePeriod; } internal void Start() { lock (_[....]) { if (_timer == null) { this._timer = new Timer(QueryCacheManager.CacheRecyclerHandler, _cacheManager, _period, _period); } } } ///that implements the periodic callback /// Permanently stops the eviction timer. /// It will no longer generate periodic callbacks and further calls to ///, , or , /// though thread-safe, will have no effect. /// /// If this eviction timer has already been stopped (using the ///method), returns false ; /// otherwise, returnstrue to indicate that the call successfully stopped and cleaned up the underlying timer instance. ////// Thread safe. May be called regardless of the current state of the eviction timer. /// Once stopped, an eviction timer cannot be restarted with the internal bool Stop() { lock (_[....]) { if (this._timer != null) { this._timer.Dispose(); this._timer = null; return true; } else { return false; } } } ///method. /// /// Pauses the operation of the eviction timer. /// ////// If this eviction timer has already been stopped (using the ///method), returns false ; /// otherwise, returnstrue to indicate that the call successfully suspended the inderlying/// and no further periodic callbacks will be generated until the method is called. /// /// Thread-safe. May be called regardless of the current state of the eviction timer. /// Once suspended, an eviction timer may be resumed or stopped. /// internal bool Suspend() { lock (_[....]) { if (this._timer != null) { this._timer.Change(Timeout.Infinite, Timeout.Infinite); return true; } else { return false; } } } ////// Causes this eviction timer to generate periodic callbacks, provided it has not been permanently stopped (using the ///method). /// /// Thread-safe. May be called regardless of the current state of the eviction timer. /// internal void Resume() { lock (_[....]) { if (this._timer != null) { this._timer.Change(this._period, this._period); } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ParentQuery.cs
- SerialReceived.cs
- LinqDataSourceDisposeEventArgs.cs
- Int16AnimationUsingKeyFrames.cs
- baseshape.cs
- DataGridBoundColumn.cs
- Parameter.cs
- AnnotationAuthorChangedEventArgs.cs
- SqlTransaction.cs
- MissingSatelliteAssemblyException.cs
- ReverseInheritProperty.cs
- SspiWrapper.cs
- ServerValidateEventArgs.cs
- Rect3DValueSerializer.cs
- ToolboxItem.cs
- BaseDataList.cs
- FixedSOMImage.cs
- PhysicalOps.cs
- TextTrailingWordEllipsis.cs
- VersionPair.cs
- TextSelection.cs
- WorkflowOperationInvoker.cs
- AdRotator.cs
- ClassGenerator.cs
- XmlSchemaSearchPattern.cs
- DataGridViewCellStyleContentChangedEventArgs.cs
- DATA_BLOB.cs
- SinglePageViewer.cs
- CompositeControlDesigner.cs
- AppDomainAttributes.cs
- ExpressionEditorAttribute.cs
- ColumnTypeConverter.cs
- XmlElementAttribute.cs
- SyndicationDeserializer.cs
- EventListener.cs
- ParseHttpDate.cs
- CursorConverter.cs
- HttpHandlerAction.cs
- DotExpr.cs
- WmlPanelAdapter.cs
- ModelItemExtensions.cs
- RegisteredExpandoAttribute.cs
- ScriptResourceAttribute.cs
- ResourceManager.cs
- FlowDecisionDesigner.xaml.cs
- InputBindingCollection.cs
- DPAPIProtectedConfigurationProvider.cs
- TableItemProviderWrapper.cs
- TextTreeNode.cs
- UserControlAutomationPeer.cs
- TraceEventCache.cs
- NavigateEvent.cs
- AbsoluteQuery.cs
- ComponentCommands.cs
- _SafeNetHandles.cs
- InvalidTimeZoneException.cs
- ViewGenerator.cs
- TextRange.cs
- CDSCollectionETWBCLProvider.cs
- ExecutedRoutedEventArgs.cs
- ElementNotEnabledException.cs
- WpfKnownType.cs
- BooleanConverter.cs
- PropertyContainer.cs
- ApplicationContext.cs
- UInt32Storage.cs
- SqlClientWrapperSmiStreamChars.cs
- CaseInsensitiveOrdinalStringComparer.cs
- SingleAnimationUsingKeyFrames.cs
- RSAOAEPKeyExchangeDeformatter.cs
- AppModelKnownContentFactory.cs
- UnmanagedMemoryStreamWrapper.cs
- RequestSecurityTokenForRemoteTokenFactory.cs
- ClickablePoint.cs
- DBCSCodePageEncoding.cs
- MetadataItemSerializer.cs
- RSAOAEPKeyExchangeFormatter.cs
- NavigationProperty.cs
- SamlEvidence.cs
- MenuCommand.cs
- adornercollection.cs
- GeneralTransform3DGroup.cs
- DataGridPagerStyle.cs
- HtmlInputImage.cs
- EventRoute.cs
- NetDataContractSerializer.cs
- FontDialog.cs
- HyperLinkDataBindingHandler.cs
- HttpServerVarsCollection.cs
- DocumentScope.cs
- XmlMembersMapping.cs
- WindowsIdentity.cs
- XmlSchemaAttributeGroupRef.cs
- XmlUtil.cs
- SolidColorBrush.cs
- WebPartEditorCancelVerb.cs
- ObjectSet.cs
- AdRotatorDesigner.cs
- ForceCopyBuildProvider.cs
- ReadContentAsBinaryHelper.cs