Esempio n. 1
0
        /// <summary>
        /// Retrieves update data for the list of update ids
        /// </summary>
        /// <param name="updateIds">The ids to retrieve data for</param>
        /// <param name="destination">The metadata destination to write update metadata to</param>
        private void GetUpdateDataForIds(List <UpdateIdentity> updateIds, IMetadataSink destination)
        {
            // Data retrieval is done is done in batches of upto MaxNumberOfUpdatesPerRequest
            var retrieveBatches = CreateBatchedListFromFlatList(updateIds, ConfigData.MaxNumberOfUpdatesPerRequest);

            // Progress tracking and reporting
            int batchesDone = 0;
            var progress    = new MetadataQueryProgress()
            {
                CurrentTask = MetadataQueryStage.GetUpdateMetadataProgress, Maximum = updateIds.Count, Current = 0
            };

            MetadataQueryProgress?.Invoke(this, progress);

            // Run batches in parallel
            retrieveBatches.AsParallel().ForAll(batch =>
            {
                var updateDataRequest                     = new GetUpdateDataRequest();
                updateDataRequest.GetUpdateData           = new GetUpdateDataRequestBody();
                updateDataRequest.GetUpdateData.cookie    = AccessToken.AccessCookie;
                updateDataRequest.GetUpdateData.updateIds = batch;

                GetUpdateDataResponse updateDataReply;
                int retryCount = 0;
                do
                {
                    try
                    {
                        updateDataReply = ServerSyncClient.GetUpdateDataAsync(updateDataRequest).GetAwaiter().GetResult();
                    }
                    catch (System.TimeoutException)
                    {
                        updateDataReply = null;
                    }
                    retryCount++;
                } while (updateDataReply == null && retryCount < 10);

                if (updateDataReply == null || updateDataReply.GetUpdateDataResponse1 == null || updateDataReply.GetUpdateDataResponse1.GetUpdateDataResult == null)
                {
                    throw new Exception("Failed to get update metadata");
                }

                // Parse the list of raw files into a more usable format
                var filesList = new List <UpdateFileUrl>(updateDataReply.GetUpdateDataResponse1.GetUpdateDataResult.fileUrls.Select(rawFile => new UpdateFileUrl(rawFile)));

                // First add the files information to the store; it will be used to link update files with urls later
                filesList.ForEach(file => destination.AddFile(file));

                // Add the updates to the result, converting them to a higher level representation
                destination.AddUpdates(updateDataReply.GetUpdateDataResponse1.GetUpdateDataResult.updates);

                lock (destination)
                {
                    // Track progress
                    batchesDone++;
                    progress.PercentDone = ((double)batchesDone * 100) / retrieveBatches.Count;
                    progress.Current    += batch.Count();
                    MetadataQueryProgress?.Invoke(this, progress);
                }
            });
        }
Esempio n. 2
0
        /// <summary>
        /// Return metadata for updates
        /// </summary>
        /// <param name="request">The request; contains IDs for updates to retrieve metadata for</param>
        /// <returns>Update metadata for requested updates</returns>
        public Task <ServerUpdateData> GetUpdateDataAsync(GetUpdateDataRequest request)
        {
            var response = new ServerUpdateData();

            // Make sure the request is not larger than the config says
            var updateRequestCount = request.GetUpdateData.updateIds.Count();

            if (updateRequestCount > ServiceConfiguration.MaxNumberOfUpdatesPerRequest)
            {
                return(null);
            }

            var returnUpdatesList = new List <ServerSyncUpdateData>();
            var returnFilesList   = new List <ServerSyncUrlData>();

            foreach (var rawIdentity in request.GetUpdateData.updateIds)
            {
                var updateIdentity = new Identity(rawIdentity);

                // Find the update; it can be either category or update
                Update update;
                if (!FilteredUpdates.TryGetValue(updateIdentity, out update))
                {
                    if ((update = Categories.First(c => c.Identity.Equals(updateIdentity))) == null)
                    {
                        throw new Exception("Update not found");
                    }
                }

                if (update.HasFiles)
                {
                    // if update contains files, we must also gather file information
                    foreach (var updateFile in update.Files)
                    {
                        returnFilesList.Add(
                            new ServerSyncUrlData()
                        {
                            FileDigest = Convert.FromBase64String(updateFile.Digests[0].DigestBase64),
                            MUUrl      = updateFile.Urls[0].MuUrl,
                            UssUrl     = $"Content/{updateFile.GetContentDirectoryName()}/{updateFile.FileName}"
                        });
                    }
                }

                var rawUpdateData = new ServerSyncUpdateData();
                rawUpdateData.Id = rawIdentity;

                using (var metadataReader = new StreamReader(MetadataSource.GetUpdateMetadataStream(update.Identity)))
                {
                    rawUpdateData.XmlUpdateBlob = metadataReader.ReadToEnd();
                }

                returnUpdatesList.Add(rawUpdateData);
            }

            response.updates = returnUpdatesList.ToArray();

            // Deduplicate list of files
            response.fileUrls = returnFilesList.GroupBy(f => f.MUUrl).Select(k => k.First()).ToArray();

            return(Task.FromResult(response));
        }