예제 #1
0
        private void AddPackageToCache(ConcurrentDictionary <IPackage, DerivedPackageData> packages, ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> > absoluteLatest, ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> > latest, bool checkFrameworks, HttpContext context, string path, IPackage zip)
        {
            string packageHash       = null;
            long   packageSize       = 0;
            string persistedHashFile = EnablePersistNupkgHash ? GetHashFile(path, false) : null;
            bool   hashComputeNeeded = true;

            ReadHashFile(context, path, persistedHashFile, ref packageSize, ref packageHash, ref hashComputeNeeded);

            if (hashComputeNeeded)
            {
                using (var stream = _fileSystem.OpenFile(path))
                {
                    packageSize = stream.Length;
                    packageHash = Convert.ToBase64String(HashProvider.CalculateHash(stream));
                }
                WriteHashFile(context, path, persistedHashFile, packageSize, packageHash);
            }

            var data = new DerivedPackageData
            {
                PackageSize = packageSize,
                PackageHash = packageHash,
                LastUpdated = _fileSystem.GetLastModified(path),
                Created     = _fileSystem.GetCreated(path),
                Path        = path,
                FullPath    = _fileSystem.GetFullPath(path),

                // default to false, these will be set later
                IsAbsoluteLatestVersion = false,
                IsLatestVersion         = false
            };

            if (checkFrameworks)
            {
                data.SupportedFrameworks = zip.GetSupportedFrameworks();
            }

            var entry = new Tuple <IPackage, DerivedPackageData>(zip, data);

            // find the latest versions
            string id = zip.Id.ToLowerInvariant();

            // update with the highest version
            absoluteLatest.AddOrUpdate(id, entry, (oldId, oldEntry) => oldEntry.Item1.Version < entry.Item1.Version ? entry : oldEntry);

            // update latest for release versions
            if (zip.IsReleaseVersion())
            {
                latest.AddOrUpdate(id, entry, (oldId, oldEntry) => oldEntry.Item1.Version < entry.Item1.Version ? entry : oldEntry);
            }

            // add the package to the cache, it should not exist already
            Debug.Assert(packages.ContainsKey(zip) == false, "duplicate package added");
            packages.AddOrUpdate(zip, entry.Item2, (oldPkg, oldData) => oldData);
        }
        private void CalculateDerivedDataFromStream(LucenePackage package, Func <Stream> openStream)
        {
            using (var stream = openStream())
            {
                if (!stream.CanSeek)
                {
                    throw new InvalidOperationException("Package stream must support CanSeek.");
                }

                package.Created     = FastZipPackageBase.GetPackageCreatedDateTime(stream);
                package.PackageSize = stream.Length;

                stream.Seek(0, SeekOrigin.Begin);
                package.PackageHash = System.Convert.ToBase64String(HashProvider.CalculateHash(stream));
            }
        }
        /// <summary>
        /// CreateCache loads all packages and determines additional metadata such as the hash, IsAbsoluteLatestVersion, and IsLatestVersion.
        /// </summary>
        private IDictionary <IPackage, DerivedPackageData> CreateCache()
        {
            ConcurrentDictionary <IPackage, DerivedPackageData> packages = new ConcurrentDictionary <IPackage, DerivedPackageData>();

            ParallelOptions opts = new ParallelOptions();

            opts.MaxDegreeOfParallelism = 4;

            ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> > absoluteLatest = new ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> >();
            ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> > latest         = new ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> >();

            // get settings
            bool checkFrameworks = EnableFrameworkFiltering;
            bool enableDelisting = EnableDelisting;

            // load and cache all packages
            Parallel.ForEach(GetPackageFiles(), opts, path =>
            {
                OptimizedZipPackage zip = OpenPackage(path);

                Debug.Assert(zip != null, "Unable to open " + path);
                if (zip != null)
                {
                    if (enableDelisting)
                    {
                        // hidden packages are considered delisted
                        zip.Listed = !File.GetAttributes(_fileSystem.GetFullPath(path)).HasFlag(FileAttributes.Hidden);
                    }

                    byte[] hashBytes;
                    long fileLength;
                    using (Stream stream = _fileSystem.OpenFile(path))
                    {
                        fileLength = stream.Length;
                        hashBytes  = HashProvider.CalculateHash(stream);
                    }

                    var data = new DerivedPackageData
                    {
                        PackageSize = fileLength,
                        PackageHash = Convert.ToBase64String(hashBytes),
                        LastUpdated = _fileSystem.GetLastModified(path),
                        Created     = _fileSystem.GetCreated(path),
                        Path        = path,
                        FullPath    = _fileSystem.GetFullPath(path),

                        // default to false, these will be set later
                        IsAbsoluteLatestVersion = false,
                        IsLatestVersion         = false
                    };

                    if (checkFrameworks)
                    {
                        data.SupportedFrameworks = zip.GetSupportedFrameworks();
                    }

                    Tuple <IPackage, DerivedPackageData> entry = new Tuple <IPackage, DerivedPackageData>(zip, data);

                    // find the latest versions
                    string id = zip.Id.ToLowerInvariant();

                    // update with the highest version
                    absoluteLatest.AddOrUpdate(id, entry, (oldId, oldEntry) => oldEntry.Item1.Version < entry.Item1.Version ? entry : oldEntry);

                    // update latest for release versions
                    if (zip.IsReleaseVersion())
                    {
                        latest.AddOrUpdate(id, entry, (oldId, oldEntry) => oldEntry.Item1.Version < entry.Item1.Version ? entry : oldEntry);
                    }

                    // add the package to the cache, it should not exist already
                    Debug.Assert(packages.ContainsKey(zip) == false, "duplicate package added");
                    packages.AddOrUpdate(zip, entry.Item2, (oldPkg, oldData) => oldData);
                }
            });

            // Set additional attributes after visiting all packages
            foreach (var entry in absoluteLatest.Values)
            {
                entry.Item2.IsAbsoluteLatestVersion = true;
            }

            foreach (var entry in latest.Values)
            {
                entry.Item2.IsLatestVersion = true;
            }

            return(packages);
        }
        /// <summary>
        /// CreateCache loads all packages and determines additional metadata such as the hash, IsAbsoluteLatestVersion, and IsLatestVersion.
        /// </summary>
        private IDictionary <IPackage, DerivedPackageData> CreateCache()
        {
            ConcurrentDictionary <IPackage, DerivedPackageData> packages = new ConcurrentDictionary <IPackage, DerivedPackageData>();

            ParallelOptions opts = new ParallelOptions();

            opts.MaxDegreeOfParallelism = 4;

            ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> > absoluteLatest = new ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> >();
            ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> > latest         = new ConcurrentDictionary <string, Tuple <IPackage, DerivedPackageData> >();

            // get settings
            bool checkFrameworks = EnableFrameworkFiltering;
            bool enableDelisting = EnableDelisting;
            // we need to save the current context because it's stored in TLS and we're computing hashes on different threads.
            var context = HttpContext.Current;

            // load and cache all packages.
            // Note that we can't pass GetPackageFiles() to Parallel.ForEach() because
            // the file could be added/deleted from _fileSystem, and if this happens,
            // we'll get error "Collection was modified; enumeration operation may not execute."
            // So we have to materialize the IEnumerable into a list first.
            var packageFiles = GetPackageFiles().ToList();

            Parallel.ForEach(packageFiles, opts, path =>
            {
                OptimizedZipPackage zip = OpenPackage(path);

                Debug.Assert(zip != null, "Unable to open " + path);
                if (zip == null)
                {
                    return;
                }
                if (enableDelisting)
                {
                    // hidden packages are considered delisted
                    zip.Listed = !File.GetAttributes(_fileSystem.GetFullPath(path)).HasFlag(FileAttributes.Hidden);
                }

                string packageHash       = null;
                long packageSize         = 0;
                string persistedHashFile = EnablePersistNupkgHash ? GetHashFile(path, false) : null;
                bool hashComputeNeeded   = true;

                ReadHashFile(context, path, persistedHashFile, ref packageSize, ref packageHash, ref hashComputeNeeded);

                if (hashComputeNeeded)
                {
                    using (var stream = _fileSystem.OpenFile(path))
                    {
                        packageSize = stream.Length;
                        packageHash = Convert.ToBase64String(HashProvider.CalculateHash(stream));
                    }
                    WriteHashFile(context, path, persistedHashFile, packageSize, packageHash);
                }

                var data = new DerivedPackageData
                {
                    PackageSize = packageSize,
                    PackageHash = packageHash,
                    LastUpdated = _fileSystem.GetLastModified(path),
                    Created     = _fileSystem.GetCreated(path),
                    Path        = path,
                    FullPath    = _fileSystem.GetFullPath(path),

                    // default to false, these will be set later
                    IsAbsoluteLatestVersion = false,
                    IsLatestVersion         = false
                };

                if (checkFrameworks)
                {
                    data.SupportedFrameworks = zip.GetSupportedFrameworks();
                }

                var entry = new Tuple <IPackage, DerivedPackageData>(zip, data);

                // find the latest versions
                string id = zip.Id.ToLowerInvariant();

                // update with the highest version
                absoluteLatest.AddOrUpdate(id, entry, (oldId, oldEntry) => oldEntry.Item1.Version < entry.Item1.Version ? entry : oldEntry);

                // update latest for release versions
                if (zip.IsReleaseVersion())
                {
                    latest.AddOrUpdate(id, entry, (oldId, oldEntry) => oldEntry.Item1.Version < entry.Item1.Version ? entry : oldEntry);
                }

                // add the package to the cache, it should not exist already
                Debug.Assert(packages.ContainsKey(zip) == false, "duplicate package added");
                packages.AddOrUpdate(zip, entry.Item2, (oldPkg, oldData) => oldData);
            });

            // Set additional attributes after visiting all packages
            foreach (var entry in absoluteLatest.Values)
            {
                entry.Item2.IsAbsoluteLatestVersion = true;
            }

            foreach (var entry in latest.Values)
            {
                entry.Item2.IsLatestVersion = true;
            }

            return(packages);
        }