public BaseFacts()
 {
     _target = new AuxiliaryData(
         DateTimeOffset.MinValue,
         Data.GetAuxiliaryFileResult(new DownloadData(), string.Empty),
         Data.GetAuxiliaryFileResult(new HashSet <string>(StringComparer.OrdinalIgnoreCase), string.Empty));
 }
            public void UsesSameMetadataInstances()
            {
                var downloadData    = Data.GetAuxiliaryFileResult(new DownloadData(), string.Empty);
                var verifedPackages = Data.GetAuxiliaryFileResult(new HashSet <string>(StringComparer.OrdinalIgnoreCase), string.Empty);

                var target = new AuxiliaryData(
                    DateTimeOffset.MaxValue,
                    downloadData,
                    verifedPackages);

                Assert.Equal(DateTimeOffset.MaxValue, target.Metadata.Loaded);
                Assert.Same(downloadData.Metadata, target.Metadata.Downloads);
                Assert.Same(verifedPackages.Metadata, target.Metadata.VerifiedPackages);
            }
        private async Task LoadAsync(TimeSpan timeout, bool shouldReload, CancellationToken token)
        {
            var acquired = false;

            try
            {
                acquired = await _lock.WaitAsync(timeout, token);

                if (!acquired)
                {
                    _logger.LogInformation("Another thread is already reloading the auxiliary data.");
                }
                else
                {
                    if (!shouldReload && Initialized)
                    {
                        return;
                    }

                    _logger.LogInformation("Starting the reload of auxiliary data.");

                    var stopwatch = Stopwatch.StartNew();

                    // Load the auxiliary files in parallel.
                    const string downloadsName        = nameof(_data.Downloads);
                    const string verifiedPackagesName = nameof(_data.VerifiedPackages);
                    var          downloadsTask        = LoadAsync(_data?.Downloads, _downloadDataClient.ReadLatestIndexedAsync);
                    var          verifiedPackagesTask = LoadAsync(_data?.VerifiedPackages, _verifiedPackagesDataClient.ReadLatestAsync);
                    await Task.WhenAll(downloadsTask, verifiedPackagesTask);

                    var downloads        = await downloadsTask;
                    var verifiedPackages = await verifiedPackagesTask;

                    // Keep track of what was actually reloaded and what didn't change.
                    var reloadedNames    = new List <string>();
                    var notModifiedNames = new List <string>();
                    (ReferenceEquals(_data?.Downloads, downloads) ? notModifiedNames : reloadedNames).Add(downloadsName);
                    (ReferenceEquals(_data?.VerifiedPackages, verifiedPackages) ? notModifiedNames : reloadedNames).Add(verifiedPackagesName);

                    // Reference assignment is atomic, so this is what makes the data available for readers.
                    _data = new AuxiliaryData(
                        DateTimeOffset.UtcNow,
                        downloads,
                        verifiedPackages);

                    // Track the counts regarding the string cache status.
                    _telemetryService.TrackAuxiliaryFilesStringCache(
                        _stringCache.StringCount,
                        _stringCache.CharCount,
                        _stringCache.RequestCount,
                        _stringCache.HitCount);
                    _stringCache.ResetCounts();

                    stopwatch.Stop();
                    _telemetryService.TrackAuxiliaryFilesReload(reloadedNames, notModifiedNames, stopwatch.Elapsed);
                    _logger.LogInformation(
                        "Done reloading auxiliary data. Took {Duration}. Reloaded: {Reloaded}. Not modified: {NotModified}",
                        stopwatch.Elapsed,
                        reloadedNames,
                        notModifiedNames);
                }
            }
            finally
            {
                if (acquired)
                {
                    _lock.Release();
                }
            }
        }