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); }