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
- UrlMappingCollection.cs
- OutOfProcStateClientManager.cs
- TransactionWaitAsyncResult.cs
- ServiceInfoCollection.cs
- ParallelTimeline.cs
- EndpointIdentityConverter.cs
- HttpApplicationFactory.cs
- DataGridViewRowPrePaintEventArgs.cs
- StylusEditingBehavior.cs
- WorkflowTransactionService.cs
- TableLayoutPanelResizeGlyph.cs
- SystemIdentity.cs
- ChooseAction.cs
- PrintControllerWithStatusDialog.cs
- AccessControlList.cs
- MetafileEditor.cs
- TextDecorationCollection.cs
- XmlHierarchyData.cs
- RowUpdatedEventArgs.cs
- TreeNodeClickEventArgs.cs
- MachineKeySection.cs
- AmbientLight.cs
- ModifyActivitiesPropertyDescriptor.cs
- ComponentSerializationService.cs
- MediaContextNotificationWindow.cs
- AppSettingsSection.cs
- SqlUtil.cs
- ImageBrush.cs
- DbProviderFactories.cs
- NestPullup.cs
- IISMapPath.cs
- UrlPath.cs
- EventMappingSettings.cs
- InputLangChangeEvent.cs
- MouseActionValueSerializer.cs
- FrameworkEventSource.cs
- IWorkflowDebuggerService.cs
- StatusStrip.cs
- HttpResponseHeader.cs
- MergePropertyDescriptor.cs
- ApplicationDirectoryMembershipCondition.cs
- ObsoleteAttribute.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- IndicFontClient.cs
- AdRotator.cs
- SqlFactory.cs
- TypedReference.cs
- PropertyChangeTracker.cs
- SQLInt64.cs
- Menu.cs
- CodeTypeReference.cs
- MetadataItemCollectionFactory.cs
- ControlParameter.cs
- WorkflowEnvironment.cs
- OdbcDataAdapter.cs
- EdmComplexTypeAttribute.cs
- SqlCacheDependencyDatabase.cs
- XmlAttributes.cs
- OrderingInfo.cs
- NameObjectCollectionBase.cs
- SapiAttributeParser.cs
- DetailsViewCommandEventArgs.cs
- CancelEventArgs.cs
- Semaphore.cs
- WaitHandleCannotBeOpenedException.cs
- CompositionCommandSet.cs
- ProfilePropertySettingsCollection.cs
- ResXResourceSet.cs
- CollectionCodeDomSerializer.cs
- TerminatorSinks.cs
- Typeface.cs
- PermissionListSet.cs
- contentDescriptor.cs
- AggregatePushdown.cs
- BamlResourceDeserializer.cs
- HttpPostProtocolImporter.cs
- HintTextConverter.cs
- PaperSource.cs
- ConfigurationConverterBase.cs
- VisualStyleTypesAndProperties.cs
- ClassicBorderDecorator.cs
- _BasicClient.cs
- invalidudtexception.cs
- DataService.cs
- JapaneseCalendar.cs
- MemoryRecordBuffer.cs
- SynchronizingStream.cs
- XmlSchemaValidator.cs
- X509SecurityTokenAuthenticator.cs
- NativeRightsManagementAPIsStructures.cs
- Header.cs
- LingerOption.cs
- ReachPrintTicketSerializerAsync.cs
- DiscoveryOperationContextExtension.cs
- VoiceSynthesis.cs
- Variant.cs
- IISUnsafeMethods.cs
- RenderDataDrawingContext.cs
- SmiTypedGetterSetter.cs
- ConfigurationLoaderException.cs