/// <inheritdoc />
        public async Task <AddDebugEntryResult> AddFileAsync(SymbolFile symbolFile)
        {
            Contract.Requires(symbolFile.IsIndexed, "File has not been indexed.");

            m_counters.IncrementCounter(SymbolClientCounter.NumAddFileRequests);
            if (symbolFile.DebugEntries.Count == 0)
            {
                // If there are no debug entries, ask bxl to log a message and return early.
                Analysis.IgnoreResult(await m_apiClient.LogMessage(I($"File '{symbolFile.FullFilePath}' does not contain symbols and will not be added to '{RequestName}'."), isWarning: false));
                m_counters.IncrementCounter(SymbolClientCounter.NumFilesWithoutDebugEntries);

                return(AddDebugEntryResult.NoSymbolData);
            }

            m_logger.Verbose($"Queued file '{symbolFile}'");
            var batchedFile = new BatchedSymbolFile(symbolFile);

            m_nagleQueue.Enqueue(batchedFile);
            return(await batchedFile.ResultTaskSource.Task);
        }
Exemple #2
0
        /// <inheritdoc />
        public async Task <AddDebugEntryResult> AddFileAsync(SymbolFile symbolFile)
        {
            Contract.Requires(symbolFile.IsIndexed, "File has not been indexed.");

            m_counters.IncrementCounter(SymbolClientCounter.NumAddFileRequests);

            if (symbolFile.DebugEntries.Count == 0)
            {
                // If there are no debug entries, ask bxl to log a message and return early.
                Analysis.IgnoreResult(await m_apiClient.LogMessage(I($"File '{symbolFile.FullFilePath}' does not contain symbols and will not be added to '{RequestName}'."), isWarning: false));
                m_counters.IncrementCounter(SymbolClientCounter.NumFilesWithoutDebugEntries);

                return(AddDebugEntryResult.NoSymbolData);
            }

            await EnsureRequestIdAndDomainIdAreInitalizedAsync();

            List <DebugEntry> result;

            using (m_counters.StartStopwatch(SymbolClientCounter.TotalAssociateTime))
            {
                try
                {
                    result = await m_symbolClient.CreateRequestDebugEntriesAsync(
                        RequestId,
                        symbolFile.DebugEntries.Select(e => CreateDebugEntry(e, m_domainId)),
                        // First, we create debug entries with ThrowIfExists behavior not to silence the collision errors.
                        DebugEntryCreateBehavior.ThrowIfExists,
                        CancellationToken);
                }
                catch (DebugEntryExistsException)
                {
                    string message = $"[SymbolDaemon] File: '{symbolFile.FullFilePath}' caused collision. " +
                                     (m_debugEntryCreateBehavior == DebugEntryCreateBehavior.ThrowIfExists
                            ? string.Empty
                            : $"SymbolDaemon will retry creating debug entry with {m_debugEntryCreateBehavior} behavior");

                    if (m_debugEntryCreateBehavior == DebugEntryCreateBehavior.ThrowIfExists)
                    {
                        // Log an error message in SymbolDaemon log file
                        m_logger.Error(message);
                        throw new DebugEntryExistsException(message);
                    }

                    // Log a message in SymbolDaemon log file
                    m_logger.Verbose(message);

                    result = await m_symbolClient.CreateRequestDebugEntriesAsync(
                        RequestId,
                        symbolFile.DebugEntries.Select(e => CreateDebugEntry(e, m_domainId)),
                        m_debugEntryCreateBehavior,
                        CancellationToken);
                }
            }

            var entriesWithMissingBlobs = result.Where(e => e.Status == DebugEntryStatus.BlobMissing).ToList();

            if (entriesWithMissingBlobs.Count > 0)
            {
                // All the entries are based on the same file, so we need to call upload only once.

                // make sure that the file is on disk (it might not be on disk if we got DebugEntries from cache/metadata file)
                var file = await symbolFile.EnsureMaterializedAsync();

                BlobIdentifierWithBlocks uploadResult;
                using (m_counters.StartStopwatch(SymbolClientCounter.TotalUploadTime))
                {
                    uploadResult = await m_symbolClient.UploadFileAsync(
                        m_domainId,
                        // uploading to the location set by the symbol service
                        entriesWithMissingBlobs[0].BlobUri,
                        RequestId,
                        symbolFile.FullFilePath,
                        entriesWithMissingBlobs[0].BlobIdentifier,
                        CancellationToken);
                }

                m_counters.IncrementCounter(SymbolClientCounter.NumFilesUploaded);
                m_counters.AddToCounter(SymbolClientCounter.TotalUploadSize, file.Length);

                m_logger.Info($"File: '{symbolFile.FullFilePath}' -- upload result: {uploadResult}");

                entriesWithMissingBlobs.ForEach(entry => entry.BlobDetails = uploadResult);

                using (m_counters.StartStopwatch(SymbolClientCounter.TotalAssociateAfterUploadTime))
                {
                    entriesWithMissingBlobs = await m_symbolClient.CreateRequestDebugEntriesAsync(
                        RequestId,
                        entriesWithMissingBlobs,
                        m_debugEntryCreateBehavior,
                        CancellationToken);
                }

                Contract.Assert(entriesWithMissingBlobs.All(e => e.Status != DebugEntryStatus.BlobMissing), "Entries with non-success code are present.");

                return(AddDebugEntryResult.UploadedAndAssociated);
            }

            m_counters.IncrementCounter(SymbolClientCounter.NumFilesAssociated);
            return(AddDebugEntryResult.Associated);
        }