private void ValidateBaseline() { if (!TryGetDeltaIndexFromFilePath(FilePath, out ulong parsedIndex, out string baseFileName)) { throw new Exception("Source file naming scheme is corrupt. Expected [version]-[rest of file name]."); } if (parsedIndex != DeltaIndex) { throw new Exception($"Source file naming scheme is corrupt. Expected index {DeltaIndex} but file name indicates index {parsedIndex}"); } BaselineFilePath = baseFileName + (DeltaIndex == 1 ? "" : "-" + (DeltaIndex - 1).ToString()) + ".zip"; if (!File.Exists(BaselineFilePath)) { throw new Exception($"Delta file {BaselineFilePath} missing"); } BaselineSource = Open(BaselineFilePath); if (BaselineSource == null) { throw new Exception($"Cannot open delta file {BaselineFilePath}"); } if (BaselineChecksum != BaselineSource.Checksum) { throw new Exception($"Unexpected checksum in delta file {BaselineFilePath}. Expected {BaselineChecksum}, found {BaselineSource.Checksum}"); } }
/// <summary> /// Creates a new metadata source as a delta from a baseline metadata source /// </summary> /// <param name="baseline"></param> public CompressedMetadataStore(CompressedMetadataStore baseline) { Version = CurrentVersion; DeltaIndex = baseline.DeltaIndex + 1; // Generate a file name that follows the indexed naming scheme. if (DeltaIndex == 1) { // If this is the first delta from a baseline, take the file name and add -1 to the end (before the extension) FilePath = $"{Path.GetFileNameWithoutExtension(baseline.FilePath)}-{DeltaIndex}{Path.GetExtension(baseline.FilePath)}"; } else { // If this is a higher delta from a baseline, make sure the current file matches the naming scheme if (!TryGetDeltaIndexFromFilePath(baseline.FilePath, out ulong parsedIndex, out string baseFileName)) { throw new Exception("Baseline file naming scheme is corrupt. Expected [file name]-[delta index].zip."); } // If it does, add the version to the base file name, before the extension FilePath = $"{baseFileName}-{DeltaIndex.ToString()}.zip"; } OutputFile = new ZipOutputStream(File.Create(FilePath)); BaselineSource = baseline; BaselineChecksum = baseline.Checksum; // Record the end of the index range for the baseline BaselineIndexesEnd = baseline.IndexToIdentity.Keys.Count - 1; BaselineIdentities = new SortedSet <Identity>(baseline.IndexToIdentity.Values); Identities = new SortedSet <Identity>(baseline.Identities); IndexToIdentity = new Dictionary <int, Identity>(baseline.IndexToIdentity); IdentityToIndex = new Dictionary <Identity, int>(baseline.IdentityToIndex); ProductsTree = new Dictionary <int, List <int> >(baseline.ProductsTree); UpdateTypeMap = new Dictionary <int, uint>(baseline.UpdateTypeMap); Updates = new ConcurrentDictionary <Identity, Update>(baseline.Updates); Categories = new ConcurrentDictionary <Identity, Update>(baseline.Categories); // Create update placeholders InstantiateUpdatePlaceholders(); UpstreamSource = baseline.UpstreamSource; // Populate indexes UpdatesIndex = Updates; CategoriesIndex = Categories; ProductsIndex = Categories.Values.OfType <Product>().ToDictionary(p => p.Identity); ClassificationsIndex = Categories.Values.OfType <Classification>().ToDictionary(c => c.Identity); DetectoidsIndex = Categories.Values.OfType <Detectoid>().ToDictionary(d => d.Identity); Filter = BaselineSource.Filter; CategoriesAnchor = BaselineSource.CategoriesAnchor; UpstreamAccountGuid = BaselineSource.UpstreamAccountGuid; UpstreamAccountName = BaselineSource.UpstreamAccountName; UpdateTitlesIndex = new Dictionary <int, string>(); // Initialize bundles information OnDeltaStore_InitializeBundes(); // Initialize prerequisites information OnDeltaStore_InitializePrerequisites(); // Initialize update classification and product information OnDeltaStore_InitializeProductClassification(); // Initialize files index OnDeltaStore_InitializeFilesIndex(); // Initialize superseding index OnDeltaStore_InitializeSupersededIndex(); // Initialize driver indexes OnDeltaStore_InitializeDriversIndex(); // Initialize KB articles index OnDeltaStore_InitializeKbArticles(); }