/// <summary> /// Reads all items from the database and stores in local cache /// </summary> private static void EnsureCache() { using (var lck = new UpgradeableReadLock(Locker)) { if (_cacheIsEnsured) return; lck.UpgradeToWriteLock(); using (var dr = SqlHelper.ExecuteReader("Select pk, id, [key], parent from cmsDictionary")) { while (dr.Read()) { //create new dictionaryitem object and put in cache var item = new DictionaryItem(dr.GetInt("pk"), dr.GetString("key"), dr.GetGuid("id"), dr.GetGuid("parent")); DictionaryItems.TryAdd(item.key, item); } } _cacheIsEnsured = true; } }
static void UmbracoModuleRouteAttempt(object sender, Routing.RoutableAttemptEventArgs e) { if (e.HttpContext.Request == null || e.HttpContext.Request.Url == null) return; if (e.Outcome == EnsureRoutableOutcome.IsRoutable) { using (var lck = new UpgradeableReadLock(Locker)) { //we only want to do the initial update once if (!_initUpdated) { lck.UpgradeToWriteLock(); _initUpdated = true; UpdateServerEntry(e.HttpContext, e.UmbracoContext.Application); return; } } } //if it is not a document request, we'll check if it is a back end request if (e.Outcome == EnsureRoutableOutcome.NotDocumentRequest) { //check if this is in the umbraco back office if (e.HttpContext.Request.Url.IsBackOfficeRequest()) { //yup it's a back office request! using (var lck = new UpgradeableReadLock(Locker)) { //we don't want to update if it's not been at least a minute since last time var isItAMinute = DateTime.Now.Subtract(_lastUpdated).TotalSeconds >= 60; if (isItAMinute) { lck.UpgradeToWriteLock(); _initUpdated = true; _lastUpdated = DateTime.Now; UpdateServerEntry(e.HttpContext, e.UmbracoContext.Application); } } } } }
/// <summary> /// Return a list of found local Assemblies excluding the known assemblies we don't want to scan /// and exluding the ones passed in and excluding the exclusion list filter, the results of this are /// cached for perforance reasons. /// </summary> /// <param name="excludeFromResults"></param> /// <returns></returns> internal static HashSet <Assembly> GetAssembliesWithKnownExclusions( IEnumerable <Assembly> excludeFromResults = null) { using (var lck = new UpgradeableReadLock(LocalFilteredAssemblyCacheLocker)) { if (LocalFilteredAssemblyCache.Any()) { return(LocalFilteredAssemblyCache); } lck.UpgradeToWriteLock(); var assemblies = GetFilteredAssemblies(excludeFromResults, KnownAssemblyExclusionFilter); foreach (var a in assemblies) { LocalFilteredAssemblyCache.Add(a); } return(LocalFilteredAssemblyCache); } }
private IEnumerable <Type> ResolveTypes <T>( Func <IEnumerable <Type> > finder, TypeResolutionKind resolutionType, bool cacheResult) { using (var readLock = new UpgradeableReadLock(_lock)) { using (DisposableTimer.TraceDuration <PluginManager>( String.Format("Starting resolution types of {0}", typeof(T).FullName), String.Format("Completed resolution of types of {0}", typeof(T).FullName))) { //check if the TypeList already exists, if so return it, if not we'll create it var typeList = _types.SingleOrDefault(x => x.IsTypeList <T>(resolutionType)); //if we're not caching the result then proceed, or if the type list doesn't exist then proceed if (!cacheResult || typeList == null) { //upgrade to a write lock since we're adding to the collection readLock.UpgradeToWriteLock(); typeList = new TypeList <T>(resolutionType); foreach (var t in finder()) { typeList.AddType(t); } //only add the cache if we are to cache the results if (cacheResult) { //add the type list to the collection _types.Add(typeList); } } return(typeList.GetTypes()); } } }
private IEnumerable <Type> ResolveTypes <T>( Func <IEnumerable <Type> > finder, TypeResolutionKind resolutionType, bool cacheResult) { using (var readLock = new UpgradeableReadLock(Locker)) { var typesFound = new List <Type>(); using (_logger.TraceDuration <PluginManager>( String.Format("Starting resolution types of {0}", typeof(T).FullName), String.Format("Completed resolution of types of {0}, found {1}", typeof(T).FullName, typesFound.Count))) { //check if the TypeList already exists, if so return it, if not we'll create it var typeList = _types.SingleOrDefault(x => x.IsTypeList <T>(resolutionType)); //need to put some logging here to try to figure out why this is happening: http://issues.umbraco.org/issue/U4-3505 if (cacheResult && typeList != null) { _logger.Logger.Debug <PluginManager>("Existing typeList found for {0} with resolution type {1}", () => typeof(T), () => resolutionType); } //if we're not caching the result then proceed, or if the type list doesn't exist then proceed if (cacheResult == false || typeList == null) { //upgrade to a write lock since we're adding to the collection readLock.UpgradeToWriteLock(); typeList = new TypeList <T>(resolutionType); //we first need to look into our cache file (this has nothing to do with the 'cacheResult' parameter which caches in memory). //if assemblies have not changed and the cache file actually exists, then proceed to try to lookup by the cache file. if (RequiresRescanning == false && File.Exists(GetPluginListFilePath())) { var fileCacheResult = TryGetCachedPluginsFromFile <T>(resolutionType); //here we need to identify if the CachedPluginNotFoundInFile was the exception, if it was then we need to re-scan //in some cases the plugin will not have been scanned for on application startup, but the assemblies haven't changed //so in this instance there will never be a result. if (fileCacheResult.Exception != null && fileCacheResult.Exception is CachedPluginNotFoundInFileException) { _logger.Logger.Debug <PluginManager>("Tried to find typelist for type {0} and resolution {1} in file cache but the type was not found so loading types by assembly scan ", () => typeof(T), () => resolutionType); //we don't have a cache for this so proceed to look them up by scanning LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder); } else { if (fileCacheResult.Success) { var successfullyLoadedFromCache = true; //we have a previous cache for this so we don't need to scan we just load what has been found in the file foreach (var t in fileCacheResult.Result) { try { //we use the build manager to ensure we get all types loaded, this is slightly slower than //Type.GetType but if the types in the assembly aren't loaded yet then we have problems with that. var type = BuildManager.GetType(t, true); typeList.AddType(type); } catch (Exception ex) { //if there are any exceptions loading types, we have to exist, this should never happen so //we will need to revert to scanning for types. successfullyLoadedFromCache = false; _logger.Logger.Error <PluginManager>("Could not load a cached plugin type: " + t + " now reverting to re-scanning assemblies for the base type: " + typeof(T).FullName, ex); break; } } if (successfullyLoadedFromCache == false) { //we need to manually load by scanning if loading from the file was not successful. LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder); } else { _logger.Logger.Debug <PluginManager>("Loaded plugin types {0} with resolution {1} from persisted cache", () => typeof(T), () => resolutionType); } } } } else { _logger.Logger.Debug <PluginManager>("Assembly changes detected, loading types {0} for resolution {1} by assembly scan", () => typeof(T), () => resolutionType); //we don't have a cache for this so proceed to look them up by scanning LoadViaScanningAndUpdateCacheFile <T>(typeList, resolutionType, finder); } //only add the cache if we are to cache the results if (cacheResult) { //add the type list to the collection var added = _types.Add(typeList); _logger.Logger.Debug <PluginManager>("Caching of typelist for type {0} and resolution {1} was successful = {2}", () => typeof(T), () => resolutionType, () => added); } } typesFound = typeList.GetTypes().ToList(); } return(typesFound); } }
/// <summary> /// lazily load a reference to all assemblies and only local assemblies. /// This is a modified version of: http://www.dominicpettifer.co.uk/Blog/44/how-to-get-a-reference-to-all-assemblies-in-the--bin-folder /// </summary> /// <remarks> /// We do this because we cannot use AppDomain.Current.GetAssemblies() as this will return only assemblies that have been /// loaded in the CLR, not all assemblies. /// See these threads: /// http://issues.umbraco.org/issue/U5-198 /// http://stackoverflow.com/questions/3552223/asp-net-appdomain-currentdomain-getassemblies-assemblies-missing-after-app /// http://stackoverflow.com/questions/2477787/difference-between-appdomain-getassemblies-and-buildmanager-getreferencedassembl /// </remarks> internal static HashSet <Assembly> GetAllAssemblies() { using (var lck = new UpgradeableReadLock(Locker)) { if (_allAssemblies == null) { lck.UpgradeToWriteLock(); HashSet <Assembly> assemblies = null; try { var isHosted = HttpContext.Current != null; try { if (isHosted) { assemblies = new HashSet <Assembly>(BuildManager.GetReferencedAssemblies().Cast <Assembly>()); } } catch (InvalidOperationException e) { if (!(e.InnerException is SecurityException)) { throw; } } if (assemblies == null) { //NOTE: we cannot use AppDomain.CurrentDomain.GetAssemblies() because this only returns assemblies that have // already been loaded in to the app domain, instead we will look directly into the bin folder and load each one. var binFolder = IOHelper.GetRootDirectoryBinFolder(); var binAssemblyFiles = Directory.GetFiles(binFolder, "*.dll", SearchOption.TopDirectoryOnly).ToList(); //var binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory; //var binAssemblyFiles = Directory.GetFiles(binFolder.FullName, "*.dll", SearchOption.TopDirectoryOnly).ToList(); assemblies = new HashSet <Assembly>(); foreach (var a in binAssemblyFiles) { try { var assName = AssemblyName.GetAssemblyName(a); var ass = Assembly.Load(assName); assemblies.Add(ass); } catch (Exception e) { if (e is SecurityException || e is BadImageFormatException) { //swallow these exceptions } else { throw; } } } } //if for some reason they are still no assemblies, then use the AppDomain to load in already loaded assemblies. if (!assemblies.Any()) { foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) { assemblies.Add(a); } } //here we are trying to get the App_Code assembly var fileExtensions = new[] { ".cs", ".vb" }; //only vb and cs files are supported var appCodeFolder = new DirectoryInfo(IOHelper.MapPath(IOHelper.ResolveUrl("~/App_code"))); //check if the folder exists and if there are any files in it with the supported file extensions if (appCodeFolder.Exists && (fileExtensions.Any(x => appCodeFolder.GetFiles("*" + x).Any()))) { var appCodeAssembly = Assembly.Load("App_Code"); if (!assemblies.Contains(appCodeAssembly)) // BuildManager will find App_Code already { assemblies.Add(appCodeAssembly); } } //now set the _allAssemblies _allAssemblies = new HashSet <Assembly>(assemblies); } catch (InvalidOperationException e) { if (!(e.InnerException is SecurityException)) { throw; } _binFolderAssemblies = _allAssemblies; } } return(_allAssemblies); } }