// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Linq; using System.Web.Caching; namespace Tools.CrashReporter.CrashReportWebSite.Models { /// /// A class to handle caching of database results on the web server. /// public class CachedDataService : IDisposable { private CrashRepository LocalCrashRepository; private BuggRepository BuggRepositoryInstance; private Cache CacheInstance; private const string CacheKeyPrefix = "_CachedDataService_"; private const string CallstackKeyPrefix = "_CallStack_"; private const string FunctionCallKeyPrefix = "_FunctionCallStack_"; private const string UserNameKeyPrefix = "_UserName_"; /// /// Link the Http context cache to a crash repository. /// /// The current Http context cache. /// The repository to associate the cache with. public CachedDataService( Cache InCache, CrashRepository InCrashRepository ) { CacheInstance = InCache; LocalCrashRepository = InCrashRepository; } /// /// Link the Http context cache to a Bugg repository. /// /// The current Http context cache. /// The repository to associate the cache with. public CachedDataService( Cache InCache, BuggRepository InBuggRepository ) { CacheInstance = InCache; BuggRepositoryInstance = InBuggRepository; } /// /// Implementing Dispose. /// public void Dispose() { Dispose( true ); GC.SuppressFinalize( this ); } /// /// Disposes the resources. /// /// true if the Dispose call is from user code, and not system code. protected virtual void Dispose( bool Disposing ) { LocalCrashRepository.Dispose(); BuggRepositoryInstance.Dispose(); } /// /// Retrieve a cached (and pre-parsed) callstack container from the cache, or parse the raw callstack, and add to the cache. /// /// The crash to retrieve the parsed callstack for. /// A parsed callstack. public CallStackContainer GetCallStack( Crash CurrentCrash ) { string Key = CacheKeyPrefix + CallstackKeyPrefix + CurrentCrash.Id; CallStackContainer CallStack = ( CallStackContainer )CacheInstance[Key]; if( CallStack == null ) { CallStack = new CallStackContainer( CurrentCrash ); CallStack.bDisplayFunctionNames = true; CacheInstance.Insert( Key, CallStack ); } return CallStack; } /// /// Retrieve a list of crashes from the cache, or retrieve a list from the database, and add to the cache. /// /// The date of the earliest crash to consider. /// The date of the most recent crash to consider. /// A list of crashes between the start and end dates. public List GetCrashes( DateTime DateFrom, DateTime DateTo ) { string Key = CacheKeyPrefix + DateFrom + DateTo; List Data = ( List )CacheInstance[Key]; if( Data == null ) { IQueryable DataQuery = LocalCrashRepository.ListAll(); DataQuery = LocalCrashRepository.FilterByDate( DataQuery, DateFrom, DateTo ); Data = DataQuery.ToList(); CacheInstance.Insert( Key, Data ); } return Data; } /// /// Retrieve a list of function call names from an encoded pattern. This is either from the cache, or from the database and then added to the cache. /// /// A callstack pattern in the form '1+3+34+2'. /// A list of function names. public List GetFunctionCalls( string Pattern ) { string Key = CacheKeyPrefix + FunctionCallKeyPrefix + Pattern; List FunctionCalls = ( List )CacheInstance[Key]; if( FunctionCalls == null ) { string[] Ids = Pattern.Split( "+".ToCharArray() ); List IdList = new List(); foreach( string id in Ids ) { int i; if( int.TryParse( id, out i ) ) { IdList.Add( i ); } } FunctionCalls = BuggRepositoryInstance.GetFunctionCalls( IdList ); CacheInstance.Insert( Key, FunctionCalls ); } return FunctionCalls; } } }