Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Unified Diff: base/metrics/histogram.cc

Issue 11682003: Serialize/Deserialize support in HistogramBase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Some changes about deserializing Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/metrics/histogram.cc
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 795ea3a832387c4bbaa1ddb8d101c94b5166f806..4a5adafd775988f54c33e53fcb46315902f81888 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 we need to clear the IPC flag.
Ilya Sherman 2013/01/09 05:48:37 nit: "process. So" -> "process, so"
kaiwang 2013/01/10 23:02:24 Done.
+ DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag);
+ *flags &= ~HistogramBase::kIPCSerializationSourceFlag;
+
+ return true;
+}
+
+bool ValidateRangeChecksum(const HistogramBase& histogram,
+ 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());
-
- 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);
- 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,16 @@ void Histogram::WriteAscii(string* output) const {
WriteAsciiImpl(true, "\n", output);
}
+bool Histogram::SerializeInfoImpl(Pickle* pickle) const {
+ DCHECK(bucket_ranges()->HasValidChecksum());
+ return pickle->WriteString(histogram_name()) &&
+ pickle->WriteInt(flags()) &&
+ pickle->WriteInt(declared_min()) &&
+ pickle->WriteInt(declared_max()) &&
+ pickle->WriteUInt64(bucket_count()) &&
+ pickle->WriteUInt32(bucket_ranges()->checksum());
+}
+
Histogram::Histogram(const string& name,
Sample minimum,
Sample maximum,
@@ -397,10 +352,6 @@ Histogram::~Histogram() {
}
}
-bool Histogram::SerializeRanges(Pickle* pickle) const {
- return true;
-}
-
bool Histogram::PrintEmptyBucket(size_t index) const {
return true;
}
@@ -431,6 +382,31 @@ const string Histogram::GetAsciiBucketRange(size_t i) const {
//------------------------------------------------------------------------------
// Private methods
+// static
+HistogramBase* Histogram::DeserializeInfoImpl(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 +686,29 @@ void LinearHistogram::InitializeBucketRanges(Sample minimum,
ranges->ResetChecksum();
}
+// static
+HistogramBase* LinearHistogram::DeserializeInfoImpl(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 +749,28 @@ BooleanHistogram::BooleanHistogram(const string& name,
const BucketRanges* ranges)
: LinearHistogram(name, 1, 2, 3, ranges) {}
+HistogramBase* BooleanHistogram::DeserializeInfoImpl(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;
+}
+
//------------------------------------------------------------------------------
// CustomHistogram:
//------------------------------------------------------------------------------
@@ -809,26 +830,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::DeserializeInfoImpl(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

Powered by Google App Engine
This is Rietveld 408576698