Index: base/metrics/histogram.h |
=================================================================== |
--- base/metrics/histogram.h (revision 64486) |
+++ base/metrics/histogram.h (working copy) |
@@ -36,6 +36,7 @@ |
#include <string> |
#include <vector> |
+#include "base/gtest_prod_util.h" |
#include "base/ref_counted.h" |
#include "base/logging.h" |
#include "base/time.h" |
@@ -243,8 +244,8 @@ |
typedef std::vector<Count> Counts; |
typedef std::vector<Sample> Ranges; |
- /* These enums are meant to facilitate deserialization of renderer histograms |
- into the browser. */ |
+ // These enums are used to facilitate deserialization of renderer histograms |
+ // into the browser. |
enum ClassType { |
HISTOGRAM, |
LINEAR_HISTOGRAM, |
@@ -273,6 +274,16 @@ |
kHexRangePrintingFlag = 0x8000, // Fancy bucket-naming supported. |
}; |
+ enum Inconsistencies { |
+ NO_INCONSISTENCIES = 0x0, |
+ RANGE_CHECKSUM_ERROR = 0x1, |
+ BUCKET_ORDER_ERROR = 0x2, |
+ COUNT_HIGH_ERROR = 0x4, |
+ COUNT_LOW_ERROR = 0x8, |
+ |
+ NEVER_EXCEEDED_VALUE = 0x10 |
+ }; |
+ |
struct DescriptionPair { |
Sample sample; |
const char* description; // Null means end of a list of pairs. |
@@ -298,6 +309,7 @@ |
Count TotalCount() const; |
int64 sum() const { return sum_; } |
int64 square_sum() const { return square_sum_; } |
+ int64 redundant_count() const { return redundant_count_; } |
// Arithmetic manipulation of corresponding elements of the set. |
void Add(const SampleSet& other); |
@@ -315,7 +327,21 @@ |
// without shared memory at some point. |
int64 sum_; // sum of samples. |
int64 square_sum_; // sum of squares of samples. |
+ |
+ private: |
+ // Allow tests to corrupt our innards for testing purposes. |
+ FRIEND_TEST(HistogramTest, CorruptSampleCounts); |
+ |
+ // To help identify memory corruption, we reduntantly save the number of |
+ // samples we've accumulated into all of our buckets. We can compare this |
+ // count to the sum of the counts in all buckets, and detect problems. Note |
+ // that due to races in histogram accumulation (if a histogram is indeed |
+ // updated on several threads simultaneously), the tallies might mismatch, |
+ // and also the snapshotting code may asynchronously get a mismatch (though |
+ // generally either race based mismatch cause is VERY rare). |
+ int64 redundant_count_; |
}; |
+ |
//---------------------------------------------------------------------------- |
// minimum should start from 1. 0 is invalid as a minimum. 0 is an implicit |
// default underflow bucket. |
@@ -367,6 +393,13 @@ |
// browser process. |
static bool DeserializeHistogramInfo(const std::string& histogram_info); |
+ // Check to see if bucket ranges, counts and tallies in the snapshot are |
+ // consistent with the bucket ranges and checksums in our histogram. This can |
+ // produce a false-alarm if a race occurred in the reading of the data during |
+ // a SnapShot process, but should otherwise be false at all times (unless we |
+ // have memory over-writes, or DRAM failures). |
+ Inconsistencies FindCorruption(const SampleSet& snapshot) const; |
+ |
//---------------------------------------------------------------------------- |
// Accessors for factory constuction, serialization and testing. |
//---------------------------------------------------------------------------- |
@@ -375,6 +408,7 @@ |
Sample declared_min() const { return declared_min_; } |
Sample declared_max() const { return declared_max_; } |
virtual Sample ranges(size_t i) const { return ranges_[i];} |
+ Sample range_checksum() const { return range_checksum_; } |
virtual size_t bucket_count() const { return bucket_count_; } |
// Snapshot the current complete set of sample data. |
// Override with atomic/locked snapshot if needed. |
@@ -409,6 +443,9 @@ |
// Get normalized size, relative to the ranges_[i]. |
virtual double GetBucketSize(Count current, size_t i) const; |
+ // Recalculate range_checksum_. |
+ void ResetRangeChecksum(); |
+ |
// Return a string description of what goes in a given bucket. |
// Most commonly this is the numeric value, but in derived classes it may |
// be a name (or string description) given to the bucket. |
@@ -430,9 +467,18 @@ |
bool ValidateBucketRanges() const; |
private: |
+ // Allow tests to corrupt our innards for testing purposes. |
+ FRIEND_TEST(HistogramTest, CorruptBucketBounds); |
+ FRIEND_TEST(HistogramTest, CorruptSampleCounts); |
+ |
// Post constructor initialization. |
void Initialize(); |
+ // Return true iff the range_checksum_ matches current ranges_ vector. |
+ bool HasValidRangeChecksum() const; |
+ |
+ Sample CalculateRangeChecksum() const; |
+ |
//---------------------------------------------------------------------------- |
// Helpers for emitting Ascii graphic. Each method appends data to output. |
@@ -477,6 +523,11 @@ |
// The dimension of ranges_ is bucket_count + 1. |
Ranges ranges_; |
+ // For redundancy, we store the sum of all the sample ranges when ranges are |
+ // generated. If ever there is ever a difference, then the histogram must |
+ // have been corrupted. |
+ Sample range_checksum_; |
+ |
// Finally, provide the state that changes with the addition of each new |
// sample. |
SampleSet sample_; |
@@ -561,11 +612,11 @@ |
virtual ClassType histogram_type() const; |
static scoped_refptr<Histogram> FactoryGet(const std::string& name, |
- const std::vector<int>& custom_ranges, Flags flags); |
+ const std::vector<Sample>& custom_ranges, Flags flags); |
protected: |
CustomHistogram(const std::string& name, |
- const std::vector<int>& custom_ranges); |
+ const std::vector<Sample>& custom_ranges); |
// Initialize ranges_ mapping. |
virtual void InitializeBucketRange(); |
@@ -573,7 +624,7 @@ |
private: |
// Temporary pointer used during construction/initialization, and then NULLed. |
- const std::vector<int>* ranges_vector_; |
+ const std::vector<Sample>* ranges_vector_; |
DISALLOW_COPY_AND_ASSIGN(CustomHistogram); |
}; |