Index: base/metrics/histogram.cc |
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc |
index 795ea3a832387c4bbaa1ddb8d101c94b5166f806..9f08a85ca63f0abb67ea2d6bf42d539a48b0454b 100644 |
--- a/base/metrics/histogram.cc |
+++ b/base/metrics/histogram.cc |
@@ -30,6 +30,54 @@ using std::vector; |
namespace base { |
+namespace { |
+ |
+bool ReadHistogramArguments(PickleIterator* iter, |
+ string* histogram_name, |
+ int* flags, |
+ int* declared_min, |
+ int* declared_max, |
+ uint64* bucket_count, |
+ uint32* range_checksum) { |
+ if (!iter->ReadString(histogram_name) || |
+ !iter->ReadInt(flags) || |
+ !iter->ReadInt(declared_min) || |
+ !iter->ReadInt(declared_max) || |
+ !iter->ReadUInt64(bucket_count) || |
+ !iter->ReadUInt32(range_checksum)) { |
+ DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name; |
+ return false; |
+ } |
+ |
+ // Since these fields may have come from an untrusted renderer, do additional |
+ // checks above and beyond those in Histogram::Initialize() |
+ if (*declared_max <= 0 || |
+ *declared_min <= 0 || |
+ *declared_max < *declared_min || |
+ INT_MAX / sizeof(HistogramBase::Count) <= *bucket_count || |
+ *bucket_count < 2) { |
+ DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; |
+ return false; |
+ } |
+ |
+ // We use the arguments to find or create the local version of the histogram |
+ // in this process. So need to clear IPC flag first. |
Ilya Sherman
2012/12/29 00:17:30
nit: "in this process. So need to clear IPC flag"
kaiwang
2013/01/08 00:51:40
Done.
|
+ DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag); |
+ *flags &= ~HistogramBase::kIPCSerializationSourceFlag; |
+ |
+ return true; |
+} |
+ |
+bool ValidateRangeChecksum(const HistogramBase* histogram, |
Ilya Sherman
2012/12/29 00:17:30
nit: Please pass by const-reference.
kaiwang
2013/01/08 00:51:40
Done.
|
+ uint32 range_checksum) { |
+ const Histogram* casted_histogram = |
+ static_cast<const Histogram*>(histogram); |
+ |
+ return casted_histogram->bucket_ranges()->checksum() == range_checksum; |
+} |
+ |
+} // namespace |
+ |
typedef HistogramBase::Count Count; |
typedef HistogramBase::Sample Sample; |
@@ -153,117 +201,6 @@ void Histogram::AddBoolean(bool value) { |
DCHECK(false); |
} |
-void Histogram::AddSamples(const HistogramSamples& samples) { |
- samples_->Add(samples); |
-} |
- |
-bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { |
- return samples_->AddFromPickle(iter); |
-} |
- |
-// static |
-string Histogram::SerializeHistogramInfo(const Histogram& histogram, |
- const HistogramSamples& snapshot) { |
- DCHECK(histogram.bucket_ranges()->HasValidChecksum()); |
Ilya Sherman
2012/12/29 00:17:30
What happened to this DCHECK?
kaiwang
2013/01/08 00:51:40
Added to Histogram::SerializeInfoImpl
|
- |
- Pickle pickle; |
- pickle.WriteString(histogram.histogram_name()); |
- pickle.WriteInt(histogram.declared_min()); |
- pickle.WriteInt(histogram.declared_max()); |
- pickle.WriteUInt64(histogram.bucket_count()); |
- pickle.WriteUInt32(histogram.bucket_ranges()->checksum()); |
- pickle.WriteInt(histogram.GetHistogramType()); |
- pickle.WriteInt(histogram.flags()); |
- |
- histogram.SerializeRanges(&pickle); |
- |
- snapshot.Serialize(&pickle); |
- |
- return string(static_cast<const char*>(pickle.data()), pickle.size()); |
-} |
- |
-// static |
-bool Histogram::DeserializeHistogramInfo(const string& histogram_info) { |
- if (histogram_info.empty()) { |
- return false; |
- } |
- |
- Pickle pickle(histogram_info.data(), |
- static_cast<int>(histogram_info.size())); |
- string histogram_name; |
- int declared_min; |
- int declared_max; |
- uint64 bucket_count; |
- uint32 range_checksum; |
- int histogram_type; |
- int pickle_flags; |
- |
- PickleIterator iter(pickle); |
- if (!iter.ReadString(&histogram_name) || |
- !iter.ReadInt(&declared_min) || |
- !iter.ReadInt(&declared_max) || |
- !iter.ReadUInt64(&bucket_count) || |
- !iter.ReadUInt32(&range_checksum) || |
- !iter.ReadInt(&histogram_type) || |
- !iter.ReadInt(&pickle_flags)) { |
- DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name; |
- return false; |
- } |
- |
- DCHECK(pickle_flags & kIPCSerializationSourceFlag); |
- // Since these fields may have come from an untrusted renderer, do additional |
- // checks above and beyond those in Histogram::Initialize() |
- if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min || |
- INT_MAX / sizeof(Count) <= bucket_count || bucket_count < 2) { |
- DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name; |
- return false; |
- } |
- |
- Flags flags = static_cast<Flags>(pickle_flags & ~kIPCSerializationSourceFlag); |
- |
- Histogram* render_histogram(NULL); |
- |
- if (histogram_type == HISTOGRAM) { |
- render_histogram = Histogram::FactoryGet( |
- histogram_name, declared_min, declared_max, bucket_count, flags); |
- } else if (histogram_type == LINEAR_HISTOGRAM) { |
- render_histogram = LinearHistogram::FactoryGet( |
- histogram_name, declared_min, declared_max, bucket_count, flags); |
- } else if (histogram_type == BOOLEAN_HISTOGRAM) { |
- render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags); |
- } else if (histogram_type == CUSTOM_HISTOGRAM) { |
- vector<Sample> sample_ranges(bucket_count); |
- if (!CustomHistogram::DeserializeRanges(&iter, &sample_ranges)) { |
- DLOG(ERROR) << "Pickle error decoding ranges: " << histogram_name; |
- return false; |
- } |
- render_histogram = |
- CustomHistogram::FactoryGet(histogram_name, sample_ranges, flags); |
- } else { |
- DLOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: " |
- << histogram_type; |
- return false; |
- } |
- |
- DCHECK_EQ(render_histogram->declared_min(), declared_min); |
- DCHECK_EQ(render_histogram->declared_max(), declared_max); |
- DCHECK_EQ(render_histogram->bucket_count(), bucket_count); |
- DCHECK_EQ(render_histogram->GetHistogramType(), histogram_type); |
- |
- if (render_histogram->bucket_ranges()->checksum() != range_checksum) { |
- return false; |
- } |
- |
- if (render_histogram->flags() & kIPCSerializationSourceFlag) { |
- DVLOG(1) << "Single process mode, histogram observed and not copied: " |
- << histogram_name; |
- return true; |
- } |
- |
- DCHECK_EQ(flags & render_histogram->flags(), flags); |
Ilya Sherman
2012/12/29 00:17:30
nit: What happened to this DCHECK?
kaiwang
2013/01/08 00:51:40
Actually I really don't understand what's this DCH
Ilya Sherman
2013/01/08 22:31:53
I'm also not sure; perhaps Jim can comment? I thi
|
- return render_histogram->AddSamplesFromPickle(&iter); |
-} |
- |
// static |
const int Histogram::kCommonRaceBasedCountMismatch = 5; |
@@ -363,6 +300,14 @@ scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { |
return SnapshotSampleVector().PassAs<HistogramSamples>(); |
} |
+void Histogram::AddSamples(const HistogramSamples& samples) { |
+ samples_->Add(samples); |
+} |
+ |
+bool Histogram::AddSamplesFromPickle(PickleIterator* iter) { |
+ return samples_->AddFromPickle(iter); |
+} |
+ |
// The following methods provide a graphical histogram display. |
void Histogram::WriteHTMLGraph(string* output) const { |
// TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. |
@@ -375,6 +320,18 @@ void Histogram::WriteAscii(string* output) const { |
WriteAsciiImpl(true, "\n", output); |
} |
+bool Histogram::SerializeInfoImpl(Pickle* pickle) const { |
+ if (pickle->WriteString(histogram_name()) && |
+ pickle->WriteInt(flags()) && |
Ilya Sherman
2012/12/29 00:17:30
I'm curious, why did you move flags to be written
kaiwang
2013/01/08 00:51:40
histogram_name and flags are fields from Histogram
|
+ pickle->WriteInt(declared_min()) && |
+ pickle->WriteInt(declared_max()) && |
+ pickle->WriteUInt64(bucket_count()) && |
+ pickle->WriteUInt32(bucket_ranges()->checksum())) { |
+ return true; |
+ } |
+ return false; |
Ilya Sherman
2012/12/29 00:17:30
Optional nit: IMO it's tidier to write this as
re
kaiwang
2013/01/08 00:51:40
Done.
|
+} |
+ |
Histogram::Histogram(const string& name, |
Sample minimum, |
Sample maximum, |
@@ -397,10 +354,6 @@ Histogram::~Histogram() { |
} |
} |
-bool Histogram::SerializeRanges(Pickle* pickle) const { |
- return true; |
-} |
- |
bool Histogram::PrintEmptyBucket(size_t index) const { |
return true; |
} |
@@ -431,6 +384,31 @@ const string Histogram::GetAsciiBucketRange(size_t i) const { |
//------------------------------------------------------------------------------ |
// Private methods |
+// static |
+HistogramBase* Histogram::DeserializeHistogramInfo(PickleIterator* iter) { |
+ string histogram_name; |
+ int flags; |
+ int declared_min; |
+ int declared_max; |
+ uint64 bucket_count; |
+ uint32 range_checksum; |
+ |
+ if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
+ &declared_max, &bucket_count, &range_checksum)) { |
+ return NULL; |
+ } |
+ |
+ // Find or create the local version of the histogram in this process. |
+ HistogramBase* histogram = Histogram::FactoryGet( |
+ histogram_name, declared_min, declared_max, bucket_count, flags); |
+ |
+ if (!ValidateRangeChecksum(histogram, range_checksum)) { |
+ // The serialized histogram might be corrupted. |
+ return NULL; |
+ } |
+ return histogram; |
+} |
+ |
scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { |
scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); |
samples->Add(*samples_); |
@@ -710,6 +688,29 @@ void LinearHistogram::InitializeBucketRanges(Sample minimum, |
ranges->ResetChecksum(); |
} |
+// static |
+HistogramBase* LinearHistogram::DeserializeHistogramInfo(PickleIterator* iter) { |
+ string histogram_name; |
+ int flags; |
+ int declared_min; |
+ int declared_max; |
+ uint64 bucket_count; |
+ uint32 range_checksum; |
+ |
+ if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
+ &declared_max, &bucket_count, &range_checksum)) { |
+ return NULL; |
+ } |
+ |
+ HistogramBase* histogram = LinearHistogram::FactoryGet( |
+ histogram_name, declared_min, declared_max, bucket_count, flags); |
+ if (!ValidateRangeChecksum(histogram, range_checksum)) { |
+ // The serialized histogram might be corrupted. |
+ return NULL; |
+ } |
+ return histogram; |
+} |
+ |
//------------------------------------------------------------------------------ |
// This section provides implementation for BooleanHistogram. |
//------------------------------------------------------------------------------ |
@@ -750,6 +751,29 @@ BooleanHistogram::BooleanHistogram(const string& name, |
const BucketRanges* ranges) |
: LinearHistogram(name, 1, 2, 3, ranges) {} |
+HistogramBase* BooleanHistogram::DeserializeHistogramInfo( |
+ PickleIterator* iter) { |
+ string histogram_name; |
+ int flags; |
+ int declared_min; |
+ int declared_max; |
+ uint64 bucket_count; |
+ uint32 range_checksum; |
+ |
+ if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
+ &declared_max, &bucket_count, &range_checksum)) { |
+ return NULL; |
+ } |
+ |
+ HistogramBase* histogram = BooleanHistogram::FactoryGet( |
+ histogram_name, flags); |
+ if (!ValidateRangeChecksum(histogram, range_checksum)) { |
+ // The serialized histogram might be corrupted. |
+ return NULL; |
+ } |
+ return histogram; |
+} |
Ilya Sherman
2012/12/29 00:17:30
It would be good to share more of this code, rathe
kaiwang
2013/01/08 00:51:40
I think the good thing of current code is it distr
Ilya Sherman
2013/01/08 22:31:53
I'm not convinced that this is true: HistogramBase
|
+ |
//------------------------------------------------------------------------------ |
// CustomHistogram: |
//------------------------------------------------------------------------------ |
@@ -809,26 +833,52 @@ CustomHistogram::CustomHistogram(const string& name, |
ranges->size() - 1, |
ranges) {} |
-bool CustomHistogram::SerializeRanges(Pickle* pickle) const { |
- for (size_t i = 0; i < bucket_ranges()->size(); ++i) { |
+bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const { |
+ if (!Histogram::SerializeInfoImpl(pickle)) |
+ return false; |
+ |
+ // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't |
+ // write them. |
+ for (size_t i = 1; i < bucket_ranges()->size() - 1; ++i) { |
if (!pickle->WriteInt(bucket_ranges()->range(i))) |
return false; |
} |
return true; |
} |
+double CustomHistogram::GetBucketSize(Count current, size_t i) const { |
+ return 1; |
+} |
+ |
// static |
-bool CustomHistogram::DeserializeRanges( |
- PickleIterator* iter, vector<Sample>* ranges) { |
- for (size_t i = 0; i < ranges->size(); ++i) { |
- if (!iter->ReadInt(&(*ranges)[i])) |
- return false; |
+HistogramBase* CustomHistogram::DeserializeHistogramInfo(PickleIterator* iter) { |
+ string histogram_name; |
+ int flags; |
+ int declared_min; |
+ int declared_max; |
+ uint64 bucket_count; |
+ uint32 range_checksum; |
+ |
+ if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min, |
+ &declared_max, &bucket_count, &range_checksum)) { |
+ return NULL; |
} |
- return true; |
-} |
-double CustomHistogram::GetBucketSize(Count current, size_t i) const { |
- return 1; |
+ // First and last ranges are not serialized. |
+ vector<Sample> sample_ranges(bucket_count - 1); |
+ |
+ for (size_t i = 0; i < sample_ranges.size(); ++i) { |
+ if (!iter->ReadInt(&sample_ranges[i])) |
+ return NULL; |
+ } |
+ |
+ HistogramBase* histogram = CustomHistogram::FactoryGet( |
+ histogram_name, sample_ranges, flags); |
+ if (!ValidateRangeChecksum(histogram, range_checksum)) { |
+ // The serialized histogram might be corrupted. |
+ return NULL; |
+ } |
+ return histogram; |
} |
// static |