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

Side by Side Diff: base/metrics/histogram.cc

Issue 11682003: Serialize/Deserialize support in HistogramBase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 12 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Histogram is an object that aggregates statistics, and can summarize them in 5 // Histogram is an object that aggregates statistics, and can summarize them in
6 // various forms, including ASCII graphical, HTML, and numerically (as a 6 // various forms, including ASCII graphical, HTML, and numerically (as a
7 // vector of numbers corresponding to each of the aggregating buckets). 7 // vector of numbers corresponding to each of the aggregating buckets).
8 // See header file for details and examples. 8 // See header file for details and examples.
9 9
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 12 matching lines...) Expand all
23 #include "base/string_util.h" 23 #include "base/string_util.h"
24 #include "base/stringprintf.h" 24 #include "base/stringprintf.h"
25 #include "base/synchronization/lock.h" 25 #include "base/synchronization/lock.h"
26 #include "base/values.h" 26 #include "base/values.h"
27 27
28 using std::string; 28 using std::string;
29 using std::vector; 29 using std::vector;
30 30
31 namespace base { 31 namespace base {
32 32
33 namespace {
34
35 bool ReadHistogramArguments(PickleIterator* iter,
36 string* histogram_name,
37 int* flags,
38 int* declared_min,
39 int* declared_max,
40 uint64* bucket_count,
41 uint32* range_checksum) {
42 if (!iter->ReadString(histogram_name) ||
43 !iter->ReadInt(flags) ||
44 !iter->ReadInt(declared_min) ||
45 !iter->ReadInt(declared_max) ||
46 !iter->ReadUInt64(bucket_count) ||
47 !iter->ReadUInt32(range_checksum)) {
48 DLOG(ERROR) << "Pickle error decoding Histogram: " << *histogram_name;
49 return false;
50 }
51
52 // Since these fields may have come from an untrusted renderer, do additional
53 // checks above and beyond those in Histogram::Initialize()
54 if (*declared_max <= 0 ||
55 *declared_min <= 0 ||
56 *declared_max < *declared_min ||
57 INT_MAX / sizeof(HistogramBase::Count) <= *bucket_count ||
58 *bucket_count < 2) {
59 DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name;
60 return false;
61 }
62
63 // We use the arguments to find or create the local version of the histogram
64 // 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.
65 DCHECK(*flags & HistogramBase::kIPCSerializationSourceFlag);
66 *flags &= ~HistogramBase::kIPCSerializationSourceFlag;
67
68 return true;
69 }
70
71 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.
72 uint32 range_checksum) {
73 const Histogram* casted_histogram =
74 static_cast<const Histogram*>(histogram);
75
76 return casted_histogram->bucket_ranges()->checksum() == range_checksum;
77 }
78
79 } // namespace
80
33 typedef HistogramBase::Count Count; 81 typedef HistogramBase::Count Count;
34 typedef HistogramBase::Sample Sample; 82 typedef HistogramBase::Sample Sample;
35 83
36 // static 84 // static
37 const size_t Histogram::kBucketCount_MAX = 16384u; 85 const size_t Histogram::kBucketCount_MAX = 16384u;
38 86
39 // TODO(rtenneti): delete this code after debugging. 87 // TODO(rtenneti): delete this code after debugging.
40 void CheckCorruption(const Histogram& histogram, bool new_histogram) { 88 void CheckCorruption(const Histogram& histogram, bool new_histogram) {
41 const std::string& histogram_name = histogram.histogram_name(); 89 const std::string& histogram_name = histogram.histogram_name();
42 char histogram_name_buf[128]; 90 char histogram_name_buf[128];
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 ranges->set_range(bucket_index, current); 194 ranges->set_range(bucket_index, current);
147 } 195 }
148 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); 196 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX);
149 ranges->ResetChecksum(); 197 ranges->ResetChecksum();
150 } 198 }
151 199
152 void Histogram::AddBoolean(bool value) { 200 void Histogram::AddBoolean(bool value) {
153 DCHECK(false); 201 DCHECK(false);
154 } 202 }
155 203
156 void Histogram::AddSamples(const HistogramSamples& samples) {
157 samples_->Add(samples);
158 }
159
160 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) {
161 return samples_->AddFromPickle(iter);
162 }
163
164 // static
165 string Histogram::SerializeHistogramInfo(const Histogram& histogram,
166 const HistogramSamples& snapshot) {
167 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
168
169 Pickle pickle;
170 pickle.WriteString(histogram.histogram_name());
171 pickle.WriteInt(histogram.declared_min());
172 pickle.WriteInt(histogram.declared_max());
173 pickle.WriteUInt64(histogram.bucket_count());
174 pickle.WriteUInt32(histogram.bucket_ranges()->checksum());
175 pickle.WriteInt(histogram.GetHistogramType());
176 pickle.WriteInt(histogram.flags());
177
178 histogram.SerializeRanges(&pickle);
179
180 snapshot.Serialize(&pickle);
181
182 return string(static_cast<const char*>(pickle.data()), pickle.size());
183 }
184
185 // static
186 bool Histogram::DeserializeHistogramInfo(const string& histogram_info) {
187 if (histogram_info.empty()) {
188 return false;
189 }
190
191 Pickle pickle(histogram_info.data(),
192 static_cast<int>(histogram_info.size()));
193 string histogram_name;
194 int declared_min;
195 int declared_max;
196 uint64 bucket_count;
197 uint32 range_checksum;
198 int histogram_type;
199 int pickle_flags;
200
201 PickleIterator iter(pickle);
202 if (!iter.ReadString(&histogram_name) ||
203 !iter.ReadInt(&declared_min) ||
204 !iter.ReadInt(&declared_max) ||
205 !iter.ReadUInt64(&bucket_count) ||
206 !iter.ReadUInt32(&range_checksum) ||
207 !iter.ReadInt(&histogram_type) ||
208 !iter.ReadInt(&pickle_flags)) {
209 DLOG(ERROR) << "Pickle error decoding Histogram: " << histogram_name;
210 return false;
211 }
212
213 DCHECK(pickle_flags & kIPCSerializationSourceFlag);
214 // Since these fields may have come from an untrusted renderer, do additional
215 // checks above and beyond those in Histogram::Initialize()
216 if (declared_max <= 0 || declared_min <= 0 || declared_max < declared_min ||
217 INT_MAX / sizeof(Count) <= bucket_count || bucket_count < 2) {
218 DLOG(ERROR) << "Values error decoding Histogram: " << histogram_name;
219 return false;
220 }
221
222 Flags flags = static_cast<Flags>(pickle_flags & ~kIPCSerializationSourceFlag);
223
224 Histogram* render_histogram(NULL);
225
226 if (histogram_type == HISTOGRAM) {
227 render_histogram = Histogram::FactoryGet(
228 histogram_name, declared_min, declared_max, bucket_count, flags);
229 } else if (histogram_type == LINEAR_HISTOGRAM) {
230 render_histogram = LinearHistogram::FactoryGet(
231 histogram_name, declared_min, declared_max, bucket_count, flags);
232 } else if (histogram_type == BOOLEAN_HISTOGRAM) {
233 render_histogram = BooleanHistogram::FactoryGet(histogram_name, flags);
234 } else if (histogram_type == CUSTOM_HISTOGRAM) {
235 vector<Sample> sample_ranges(bucket_count);
236 if (!CustomHistogram::DeserializeRanges(&iter, &sample_ranges)) {
237 DLOG(ERROR) << "Pickle error decoding ranges: " << histogram_name;
238 return false;
239 }
240 render_histogram =
241 CustomHistogram::FactoryGet(histogram_name, sample_ranges, flags);
242 } else {
243 DLOG(ERROR) << "Error Deserializing Histogram Unknown histogram_type: "
244 << histogram_type;
245 return false;
246 }
247
248 DCHECK_EQ(render_histogram->declared_min(), declared_min);
249 DCHECK_EQ(render_histogram->declared_max(), declared_max);
250 DCHECK_EQ(render_histogram->bucket_count(), bucket_count);
251 DCHECK_EQ(render_histogram->GetHistogramType(), histogram_type);
252
253 if (render_histogram->bucket_ranges()->checksum() != range_checksum) {
254 return false;
255 }
256
257 if (render_histogram->flags() & kIPCSerializationSourceFlag) {
258 DVLOG(1) << "Single process mode, histogram observed and not copied: "
259 << histogram_name;
260 return true;
261 }
262
263 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
264 return render_histogram->AddSamplesFromPickle(&iter);
265 }
266
267 // static 204 // static
268 const int Histogram::kCommonRaceBasedCountMismatch = 5; 205 const int Histogram::kCommonRaceBasedCountMismatch = 5;
269 206
270 Histogram::Inconsistencies Histogram::FindCorruption( 207 Histogram::Inconsistencies Histogram::FindCorruption(
271 const HistogramSamples& samples) const { 208 const HistogramSamples& samples) const {
272 int inconsistencies = NO_INCONSISTENCIES; 209 int inconsistencies = NO_INCONSISTENCIES;
273 Sample previous_range = -1; // Bottom range is always 0. 210 Sample previous_range = -1; // Bottom range is always 0.
274 for (size_t index = 0; index < bucket_count(); ++index) { 211 for (size_t index = 0; index < bucket_count(); ++index) {
275 int new_range = ranges(index); 212 int new_range = ranges(index);
276 if (previous_range >= new_range) 213 if (previous_range >= new_range)
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 value = kSampleType_MAX - 1; 293 value = kSampleType_MAX - 1;
357 if (value < 0) 294 if (value < 0)
358 value = 0; 295 value = 0;
359 samples_->Accumulate(value, 1); 296 samples_->Accumulate(value, 1);
360 } 297 }
361 298
362 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const { 299 scoped_ptr<HistogramSamples> Histogram::SnapshotSamples() const {
363 return SnapshotSampleVector().PassAs<HistogramSamples>(); 300 return SnapshotSampleVector().PassAs<HistogramSamples>();
364 } 301 }
365 302
303 void Histogram::AddSamples(const HistogramSamples& samples) {
304 samples_->Add(samples);
305 }
306
307 bool Histogram::AddSamplesFromPickle(PickleIterator* iter) {
308 return samples_->AddFromPickle(iter);
309 }
310
366 // The following methods provide a graphical histogram display. 311 // The following methods provide a graphical histogram display.
367 void Histogram::WriteHTMLGraph(string* output) const { 312 void Histogram::WriteHTMLGraph(string* output) const {
368 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc. 313 // TBD(jar) Write a nice HTML bar chart, with divs an mouse-overs etc.
369 output->append("<PRE>"); 314 output->append("<PRE>");
370 WriteAsciiImpl(true, "<br>", output); 315 WriteAsciiImpl(true, "<br>", output);
371 output->append("</PRE>"); 316 output->append("</PRE>");
372 } 317 }
373 318
374 void Histogram::WriteAscii(string* output) const { 319 void Histogram::WriteAscii(string* output) const {
375 WriteAsciiImpl(true, "\n", output); 320 WriteAsciiImpl(true, "\n", output);
376 } 321 }
377 322
323 bool Histogram::SerializeInfoImpl(Pickle* pickle) const {
324 if (pickle->WriteString(histogram_name()) &&
325 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
326 pickle->WriteInt(declared_min()) &&
327 pickle->WriteInt(declared_max()) &&
328 pickle->WriteUInt64(bucket_count()) &&
329 pickle->WriteUInt32(bucket_ranges()->checksum())) {
330 return true;
331 }
332 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.
333 }
334
378 Histogram::Histogram(const string& name, 335 Histogram::Histogram(const string& name,
379 Sample minimum, 336 Sample minimum,
380 Sample maximum, 337 Sample maximum,
381 size_t bucket_count, 338 size_t bucket_count,
382 const BucketRanges* ranges) 339 const BucketRanges* ranges)
383 : HistogramBase(name), 340 : HistogramBase(name),
384 bucket_ranges_(ranges), 341 bucket_ranges_(ranges),
385 declared_min_(minimum), 342 declared_min_(minimum),
386 declared_max_(maximum), 343 declared_max_(maximum),
387 bucket_count_(bucket_count) { 344 bucket_count_(bucket_count) {
388 if (ranges) 345 if (ranges)
389 samples_.reset(new SampleVector(ranges)); 346 samples_.reset(new SampleVector(ranges));
390 } 347 }
391 348
392 Histogram::~Histogram() { 349 Histogram::~Histogram() {
393 if (StatisticsRecorder::dump_on_exit()) { 350 if (StatisticsRecorder::dump_on_exit()) {
394 string output; 351 string output;
395 WriteAsciiImpl(true, "\n", &output); 352 WriteAsciiImpl(true, "\n", &output);
396 DLOG(INFO) << output; 353 DLOG(INFO) << output;
397 } 354 }
398 } 355 }
399 356
400 bool Histogram::SerializeRanges(Pickle* pickle) const {
401 return true;
402 }
403
404 bool Histogram::PrintEmptyBucket(size_t index) const { 357 bool Histogram::PrintEmptyBucket(size_t index) const {
405 return true; 358 return true;
406 } 359 }
407 360
408 // Use the actual bucket widths (like a linear histogram) until the widths get 361 // Use the actual bucket widths (like a linear histogram) until the widths get
409 // over some transition value, and then use that transition width. Exponentials 362 // over some transition value, and then use that transition width. Exponentials
410 // get so big so fast (and we don't expect to see a lot of entries in the large 363 // get so big so fast (and we don't expect to see a lot of entries in the large
411 // buckets), so we need this to make it possible to see what is going on and 364 // buckets), so we need this to make it possible to see what is going on and
412 // not have 0-graphical-height buckets. 365 // not have 0-graphical-height buckets.
413 double Histogram::GetBucketSize(Count current, size_t i) const { 366 double Histogram::GetBucketSize(Count current, size_t i) const {
(...skipping 10 matching lines...) Expand all
424 if (kHexRangePrintingFlag & flags()) 377 if (kHexRangePrintingFlag & flags())
425 StringAppendF(&result, "%#x", ranges(i)); 378 StringAppendF(&result, "%#x", ranges(i));
426 else 379 else
427 StringAppendF(&result, "%d", ranges(i)); 380 StringAppendF(&result, "%d", ranges(i));
428 return result; 381 return result;
429 } 382 }
430 383
431 //------------------------------------------------------------------------------ 384 //------------------------------------------------------------------------------
432 // Private methods 385 // Private methods
433 386
387 // static
388 HistogramBase* Histogram::DeserializeHistogramInfo(PickleIterator* iter) {
389 string histogram_name;
390 int flags;
391 int declared_min;
392 int declared_max;
393 uint64 bucket_count;
394 uint32 range_checksum;
395
396 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
397 &declared_max, &bucket_count, &range_checksum)) {
398 return NULL;
399 }
400
401 // Find or create the local version of the histogram in this process.
402 HistogramBase* histogram = Histogram::FactoryGet(
403 histogram_name, declared_min, declared_max, bucket_count, flags);
404
405 if (!ValidateRangeChecksum(histogram, range_checksum)) {
406 // The serialized histogram might be corrupted.
407 return NULL;
408 }
409 return histogram;
410 }
411
434 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const { 412 scoped_ptr<SampleVector> Histogram::SnapshotSampleVector() const {
435 scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges())); 413 scoped_ptr<SampleVector> samples(new SampleVector(bucket_ranges()));
436 samples->Add(*samples_); 414 samples->Add(*samples_);
437 return samples.Pass(); 415 return samples.Pass();
438 } 416 }
439 417
440 void Histogram::WriteAsciiImpl(bool graph_it, 418 void Histogram::WriteAsciiImpl(bool graph_it,
441 const string& newline, 419 const string& newline,
442 string* output) const { 420 string* output) const {
443 // Get local (stack) copies of all effectively volatile class data so that we 421 // Get local (stack) copies of all effectively volatile class data so that we
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 size_t i; 681 size_t i;
704 for (i = 1; i < bucket_count; ++i) { 682 for (i = 1; i < bucket_count; ++i) {
705 double linear_range = 683 double linear_range =
706 (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2); 684 (min * (bucket_count -1 - i) + max * (i - 1)) / (bucket_count - 2);
707 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5)); 685 ranges->set_range(i, static_cast<Sample>(linear_range + 0.5));
708 } 686 }
709 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX); 687 ranges->set_range(ranges->size() - 1, HistogramBase::kSampleType_MAX);
710 ranges->ResetChecksum(); 688 ranges->ResetChecksum();
711 } 689 }
712 690
691 // static
692 HistogramBase* LinearHistogram::DeserializeHistogramInfo(PickleIterator* iter) {
693 string histogram_name;
694 int flags;
695 int declared_min;
696 int declared_max;
697 uint64 bucket_count;
698 uint32 range_checksum;
699
700 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
701 &declared_max, &bucket_count, &range_checksum)) {
702 return NULL;
703 }
704
705 HistogramBase* histogram = LinearHistogram::FactoryGet(
706 histogram_name, declared_min, declared_max, bucket_count, flags);
707 if (!ValidateRangeChecksum(histogram, range_checksum)) {
708 // The serialized histogram might be corrupted.
709 return NULL;
710 }
711 return histogram;
712 }
713
713 //------------------------------------------------------------------------------ 714 //------------------------------------------------------------------------------
714 // This section provides implementation for BooleanHistogram. 715 // This section provides implementation for BooleanHistogram.
715 //------------------------------------------------------------------------------ 716 //------------------------------------------------------------------------------
716 717
717 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) { 718 Histogram* BooleanHistogram::FactoryGet(const string& name, int32 flags) {
718 Histogram* histogram = StatisticsRecorder::FindHistogram(name); 719 Histogram* histogram = StatisticsRecorder::FindHistogram(name);
719 if (!histogram) { 720 if (!histogram) {
720 // To avoid racy destruction at shutdown, the following will be leaked. 721 // To avoid racy destruction at shutdown, the following will be leaked.
721 BucketRanges* ranges = new BucketRanges(4); 722 BucketRanges* ranges = new BucketRanges(4);
722 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges); 723 LinearHistogram::InitializeBucketRanges(1, 2, 3, ranges);
(...skipping 20 matching lines...) Expand all
743 } 744 }
744 745
745 void BooleanHistogram::AddBoolean(bool value) { 746 void BooleanHistogram::AddBoolean(bool value) {
746 Add(value ? 1 : 0); 747 Add(value ? 1 : 0);
747 } 748 }
748 749
749 BooleanHistogram::BooleanHistogram(const string& name, 750 BooleanHistogram::BooleanHistogram(const string& name,
750 const BucketRanges* ranges) 751 const BucketRanges* ranges)
751 : LinearHistogram(name, 1, 2, 3, ranges) {} 752 : LinearHistogram(name, 1, 2, 3, ranges) {}
752 753
754 HistogramBase* BooleanHistogram::DeserializeHistogramInfo(
755 PickleIterator* iter) {
756 string histogram_name;
757 int flags;
758 int declared_min;
759 int declared_max;
760 uint64 bucket_count;
761 uint32 range_checksum;
762
763 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
764 &declared_max, &bucket_count, &range_checksum)) {
765 return NULL;
766 }
767
768 HistogramBase* histogram = BooleanHistogram::FactoryGet(
769 histogram_name, flags);
770 if (!ValidateRangeChecksum(histogram, range_checksum)) {
771 // The serialized histogram might be corrupted.
772 return NULL;
773 }
774 return histogram;
775 }
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
776
753 //------------------------------------------------------------------------------ 777 //------------------------------------------------------------------------------
754 // CustomHistogram: 778 // CustomHistogram:
755 //------------------------------------------------------------------------------ 779 //------------------------------------------------------------------------------
756 780
757 Histogram* CustomHistogram::FactoryGet(const string& name, 781 Histogram* CustomHistogram::FactoryGet(const string& name,
758 const vector<Sample>& custom_ranges, 782 const vector<Sample>& custom_ranges,
759 int32 flags) { 783 int32 flags) {
760 CHECK(ValidateCustomRanges(custom_ranges)); 784 CHECK(ValidateCustomRanges(custom_ranges));
761 785
762 Histogram* histogram = StatisticsRecorder::FindHistogram(name); 786 Histogram* histogram = StatisticsRecorder::FindHistogram(name);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 } 826 }
803 827
804 CustomHistogram::CustomHistogram(const string& name, 828 CustomHistogram::CustomHistogram(const string& name,
805 const BucketRanges* ranges) 829 const BucketRanges* ranges)
806 : Histogram(name, 830 : Histogram(name,
807 ranges->range(1), 831 ranges->range(1),
808 ranges->range(ranges->size() - 2), 832 ranges->range(ranges->size() - 2),
809 ranges->size() - 1, 833 ranges->size() - 1,
810 ranges) {} 834 ranges) {}
811 835
812 bool CustomHistogram::SerializeRanges(Pickle* pickle) const { 836 bool CustomHistogram::SerializeInfoImpl(Pickle* pickle) const {
813 for (size_t i = 0; i < bucket_ranges()->size(); ++i) { 837 if (!Histogram::SerializeInfoImpl(pickle))
838 return false;
839
840 // Serialize ranges. First and last ranges are alwasy 0 and INT_MAX, so don't
841 // write them.
842 for (size_t i = 1; i < bucket_ranges()->size() - 1; ++i) {
814 if (!pickle->WriteInt(bucket_ranges()->range(i))) 843 if (!pickle->WriteInt(bucket_ranges()->range(i)))
815 return false; 844 return false;
816 } 845 }
817 return true; 846 return true;
818 } 847 }
819 848
820 // static
821 bool CustomHistogram::DeserializeRanges(
822 PickleIterator* iter, vector<Sample>* ranges) {
823 for (size_t i = 0; i < ranges->size(); ++i) {
824 if (!iter->ReadInt(&(*ranges)[i]))
825 return false;
826 }
827 return true;
828 }
829
830 double CustomHistogram::GetBucketSize(Count current, size_t i) const { 849 double CustomHistogram::GetBucketSize(Count current, size_t i) const {
831 return 1; 850 return 1;
832 } 851 }
833 852
834 // static 853 // static
854 HistogramBase* CustomHistogram::DeserializeHistogramInfo(PickleIterator* iter) {
855 string histogram_name;
856 int flags;
857 int declared_min;
858 int declared_max;
859 uint64 bucket_count;
860 uint32 range_checksum;
861
862 if (!ReadHistogramArguments(iter, &histogram_name, &flags, &declared_min,
863 &declared_max, &bucket_count, &range_checksum)) {
864 return NULL;
865 }
866
867 // First and last ranges are not serialized.
868 vector<Sample> sample_ranges(bucket_count - 1);
869
870 for (size_t i = 0; i < sample_ranges.size(); ++i) {
871 if (!iter->ReadInt(&sample_ranges[i]))
872 return NULL;
873 }
874
875 HistogramBase* histogram = CustomHistogram::FactoryGet(
876 histogram_name, sample_ranges, flags);
877 if (!ValidateRangeChecksum(histogram, range_checksum)) {
878 // The serialized histogram might be corrupted.
879 return NULL;
880 }
881 return histogram;
882 }
883
884 // static
835 bool CustomHistogram::ValidateCustomRanges( 885 bool CustomHistogram::ValidateCustomRanges(
836 const vector<Sample>& custom_ranges) { 886 const vector<Sample>& custom_ranges) {
837 bool has_valid_range = false; 887 bool has_valid_range = false;
838 for (size_t i = 0; i < custom_ranges.size(); i++) { 888 for (size_t i = 0; i < custom_ranges.size(); i++) {
839 Sample sample = custom_ranges[i]; 889 Sample sample = custom_ranges[i];
840 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1) 890 if (sample < 0 || sample > HistogramBase::kSampleType_MAX - 1)
841 return false; 891 return false;
842 if (sample != 0) 892 if (sample != 0)
843 has_valid_range = true; 893 has_valid_range = true;
844 } 894 }
(...skipping 12 matching lines...) Expand all
857 907
858 BucketRanges* bucket_ranges = new BucketRanges(ranges.size()); 908 BucketRanges* bucket_ranges = new BucketRanges(ranges.size());
859 for (size_t i = 0; i < ranges.size(); i++) { 909 for (size_t i = 0; i < ranges.size(); i++) {
860 bucket_ranges->set_range(i, ranges[i]); 910 bucket_ranges->set_range(i, ranges[i]);
861 } 911 }
862 bucket_ranges->ResetChecksum(); 912 bucket_ranges->ResetChecksum();
863 return bucket_ranges; 913 return bucket_ranges;
864 } 914 }
865 915
866 } // namespace base 916 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698