public Package(IPackage package, DerivedPackageData derivedData) { Id = package.Id; Version = package.Version.ToString(); Title = package.Title; Authors = String.Join(",", package.Authors); if (package.IconUrl != null) { IconUrl = package.IconUrl.GetComponents(UriComponents.HttpRequestUrl, UriFormat.Unescaped); } if (package.LicenseUrl != null) { LicenseUrl = package.LicenseUrl.GetComponents(UriComponents.HttpRequestUrl, UriFormat.Unescaped); } if (package.ProjectUrl != null) { ProjectUrl = package.ProjectUrl.GetComponents(UriComponents.HttpRequestUrl, UriFormat.Unescaped); } RequireLicenseAcceptance = package.RequireLicenseAcceptance; Description = package.Description; Summary = package.Summary; ReleaseNotes = package.ReleaseNotes; Tags = package.Tags; Dependencies = String.Join("|", package.DependencySets.SelectMany(ConvertDependencySetToStrings)); PackageHash = derivedData.PackageHash; PackageHashAlgorithm = "SHA512"; PackageSize = derivedData.PackageSize; LastUpdated = derivedData.LastUpdated.UtcDateTime; Published = derivedData.Created.UtcDateTime; IsAbsoluteLatestVersion = package.IsAbsoluteLatestVersion; IsLatestVersion = package.IsLatestVersion; Path = derivedData.Path; FullPath = derivedData.FullPath; MinClientVersion = package.MinClientVersion == null ? null : package.MinClientVersion.ToString(); }
private void SetData(IPackage package, DerivedPackageData packageData) { _cacheLock.EnterWriteLock(); try { _derivedDataLookup[package] = packageData; } finally { _cacheLock.ExitWriteLock(); } }
/// <summary> /// Gives the Package containing both the IPackage and the derived metadata. /// The returned Package will be null if <paramref name="package" /> no longer exists in the cache. /// </summary> public Package GetMetadataPackage(IPackage package) { Package metadata = null; // The cache may have changed, and the metadata may no longer exist DerivedPackageData data = null; if (PackageCache.TryGetValue(package, out data)) { metadata = new Package(package, data); } return(metadata); }
/// <summary> /// Gets the metadata package. /// </summary> /// <param name="package">The package.</param> /// <returns></returns> public Package GetMetadataPackage(IPackage package) { var derived = new DerivedPackageData() { //Created = ? //FullPath = ? IsAbsoluteLatestVersion = package.IsAbsoluteLatestVersion, IsLatestVersion = package.IsLatestVersion //LastUpdated = ? //PackageHash = package.GetHash(), //PackageSize = ?? //Path = ?? //SupportedFrameworks = package.GetSupportedFrameworks(), }; //var pkg = new Package(package, new DerivedPackageData()); return new Package(package, derived); }
protected override IPackage OpenPackage(string path) { IPackage package = base.OpenPackage(path); if (EnableDelisting) { // hidden packages are considered delisted var localPackage = package as LocalPackage; if (localPackage != null) { localPackage.Listed = !File.GetAttributes(FileSystem.GetFullPath(path)).HasFlag(FileAttributes.Hidden); } } _cacheLock.EnterWriteLock(); try { DateTime start = DateTime.Now; while (true) { DerivedPackageData packageData; if (!_derivedDataLookup.TryGetValue(package, out packageData)) { // take ownership _derivedDataLookup[package] = null; break; } if (packageData != null) { // derived data has been computed and cached return(package); } if ((DateTime.Now - start).TotalSeconds > MaxWaitMs) { // we're giving up on waiting; potentially other thread is blocked, died, ... take ownership _derivedDataLookup[package] = null; break; } // about to wait; release locks _cacheLock.ExitWriteLock(); _derivedDataComputed.WaitOne(MaxWaitMs); _cacheLock.EnterWriteLock(); } } finally { _cacheLock.ExitWriteLock(); } try { // compute DerivedPackageData packageData = CalculateDerivedData(package, path); // write value SetData(package, packageData); } catch { // on failure, clean cache DeleteData(package); throw; } finally { // We've either failed or succeeded => wake up waiting threads, if any. _derivedDataComputed.Set(); } return(package); }
/// <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; }
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); }
/// <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; // 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); }