Example #1
0
        /// <summary>
        /// Adds a list of updates to the query result. The XML metadata is written to disk to avoid running out of memory
        /// </summary>
        /// <param name="overTheWireUpdates">The updates to add to the result</param>
        public void AddUpdates(IEnumerable <ServerSyncUpdateData> overTheWireUpdates)
        {
            foreach (var overTheWireUpdate in overTheWireUpdates)
            {
                var updateIdentity = new Identity(overTheWireUpdate.Id);

                bool newEntryToBeAdded = false;
                lock (Identities)
                {
                    if (!Identities.Contains(updateIdentity))
                    {
                        newEntryToBeAdded = true;
                    }
                }

                if (newEntryToBeAdded)
                {
                    // We need to parse the XML update blob
                    string updateXml = overTheWireUpdate.XmlUpdateBlob;
                    if (string.IsNullOrEmpty(updateXml))
                    {
                        // If the plain text blob is not availabe, use the compressed XML blob
                        if (overTheWireUpdate.XmlUpdateBlobCompressed == null || overTheWireUpdate.XmlUpdateBlobCompressed.Length == 0)
                        {
                            throw new Exception("Missing XmlUpdateBlobCompressed");
                        }

                        // Note: This only works on Windows.
                        updateXml = CabinetUtility.DecompressData(overTheWireUpdate.XmlUpdateBlobCompressed);
                    }

                    var xdoc      = XDocument.Parse(updateXml, LoadOptions.None);
                    var newUpdate = Update.FromUpdateXml(updateIdentity, xdoc);
                    AddUpdate(newUpdate, updateXml, out var newUpdateIndex, xdoc);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Adds an update to the query result. The XML metadata is written to disk to avoid running out of memory
        /// </summary>
        /// <param name="update">The updates to add to the result</param>
        /// <param name="updateMetadata">The update metadata to add</param>
        /// <param name="newUpdateIndex">The index of the new entry, if it was added to the index</param>
        /// <param name="updateXmlDoc">Update XML document used to load additional data if needed</param>
        /// <returns>True if a new entry was added, false otherwise</returns>
        private bool AddUpdate(Update update, string updateMetadata, out int newUpdateIndex, XDocument updateXmlDoc)
        {
            var updateIdentity = update.Identity;

            newUpdateIndex = 0;

            lock (Identities)
            {
                if (!Identities.Contains(updateIdentity))
                {
                    newUpdateIndex = AddUpdateEntry(update, updateXmlDoc);

                    var updateEntryName = GetUpdateXmlPath(updateIdentity);
                    OutputFile.PutNextEntry(new ZipEntry(updateEntryName));
                    OutputFile.Write(Encoding.UTF8.GetBytes(updateMetadata));
                    OutputFile.CloseEntry();
                    OutputFile.Flush();

                    return(true);
                }
            }

            return(false);
        }
        private void AddUpdateBundleInformation(int newUpdateIndex, Identity newUpdateIdentity, XDocument updateXml)
        {
            var bundledUpdates = BundlesUpdatesParser.Parse(updateXml);

            if (PendingBundledUpdates.ContainsKey(newUpdateIdentity))
            {
                // We've seen this update before, as bundled with other updates
                // Now that we have an update for it, adds its bundling information
                IsBundledTable.Add(newUpdateIndex, PendingBundledUpdates[newUpdateIdentity]);
                foreach (var newUpdateParentBundleIndex in PendingBundledUpdates[newUpdateIdentity])
                {
                    // A bundled update that was pending before was added; add it to the parent's list of bundled updates
                    if (!BundlesIndex[newUpdateParentBundleIndex].Contains(newUpdateIndex))
                    {
                        BundlesIndex[newUpdateParentBundleIndex].Add(newUpdateIndex);
                    }
                }

                // Remove from list of pending updates;
                PendingBundledUpdates.Remove(newUpdateIdentity);
            }
            else
            {
                // When initially added, updates are not considered bundled
                // Updates become bundled when they are found within another update
                IsBundledTable.Add(newUpdateIndex, new List <int>());
            }

            if (bundledUpdates.Count > 0)
            {
                var knownBundledUpdates   = bundledUpdates.Where(u => Identities.Contains(u)).Select(id => this[id]);
                var unknownBundledUpdates = bundledUpdates.Where(u => !Identities.Contains(u));

                // Add known bundled updates
                BundlesIndex.Add(
                    newUpdateIndex,
                    new List <int>(knownBundledUpdates));

                // Mark all bundled updates as bundled
                foreach (var bundledUpdate in knownBundledUpdates)
                {
                    // Try to mark the bundled update as bundled by adding it to the bundled table
                    if (IsBundledTable.ContainsKey(bundledUpdate))
                    {
                        // An entry already exists; switch it to true now, regardless of the previous value
                        if (!IsBundledTable[bundledUpdate].Contains(newUpdateIndex))
                        {
                            IsBundledTable[bundledUpdate].Add(newUpdateIndex);
                        }
                    }
                    else
                    {
                        IsBundledTable.Add(bundledUpdate, new List <int>()
                        {
                            newUpdateIndex
                        });
                    }
                }

                // Add unknown bundled updates to a pending list
                foreach (var bundledUpdate in unknownBundledUpdates)
                {
                    // The bundled update was not added to the metadata collection yet. Put it on a pending list with a mapping to its parent bundle
                    if (PendingBundledUpdates.ContainsKey(bundledUpdate))
                    {
                        if (!PendingBundledUpdates[bundledUpdate].Contains(newUpdateIndex))
                        {
                            PendingBundledUpdates[bundledUpdate].Add(newUpdateIndex);
                        }
                    }
                    else
                    {
                        PendingBundledUpdates.TryAdd(bundledUpdate, new List <int>()
                        {
                            newUpdateIndex
                        });
                    }
                }
            }
        }