public async Task UpdateAsync( HiveType hive, IReadOnlyList <HiveType> replicaHives, string id, IReadOnlyList <CatalogCommitItem> entries, IReadOnlyDictionary <CatalogCommitItem, PackageDetailsCatalogLeaf> entryToCatalogLeaf, CatalogCommit registrationCommit) { // Validate the input and put it in more convenient forms. if (!entries.Any()) { return; } GuardInput(entries, entryToCatalogLeaf); var sortedCatalog = entries.OrderBy(x => x.PackageIdentity.Version).ToList(); var versionToCatalogLeaf = entryToCatalogLeaf.ToDictionary(x => x.Key.PackageIdentity.Version, x => x.Value); // Remove SemVer 2.0.0 versions if this hive should only have SemVer 1.0.0 versions. if (ShouldExcludeSemVer2(hive)) { Guard.Assert( replicaHives.All(ShouldExcludeSemVer2), "A replica hive of a non-SemVer 2.0.0 hive must also exclude SemVer 2.0.0."); ExcludeSemVer2(hive, sortedCatalog, versionToCatalogLeaf); } else { Guard.Assert( replicaHives.All(x => !ShouldExcludeSemVer2(x)), "A replica hive of a SemVer 2.0.0 hive must also include SemVer 2.0.0."); } _logger.LogInformation( "Starting to update the {PackageId} registration index in the {Hive} hive and {ReplicaHives} replica hives with {UpsertCount} " + "package details and {DeleteCount} package deletes.", id, hive, replicaHives, entryToCatalogLeaf.Count, entries.Count - entryToCatalogLeaf.Count); // Read the existing registration index if it exists. If it does not exist, initialize a new index. var index = await _storage.ReadIndexOrNullAsync(hive, id); IndexInfo indexInfo; if (index == null) { indexInfo = IndexInfo.New(); } else { indexInfo = IndexInfo.Existing(_storage, hive, index); } // Find all of the existing page URLs. This will be used later to find orphan pages. var existingPageUrls = GetPageUrls(indexInfo); // Read all of the obviously relevant pages in parallel. This simply evaluates some work that would // otherwise be done lazily. await LoadRelevantPagesAsync(sortedCatalog, indexInfo); // Merge the incoming catalog entries in memory. var mergeResult = await _merger.MergeAsync(indexInfo, sortedCatalog); // Write the modified leaves. await UpdateLeavesAsync(hive, replicaHives, id, versionToCatalogLeaf, registrationCommit, mergeResult); // Write the pages and handle the inline vs. non-inlined cases. if (indexInfo.Items.Count == 0) { _logger.LogInformation("There are no pages to update."); } else { var itemCount = indexInfo.Items.Sum(x => x.Count); if (itemCount <= _options.Value.MaxInlinedLeafItems) { _logger.LogInformation( "There are {Count} total leaf items so the leaf items will be inlined.", itemCount); await UpdateInlinedPagesAsync(hive, id, indexInfo, registrationCommit); } else { _logger.LogInformation( "There are {Count} total leaf items so the leaf items will not be inlined.", itemCount); await UpdateNonInlinedPagesAsync(hive, replicaHives, id, indexInfo, registrationCommit, mergeResult); } } // Write the index, if there were any changes. if (mergeResult.ModifiedPages.Any() || mergeResult.ModifiedLeaves.Any()) { _logger.LogInformation("Updating the index."); _entityBuilder.UpdateIndex(indexInfo.Index, hive, id, indexInfo.Items.Count); _entityBuilder.UpdateCommit(indexInfo.Index, registrationCommit); await _storage.WriteIndexAsync(hive, replicaHives, id, indexInfo.Index); } if (!indexInfo.Items.Any()) { _logger.LogInformation("Deleting the index since there are no more page items."); await _storage.DeleteIndexAsync(hive, replicaHives, id); } // Delete orphan blobs. await DeleteOrphansAsync(hive, replicaHives, existingPageUrls, indexInfo, mergeResult); _logger.LogInformation( "Done updating the {PackageId} registration index in the {Hive} hive and replica hives {ReplicaHives}. {ModifiedPages} pages were " + "updated, {ModifiedLeaves} leaves were upserted, and {DeletedLeaves} leaves were deleted.", id, hive, replicaHives, mergeResult.ModifiedPages.Count, mergeResult.ModifiedLeaves.Count, mergeResult.DeletedLeaves.Count); }