| Index: components/metrics/file_metrics_provider.cc
|
| diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc
|
| index d9a6a042c23ce137a1f0deac417e7f81ffb61f14..cd591f5774ffd75ce3767793efe5de99000f68f7 100644
|
| --- a/components/metrics/file_metrics_provider.cc
|
| +++ b/components/metrics/file_metrics_provider.cc
|
| @@ -20,6 +20,7 @@
|
| #include "base/time/time.h"
|
| #include "components/metrics/metrics_pref_names.h"
|
| #include "components/metrics/metrics_service.h"
|
| +#include "components/metrics/persistent_system_profile.h"
|
| #include "components/prefs/pref_registry_simple.h"
|
| #include "components/prefs/pref_service.h"
|
|
|
| @@ -84,12 +85,16 @@ void DeleteFileWhenPossible(const base::FilePath& path) {
|
| // This structure stores all the information about the sources being monitored
|
| // and their current reporting state.
|
| struct FileMetricsProvider::SourceInfo {
|
| - SourceInfo(SourceType source_type) : type(source_type) {}
|
| + SourceInfo(SourceType source_type, SourceAssociation source_association)
|
| + : type(source_type), association(source_association) {}
|
| ~SourceInfo() {}
|
|
|
| // How to access this source (file/dir, atomic/active).
|
| const SourceType type;
|
|
|
| + // With what run this source is associated.
|
| + const SourceAssociation association;
|
| +
|
| // Where on disk the directory is located. This will only be populated when
|
| // a directory is being monitored.
|
| base::FilePath directory;
|
| @@ -136,7 +141,7 @@ void FileMetricsProvider::RegisterSource(const base::FilePath& path,
|
| // Ensure that kSourceOptions has been filled for this type.
|
| DCHECK_GT(arraysize(kSourceOptions), static_cast<size_t>(type));
|
|
|
| - std::unique_ptr<SourceInfo> source(new SourceInfo(type));
|
| + std::unique_ptr<SourceInfo> source(new SourceInfo(type, source_association));
|
| source->prefs_key = prefs_key.as_string();
|
|
|
| switch (source->type) {
|
| @@ -161,9 +166,11 @@ void FileMetricsProvider::RegisterSource(const base::FilePath& path,
|
|
|
| switch (source_association) {
|
| case ASSOCIATE_CURRENT_RUN:
|
| + case ASSOCIATE_INTERNAL_PROFILE:
|
| sources_to_check_.push_back(std::move(source));
|
| break;
|
| case ASSOCIATE_PREVIOUS_RUN:
|
| + case ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN:
|
| DCHECK_EQ(SOURCE_HISTOGRAMS_ATOMIC_FILE, source->type);
|
| sources_for_previous_run_.push_back(std::move(source));
|
| break;
|
| @@ -250,6 +257,30 @@ bool FileMetricsProvider::LocateNextFileInDirectory(SourceInfo* source) {
|
| }
|
|
|
| // static
|
| +void FileMetricsProvider::FinishedWithSource(SourceInfo* source,
|
| + AccessResult result) {
|
| + // Different source types require different post-processing.
|
| + switch (source->type) {
|
| + case SOURCE_HISTOGRAMS_ATOMIC_FILE:
|
| + case SOURCE_HISTOGRAMS_ATOMIC_DIR:
|
| + // Done with this file so delete the allocator and its owned file.
|
| + source->allocator.reset();
|
| + // Remove the file if has been recorded. This prevents them from
|
| + // accumulating or also being recorded by different instances of
|
| + // the browser.
|
| + if (result == ACCESS_RESULT_SUCCESS ||
|
| + result == ACCESS_RESULT_NOT_MODIFIED) {
|
| + DeleteFileWhenPossible(source->path);
|
| + }
|
| + break;
|
| + case SOURCE_HISTOGRAMS_ACTIVE_FILE:
|
| + // Keep the allocator open so it doesn't have to be re-mapped each
|
| + // time. This also allows the contents to be merged on-demand.
|
| + break;
|
| + }
|
| +}
|
| +
|
| +// static
|
| void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner(
|
| SourceInfoList* sources) {
|
| // This method has all state information passed in |sources| and is intended
|
| @@ -264,31 +295,19 @@ void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner(
|
| "UMA.FileMetricsProvider.AccessResult", result, ACCESS_RESULT_MAX);
|
| }
|
|
|
| + // Metrics associted with internal profiles have to be fetched directly
|
| + // so just keep the mapping for use by the main thread.
|
| + if (source->association == ASSOCIATE_INTERNAL_PROFILE)
|
| + continue;
|
| +
|
| // Mapping was successful. Merge it.
|
| if (result == ACCESS_RESULT_SUCCESS) {
|
| MergeHistogramDeltasFromSource(source.get());
|
| DCHECK(source->read_complete);
|
| }
|
|
|
| - // Different source types require different post-processing.
|
| - switch (source->type) {
|
| - case SOURCE_HISTOGRAMS_ATOMIC_FILE:
|
| - case SOURCE_HISTOGRAMS_ATOMIC_DIR:
|
| - // Done with this file so delete the allocator and its owned file.
|
| - source->allocator.reset();
|
| - // Remove the file if has been recorded. This prevents them from
|
| - // accumulating or also being recorded by different instances of
|
| - // the browser.
|
| - if (result == ACCESS_RESULT_SUCCESS ||
|
| - result == ACCESS_RESULT_NOT_MODIFIED) {
|
| - base::DeleteFile(source->path, /*recursive=*/false);
|
| - }
|
| - break;
|
| - case SOURCE_HISTOGRAMS_ACTIVE_FILE:
|
| - // Keep the allocator open so it doesn't have to be re-mapped each
|
| - // time. This also allows the contents to be merged on-demand.
|
| - break;
|
| - }
|
| + // All done with this source.
|
| + FinishedWithSource(source.get(), result);
|
| }
|
| }
|
|
|
| @@ -297,8 +316,11 @@ void FileMetricsProvider::CheckAndMergeMetricSourcesOnTaskRunner(
|
| // static
|
| FileMetricsProvider::AccessResult FileMetricsProvider::CheckAndMapMetricSource(
|
| SourceInfo* source) {
|
| - DCHECK(!source->allocator);
|
| + // If source was read, clean up after it.
|
| + if (source->read_complete)
|
| + FinishedWithSource(source, ACCESS_RESULT_SUCCESS);
|
| source->read_complete = false;
|
| + DCHECK(!source->allocator);
|
|
|
| // If the source is a directory, look for files within it.
|
| if (!source->directory.empty() && !LocateNextFileInDirectory(source))
|
| @@ -437,10 +459,16 @@ void FileMetricsProvider::RecordSourcesChecked(SourceInfoList* checked) {
|
| RecordSourceAsRead(source);
|
| did_read = true;
|
| }
|
| - if (source->allocator)
|
| - sources_mapped_.splice(sources_mapped_.end(), *checked, temp);
|
| - else
|
| + if (source->allocator) {
|
| + if (source->association == ASSOCIATE_INTERNAL_PROFILE) {
|
| + sources_with_profile_.splice(sources_with_profile_.end(), *checked,
|
| + temp);
|
| + } else {
|
| + sources_mapped_.splice(sources_mapped_.end(), *checked, temp);
|
| + }
|
| + } else {
|
| sources_to_check_.splice(sources_to_check_.end(), *checked, temp);
|
| + }
|
| }
|
|
|
| // If a read was done, schedule another one immediately. In the case of a
|
| @@ -487,6 +515,36 @@ void FileMetricsProvider::OnDidCreateMetricsLog() {
|
| sources_for_previous_run_.clear();
|
| }
|
|
|
| +bool FileMetricsProvider::ProvideIndependentMetrics(
|
| + SystemProfileProto* system_profile_proto,
|
| + base::HistogramSnapshotManager* snapshot_manager) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + while (true) {
|
| + if (sources_with_profile_.empty())
|
| + return false;
|
| +
|
| + SourceInfo* source = sources_with_profile_.begin()->get();
|
| + DCHECK(source->allocator);
|
| +
|
| + bool success = false;
|
| + if (PersistentSystemProfile::GetSystemProfile(
|
| + *source->allocator->memory_allocator(), system_profile_proto)) {
|
| + RecordHistogramSnapshotsFromSource(snapshot_manager, source);
|
| + success = true;
|
| + }
|
| +
|
| + // Regardless of whether this source was successfully recorded, it is never
|
| + // read again.
|
| + source->read_complete = true;
|
| + RecordSourceAsRead(source);
|
| + sources_to_check_.splice(sources_to_check_.end(), sources_with_profile_,
|
| + sources_with_profile_.begin());
|
| + if (success)
|
| + return true;
|
| + }
|
| +}
|
| +
|
| bool FileMetricsProvider::HasInitialStabilityMetrics() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
|
|
| @@ -521,6 +579,19 @@ bool FileMetricsProvider::HasInitialStabilityMetrics() {
|
| RecordSourceAsRead(source);
|
| DeleteFileAsync(source->path);
|
| sources_for_previous_run_.erase(temp);
|
| + continue;
|
| + }
|
| +
|
| + DCHECK(source->allocator);
|
| +
|
| + // If the source should be associated with an existing internal profile,
|
| + // move it to |sources_with_profile_| for later upload.
|
| + if (source->association == ASSOCIATE_INTERNAL_PROFILE_OR_PREVIOUS_RUN) {
|
| + if (PersistentSystemProfile::HasSystemProfile(
|
| + *source->allocator->memory_allocator())) {
|
| + sources_with_profile_.splice(sources_with_profile_.end(),
|
| + sources_for_previous_run_, temp);
|
| + }
|
| }
|
| }
|
|
|
|
|