Index: base/metrics/histogram_persistence.cc |
diff --git a/base/metrics/histogram_persistence.cc b/base/metrics/histogram_persistence.cc |
index f18d17528354329cd4995615d2451f6a52c59302..77515fffe9e3333899330aa751b751184ec3f574 100644 |
--- a/base/metrics/histogram_persistence.cc |
+++ b/base/metrics/histogram_persistence.cc |
@@ -10,6 +10,7 @@ |
#include "base/metrics/histogram.h" |
#include "base/metrics/histogram_base.h" |
#include "base/metrics/histogram_samples.h" |
+#include "base/metrics/sparse_histogram.h" |
#include "base/metrics/statistics_recorder.h" |
#include "base/synchronization/lock.h" |
@@ -238,6 +239,17 @@ HistogramBase* CreatePersistentHistogram( |
return nullptr; |
} |
+ // Sparse histograms are quite different so handle them as a special case. |
+ if (histogram_data_ptr->histogram_type == SPARSE_HISTOGRAM) { |
+ HistogramBase* histogram = SparseHistogram::PersistentGet( |
+ allocator, |
+ histogram_data_ptr->name, |
+ &histogram_data_ptr->samples_metadata, |
+ &histogram_data_ptr->logged_metadata); |
+ DCHECK(histogram); |
+ return histogram; |
+ } |
+ |
// Copy the histogram_data to local storage because anything in persistent |
// memory cannot be trusted as it could be changed at any moment by a |
// malicious actor that shares access. The contents of histogram_data are |
@@ -419,48 +431,68 @@ HistogramBase* AllocatePersistentHistogram( |
return nullptr; |
} |
- // If CalculateRequiredCountsBytes() returns zero then the bucket_count |
- // was not valid. |
- size_t bucket_count = bucket_ranges->bucket_count(); |
- size_t counts_bytes = CalculateRequiredCountsBytes(bucket_count); |
- if (!counts_bytes) { |
- NOTREACHED(); |
- return nullptr; |
- } |
+ // Create all the metadata necessary for a persistent histogram. Sparse |
+ // histograms are quite different so handle them as a special case. |
+ PersistentMemoryAllocator::Reference histogram_ref = 0; |
+ PersistentHistogramData* histogram_data = nullptr; |
+ if (histogram_type == SPARSE_HISTOGRAM) { |
+ histogram_ref = allocator->Allocate( |
+ offsetof(PersistentHistogramData, name) + name.length() + 1, |
+ kTypeIdHistogram); |
+ histogram_data = allocator->GetAsObject<PersistentHistogramData>( |
+ histogram_ref, kTypeIdHistogram); |
+ if (histogram_data) { |
+ strcpy(histogram_data->name, name.c_str()); |
+ histogram_data->histogram_type = histogram_type; |
+ histogram_data->flags = flags; |
+ } |
+ } else { |
+ // If CalculateRequiredCountsBytes() returns zero then the bucket_count |
grt (UTC plus 2)
2016/03/02 20:00:42
nit: move this comment into the "!counts_bytes" bl
bcwhite
2016/03/02 22:32:43
Done.
|
+ // was not valid. |
+ size_t bucket_count = bucket_ranges->bucket_count(); |
+ size_t counts_bytes = CalculateRequiredCountsBytes(bucket_count); |
+ if (!counts_bytes) { |
+ NOTREACHED(); |
+ return nullptr; |
+ } |
- size_t ranges_bytes = (bucket_count + 1) * sizeof(HistogramBase::Sample); |
- PersistentMemoryAllocator::Reference ranges_ref = |
- allocator->Allocate(ranges_bytes, kTypeIdRangesArray); |
- PersistentMemoryAllocator::Reference counts_ref = |
- allocator->Allocate(counts_bytes, kTypeIdCountsArray); |
- PersistentMemoryAllocator::Reference histogram_ref = |
- allocator->Allocate(offsetof(PersistentHistogramData, name) + |
- name.length() + 1, kTypeIdHistogram); |
- HistogramBase::Sample* ranges_data = |
- allocator->GetAsObject<HistogramBase::Sample>(ranges_ref, |
- kTypeIdRangesArray); |
- PersistentHistogramData* histogram_data = |
- allocator->GetAsObject<PersistentHistogramData>(histogram_ref, |
- kTypeIdHistogram); |
- |
- // Only continue here if all allocations were successful. If they weren't |
- // there is no way to free the space but that's not really a problem since |
- // the allocations only fail because the space is full and so any future |
- // attempts will also fail. |
- if (counts_ref && ranges_data && histogram_data) { |
- strcpy(histogram_data->name, name.c_str()); |
- for (size_t i = 0; i < bucket_ranges->size(); ++i) |
- ranges_data[i] = bucket_ranges->range(i); |
- |
- histogram_data->histogram_type = histogram_type; |
- histogram_data->flags = flags; |
- histogram_data->minimum = minimum; |
- histogram_data->maximum = maximum; |
- histogram_data->bucket_count = static_cast<uint32_t>(bucket_count); |
- histogram_data->ranges_ref = ranges_ref; |
- histogram_data->ranges_checksum = bucket_ranges->checksum(); |
- histogram_data->counts_ref = counts_ref; |
+ size_t ranges_bytes = (bucket_count + 1) * sizeof(HistogramBase::Sample); |
+ PersistentMemoryAllocator::Reference counts_ref = |
+ allocator->Allocate(counts_bytes, kTypeIdCountsArray); |
+ PersistentMemoryAllocator::Reference ranges_ref = |
+ allocator->Allocate(ranges_bytes, kTypeIdRangesArray); |
+ HistogramBase::Sample* ranges_data = |
+ allocator->GetAsObject<HistogramBase::Sample>(ranges_ref, |
+ kTypeIdRangesArray); |
+ histogram_ref = allocator->Allocate( |
+ offsetof(PersistentHistogramData, name) + name.length() + 1, |
+ kTypeIdHistogram); |
+ histogram_data = allocator->GetAsObject<PersistentHistogramData>( |
+ histogram_ref, kTypeIdHistogram); |
+ |
+ // Only continue here if all allocations were successful. If they weren't |
+ // there is no way to free the space but that's not really a problem since |
+ // the allocations only fail because the space is full and so any future |
+ // attempts will also fail. |
+ if (counts_ref && ranges_data && histogram_data) { |
+ strcpy(histogram_data->name, name.c_str()); |
grt (UTC plus 2)
2016/03/02 20:00:42
nit: use memcpy since you know the size
bcwhite
2016/03/02 22:32:43
Done.
|
+ for (size_t i = 0; i < bucket_ranges->size(); ++i) |
+ ranges_data[i] = bucket_ranges->range(i); |
+ |
+ histogram_data->histogram_type = histogram_type; |
+ histogram_data->flags = flags; |
+ histogram_data->minimum = minimum; |
+ histogram_data->maximum = maximum; |
+ histogram_data->bucket_count = static_cast<uint32_t>(bucket_count); |
grt (UTC plus 2)
2016/03/02 20:00:42
i think this is safe on account of CalculateRequir
bcwhite
2016/03/02 22:32:43
It's actually limited because any allocation that
|
+ histogram_data->ranges_ref = ranges_ref; |
+ histogram_data->ranges_checksum = bucket_ranges->checksum(); |
+ histogram_data->counts_ref = counts_ref; |
+ } else { |
+ histogram_data = nullptr; // Clear this for proper handling below. |
+ } |
+ } |
+ if (histogram_data) { |
// Create the histogram using resources in persistent memory. This ends up |
// resolving the "ref" values stored in histogram_data instad of just |
// using what is already known above but avoids duplicating the switch |