예제 #1
0
 public CompatibilityProfileCacheEntry(
     CompatibilityProfileDataMut mutableProfileData,
     CompatibilityProfileData profile)
 {
     MutableProfileData = mutableProfileData;
     Profile            = profile;
 }
예제 #2
0
        private Task <CompatibilityProfileCacheEntry> GetUnionProfile(DirectoryInfo profileDir)
        {
            IEnumerable <string> profilePaths = profileDir.EnumerateFiles("*.json")
                                                .Where(file => file.Name.IndexOf("union", StringComparison.OrdinalIgnoreCase) < 0) // Filter out union files
                                                .Select(file => file.FullName);

            IEnumerable <CompatibilityProfileCacheEntry> profiles = GetProfilesFromPaths(profilePaths).Result;

            string unionId   = GetUnionIdFromProfiles(profiles);
            string unionPath = Path.Combine(profileDir.FullName, unionId + ".json");

            return(_profileCache.GetOrAdd(unionPath, new Lazy <Task <CompatibilityProfileCacheEntry> >(() => Task.Run(() => {
                try
                {
                    // We read the ID first to avoid needing to rehydrate MBs of unneeded JSON
                    if (JsonProfileSerializer.ReadIdFromProfileFile(unionPath) == unionId)
                    {
                        CompatibilityProfileDataMut loadedUnionProfile = _jsonSerializer.DeserializeFromFile(unionPath);

                        // This is unlikely, but the ID has limited entropy
                        if (UnionMatchesProfiles(loadedUnionProfile, profiles))
                        {
                            return new CompatibilityProfileCacheEntry(
                                loadedUnionProfile,
                                new CompatibilityProfileData(loadedUnionProfile));
                        }
                    }

                    // We found the union file, but it didn't match for some reason
                    File.Delete(unionPath);
                }
                catch (Exception)
                {
                    // Do nothing, we will now generate the profile
                }

                // Loading the union file failed, so we are forced to generate it
                CompatibilityProfileDataMut generatedUnionProfile = ProfileCombination.UnionMany(unionId, profiles.Select(p => p.MutableProfileData));

                // Write the union to the filesystem for faster startup later
                Task.Run(() => {
                    _jsonSerializer.SerializeToFile(generatedUnionProfile, unionPath);
                });

                return new CompatibilityProfileCacheEntry(
                    generatedUnionProfile,
                    new CompatibilityProfileData(generatedUnionProfile));
            }))).Value);
        }
예제 #3
0
        /// <summary>
        /// Load a profile from a path.
        /// Caches profiles based on path, so that repeated calls do not require JSON deserialization.
        /// </summary>
        /// <param name="path">The path to load a profile from.</param>
        /// <returns>A query object around the loaded profile.</returns>
        private Lazy <Task <CompatibilityProfileCacheEntry> > GetProfileFromPath(string path)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            return(_profileCache.GetOrAdd(path, new Lazy <Task <CompatibilityProfileCacheEntry> >(() => Task.Run(() => {
                CompatibilityProfileDataMut compatibilityProfileMut = _jsonSerializer.DeserializeFromFile(path);

                var compatibilityProfile = new CompatibilityProfileData(compatibilityProfileMut);

                return new CompatibilityProfileCacheEntry(
                    compatibilityProfileMut,
                    compatibilityProfile);
            }))));
        }
예제 #4
0
        private static bool UnionMatchesProfiles(
            CompatibilityProfileDataMut unionProfile,
            IEnumerable <CompatibilityProfileCacheEntry> profiles)
        {
            var idsToSee = new HashSet <string>(unionProfile.ConstituentProfiles);

            foreach (CompatibilityProfileCacheEntry profile in profiles)
            {
                // Check that every ID is in the list
                if (!idsToSee.Remove(profile.Profile.Id))
                {
                    return(false);
                }
            }

            // Check that there are no other IDs in the profile
            return(idsToSee.Count == 0);
        }
        /// <summary>
        /// Create a query object around a collected compatibility profile.
        /// </summary>
        /// <param name="compatibilityProfileData">The collected compatibility profile data.</param>
        public CompatibilityProfileData(CompatibilityProfileDataMut compatibilityProfileData)
        {
            Runtime = new RuntimeData(compatibilityProfileData.Runtime);

            Id = compatibilityProfileData.Id;

            if (compatibilityProfileData.ConstituentProfiles != null)
            {
                // This is intended to be case-sensitive
                ConstituentProfiles = new HashSet <string>(compatibilityProfileData.ConstituentProfiles);
            }

            // This should only be null in the case of the anyplatform_union profile
            if (compatibilityProfileData.Platform != null)
            {
                Platform = new PlatformData(compatibilityProfileData.Platform);
            }
        }