Beispiel #1
0
        /// <summary>
        /// Start monitoring the resources.
        /// </summary>
        /// <param name="resourcesToMonitor">The resources to be monitored.</param>
        /// <param name="callbackAction">Handler to call when any of the resources is uptdated</param>
        /// <returns><c>true</c> if the operation succeeded; <c>false</c> otherwise.</returns>
        public bool TryStartMonitoring(IEnumerable <IResource> resourcesToMonitor, ResourceUpdatedHandler callbackAction)
        {
            if (!Code.ValidateArgument(resourcesToMonitor, nameof(resourcesToMonitor), TaggingUtilities.ReserveTag(0x238208c9 /* tag_9669j */)) ||
                !Code.ValidateArgument(callbackAction, nameof(callbackAction), TaggingUtilities.ReserveTag(0x238208ca /* tag_9669k */)))
            {
                return(false);
            }

            IList <IResource>      resources      = resourcesToMonitor.ToList();
            ResourceMonitoringData monitoringData = new ResourceMonitoringData(callbackAction, resources);

            if (!TryPerformInitialLoad(resources, monitoringData))
            {
                return(false);
            }

            if (!m_resourceMonitoringData.TryAdd(callbackAction, monitoringData))
            {
                return(false);
            }

            foreach (IResource resource in resources)
            {
                if (!resource.IsStatic)
                {
                    m_monitoredResources.TryAdd(resource, true);
                }
            }

            StartExclusiveAction();

            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Perfroms initial load of the resources which are not yet known to the monitor
        /// </summary>
        /// <param name="resources">A list of resources</param>
        /// <param name="monitoringData">Monitoring data for this initial load</param>
        private bool TryPerformInitialLoad(IEnumerable <IResource> resources, ResourceMonitoringData monitoringData)
        {
            List <IResource> resourcesNotYetSeen = new List <IResource>();

            foreach (IResource resource in resources)
            {
                if (!m_resourceDetails.TryGetValue(resource, out IResourceDetails details))
                {
                    // it is not terrible if we add here a resource that we have actually already loaded
                    // but we would want to reduce the number of such occasions to minimum
                    resourcesNotYetSeen.Add(resource);
                }
            }

            CheckResourcesForUpdates(resourcesNotYetSeen, monitoringData);
            foreach (IResource resource in resourcesNotYetSeen)
            {
                if (!m_resourceDetails.TryGetValue(resource, out IResourceDetails details))
                {
                    return(false);
                }
            }

            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Call all of the handlers who are initerested in any of the updated resources
        /// or just the specified handler if it should be called
        /// </summary>
        /// <param name="updatedResources">Resources that were updated since the last check</param>
        /// <param name="singleMonitoringData">Single handler to be called if not null</param>
        private void NotifyHandlers(HashSet <IResource> updatedResources, ResourceMonitoringData singleMonitoringData)
        {
            ICollection <ResourceMonitoringData> monitoringCollection = m_resourceMonitoringData.Values;

            if (singleMonitoringData != null)
            {
                monitoringCollection = new List <ResourceMonitoringData> {
                    singleMonitoringData
                };
            }

            foreach (ResourceMonitoringData monitoringInstance in monitoringCollection)
            {
                monitoringInstance.CallHandlerIfNecessary(m_resourceDetails, updatedResources);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Check resources for updates
        /// </summary>
        /// <param name="resources">A list of resources to be checked</param>
        /// <param name="singleMonitoringData">Signle instance of ResourceMonitoringData to use if present (use class-wide dict instead)</param>
        private void CheckResourcesForUpdates(IEnumerable <IResource> resources, ResourceMonitoringData singleMonitoringData)
        {
            HashSet <IResource> updatedResources = new HashSet <IResource>();

            foreach (IResource resource in resources)
            {
                IResourceDetails newDetails = GetFileDetails(resource);
                if (newDetails == null)
                {
                    ULSLogging.LogTraceTag(0x238208cc /* tag_9669m */, Categories.ConfigurationDataSet, Levels.Warning, "Failed to load resource details for '{0}'", resource.Name);
                    continue;
                }

                bool updated;
                if (m_resourceDetails.TryGetValue(resource, out IResourceDetails currentDetails) && currentDetails != null)
                {
                    updated = !string.Equals(currentDetails.SHA256Hash, newDetails.SHA256Hash, StringComparison.Ordinal);
                }
                else
                {
                    // it is the first time we load this resource
                    updated = true;
                }

                if (updated)
                {
                    // No explicit synchronization was added here for the following reason:
                    // the worst thing that can happed is two parallel threads consider the same resource
                    // updated and both call the ResourceMonitoringData.CallHandlerIfNecessary
                    // That method on its own ensures in-order execution of handlers
                    m_resourceDetails.AddOrUpdate(resource, newDetails, (res, oldDetails) => newDetails);
                    updatedResources.Add(resource);
                }
            }

            NotifyHandlers(updatedResources, singleMonitoringData);
        }