xref: /aosp_15_r20/external/cronet/base/metrics/histogram_samples.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_METRICS_HISTOGRAM_SAMPLES_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_METRICS_HISTOGRAM_SAMPLES_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
9*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #include <limits>
12*6777b538SAndroid Build Coastguard Worker #include <memory>
13*6777b538SAndroid Build Coastguard Worker #include <string>
14*6777b538SAndroid Build Coastguard Worker #include <string_view>
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker #include "base/atomicops.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_base.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace base {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker class Pickle;
25*6777b538SAndroid Build Coastguard Worker class PickleIterator;
26*6777b538SAndroid Build Coastguard Worker class SampleCountIterator;
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker // HistogramSamples is a container storing all samples of a histogram. All
29*6777b538SAndroid Build Coastguard Worker // elements must be of a fixed width to ensure 32/64-bit interoperability.
30*6777b538SAndroid Build Coastguard Worker // If this structure changes, bump the version number for kTypeIdHistogram
31*6777b538SAndroid Build Coastguard Worker // in persistent_histogram_allocator.cc.
32*6777b538SAndroid Build Coastguard Worker //
33*6777b538SAndroid Build Coastguard Worker // Note that though these samples are individually consistent (through the use
34*6777b538SAndroid Build Coastguard Worker // of atomic operations on the counts), there is only "eventual consistency"
35*6777b538SAndroid Build Coastguard Worker // overall when multiple threads are accessing this data. That means that the
36*6777b538SAndroid Build Coastguard Worker // sum, redundant-count, etc. could be momentarily out-of-sync with the stored
37*6777b538SAndroid Build Coastguard Worker // counts but will settle to a consistent "steady state" once all threads have
38*6777b538SAndroid Build Coastguard Worker // exited this code.
39*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT HistogramSamples {
40*6777b538SAndroid Build Coastguard Worker  public:
41*6777b538SAndroid Build Coastguard Worker   // A single bucket and count. To fit within a single atomic on 32-bit build
42*6777b538SAndroid Build Coastguard Worker   // architectures, both |bucket| and |count| are limited in size to 16 bits.
43*6777b538SAndroid Build Coastguard Worker   // This limits the functionality somewhat but if an entry can't fit then
44*6777b538SAndroid Build Coastguard Worker   // the full array of samples can be allocated and used.
45*6777b538SAndroid Build Coastguard Worker   struct SingleSample {
46*6777b538SAndroid Build Coastguard Worker     uint16_t bucket;
47*6777b538SAndroid Build Coastguard Worker     uint16_t count;
48*6777b538SAndroid Build Coastguard Worker   };
49*6777b538SAndroid Build Coastguard Worker 
50*6777b538SAndroid Build Coastguard Worker   // A structure for managing an atomic single sample. Because this is generally
51*6777b538SAndroid Build Coastguard Worker   // used in association with other atomic values, the defined methods use
52*6777b538SAndroid Build Coastguard Worker   // acquire/release operations to guarantee ordering with outside values.
53*6777b538SAndroid Build Coastguard Worker   union BASE_EXPORT AtomicSingleSample {
AtomicSingleSample()54*6777b538SAndroid Build Coastguard Worker     AtomicSingleSample() : as_atomic(0) {}
AtomicSingleSample(subtle::Atomic32 rhs)55*6777b538SAndroid Build Coastguard Worker     explicit AtomicSingleSample(subtle::Atomic32 rhs) : as_atomic(rhs) {}
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker     // Returns the single sample in an atomic manner. This in an "acquire"
58*6777b538SAndroid Build Coastguard Worker     // load. The returned sample isn't shared and thus its fields can be safely
59*6777b538SAndroid Build Coastguard Worker     // accessed. If this object is disabled, this will return an empty sample
60*6777b538SAndroid Build Coastguard Worker     // (bucket count set to 0).
61*6777b538SAndroid Build Coastguard Worker     SingleSample Load() const;
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker     // Extracts and returns the single sample and changes it to |new_value| in
64*6777b538SAndroid Build Coastguard Worker     // an atomic manner. If this object is disabled, this will return an empty
65*6777b538SAndroid Build Coastguard Worker     // sample (bucket count set to 0).
66*6777b538SAndroid Build Coastguard Worker     SingleSample Extract(AtomicSingleSample new_value = AtomicSingleSample(0));
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker     // Like Extract() above, but also disables this object so that it will
69*6777b538SAndroid Build Coastguard Worker     // never accumulate another value. If this object is already disabled, this
70*6777b538SAndroid Build Coastguard Worker     // will return an empty sample (bucket count set to 0).
71*6777b538SAndroid Build Coastguard Worker     SingleSample ExtractAndDisable();
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker     // Adds a given count to the held bucket. If not possible, it returns false
74*6777b538SAndroid Build Coastguard Worker     // and leaves the parts unchanged. Once extracted/disabled, this always
75*6777b538SAndroid Build Coastguard Worker     // returns false. This in an "acquire/release" operation.
76*6777b538SAndroid Build Coastguard Worker     bool Accumulate(size_t bucket, HistogramBase::Count count);
77*6777b538SAndroid Build Coastguard Worker 
78*6777b538SAndroid Build Coastguard Worker     // Returns if the sample has been "disabled" (via Extract) and thus not
79*6777b538SAndroid Build Coastguard Worker     // allowed to accept further accumulation.
80*6777b538SAndroid Build Coastguard Worker     bool IsDisabled() const;
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker    private:
83*6777b538SAndroid Build Coastguard Worker     // union field: The actual sample bucket and count.
84*6777b538SAndroid Build Coastguard Worker     SingleSample as_parts;
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker     // union field: The sample as an atomic value. Atomic64 would provide
87*6777b538SAndroid Build Coastguard Worker     // more flexibility but isn't available on all builds. This can hold a
88*6777b538SAndroid Build Coastguard Worker     // special, internal "disabled" value indicating that it must not accept
89*6777b538SAndroid Build Coastguard Worker     // further accumulation.
90*6777b538SAndroid Build Coastguard Worker     subtle::Atomic32 as_atomic;
91*6777b538SAndroid Build Coastguard Worker   };
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   // A structure of information about the data, common to all sample containers.
94*6777b538SAndroid Build Coastguard Worker   // Because of how this is used in persistent memory, it must be a POD object
95*6777b538SAndroid Build Coastguard Worker   // that makes sense when initialized to all zeros.
96*6777b538SAndroid Build Coastguard Worker   struct Metadata {
97*6777b538SAndroid Build Coastguard Worker     // Expected size for 32/64-bit check.
98*6777b538SAndroid Build Coastguard Worker     static constexpr size_t kExpectedInstanceSize = 24;
99*6777b538SAndroid Build Coastguard Worker 
100*6777b538SAndroid Build Coastguard Worker     // Initialized when the sample-set is first created with a value provided
101*6777b538SAndroid Build Coastguard Worker     // by the caller. It is generally used to identify the sample-set across
102*6777b538SAndroid Build Coastguard Worker     // threads and processes, though not necessarily uniquely as it is possible
103*6777b538SAndroid Build Coastguard Worker     // to have multiple sample-sets representing subsets of the data.
104*6777b538SAndroid Build Coastguard Worker     uint64_t id;
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker     // The sum of all the entries, effectivly the sum(sample * count) for
107*6777b538SAndroid Build Coastguard Worker     // all samples. Despite being atomic, no guarantees are made on the
108*6777b538SAndroid Build Coastguard Worker     // accuracy of this value; there may be races during histogram
109*6777b538SAndroid Build Coastguard Worker     // accumulation and snapshotting that we choose to accept. It should
110*6777b538SAndroid Build Coastguard Worker     // be treated as approximate.
111*6777b538SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS
112*6777b538SAndroid Build Coastguard Worker     subtle::Atomic64 sum;
113*6777b538SAndroid Build Coastguard Worker #else
114*6777b538SAndroid Build Coastguard Worker     // 32-bit systems don't have atomic 64-bit operations. Use a basic type
115*6777b538SAndroid Build Coastguard Worker     // and don't worry about "shearing".
116*6777b538SAndroid Build Coastguard Worker     int64_t sum;
117*6777b538SAndroid Build Coastguard Worker #endif
118*6777b538SAndroid Build Coastguard Worker 
119*6777b538SAndroid Build Coastguard Worker     // A "redundant" count helps identify memory corruption. It redundantly
120*6777b538SAndroid Build Coastguard Worker     // stores the total number of samples accumulated in the histogram. We
121*6777b538SAndroid Build Coastguard Worker     // can compare this count to the sum of the counts (TotalCount() function),
122*6777b538SAndroid Build Coastguard Worker     // and detect problems. Note, depending on the implementation of different
123*6777b538SAndroid Build Coastguard Worker     // histogram types, there might be races during histogram accumulation
124*6777b538SAndroid Build Coastguard Worker     // and snapshotting that we choose to accept. In this case, the tallies
125*6777b538SAndroid Build Coastguard Worker     // might mismatch even when no memory corruption has happened.
126*6777b538SAndroid Build Coastguard Worker     HistogramBase::AtomicCount redundant_count{0};
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker     // A single histogram value and associated count. This allows histograms
129*6777b538SAndroid Build Coastguard Worker     // that typically report only a single value to not require full storage
130*6777b538SAndroid Build Coastguard Worker     // to be allocated.
131*6777b538SAndroid Build Coastguard Worker     AtomicSingleSample single_sample;  // 32 bits
132*6777b538SAndroid Build Coastguard Worker   };
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker   // Because structures held in persistent memory must be POD, there can be no
135*6777b538SAndroid Build Coastguard Worker   // default constructor to clear the fields. This derived class exists just
136*6777b538SAndroid Build Coastguard Worker   // to clear them when being allocated on the heap.
137*6777b538SAndroid Build Coastguard Worker   struct BASE_EXPORT LocalMetadata : Metadata {
138*6777b538SAndroid Build Coastguard Worker     LocalMetadata();
139*6777b538SAndroid Build Coastguard Worker   };
140*6777b538SAndroid Build Coastguard Worker 
141*6777b538SAndroid Build Coastguard Worker   HistogramSamples(const HistogramSamples&) = delete;
142*6777b538SAndroid Build Coastguard Worker   HistogramSamples& operator=(const HistogramSamples&) = delete;
143*6777b538SAndroid Build Coastguard Worker   virtual ~HistogramSamples();
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker   virtual void Accumulate(HistogramBase::Sample value,
146*6777b538SAndroid Build Coastguard Worker                           HistogramBase::Count count) = 0;
147*6777b538SAndroid Build Coastguard Worker   virtual HistogramBase::Count GetCount(HistogramBase::Sample value) const = 0;
148*6777b538SAndroid Build Coastguard Worker   virtual HistogramBase::Count TotalCount() const = 0;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   void Add(const HistogramSamples& other);
151*6777b538SAndroid Build Coastguard Worker 
152*6777b538SAndroid Build Coastguard Worker   // Add from serialized samples.
153*6777b538SAndroid Build Coastguard Worker   bool AddFromPickle(PickleIterator* iter);
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   void Subtract(const HistogramSamples& other);
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker   // Adds the samples from |other| while also resetting |other|'s sample counts
158*6777b538SAndroid Build Coastguard Worker   // to 0.
159*6777b538SAndroid Build Coastguard Worker   void Extract(HistogramSamples& other);
160*6777b538SAndroid Build Coastguard Worker 
161*6777b538SAndroid Build Coastguard Worker   // Returns an iterator to read the sample counts.
162*6777b538SAndroid Build Coastguard Worker   virtual std::unique_ptr<SampleCountIterator> Iterator() const = 0;
163*6777b538SAndroid Build Coastguard Worker 
164*6777b538SAndroid Build Coastguard Worker   // Returns a special kind of iterator that resets the underlying sample count
165*6777b538SAndroid Build Coastguard Worker   // to 0 when Get() is called. The returned iterator must be consumed
166*6777b538SAndroid Build Coastguard Worker   // completely before being destroyed, otherwise samples may be lost (this is
167*6777b538SAndroid Build Coastguard Worker   // enforced by a DCHECK in the destructor).
168*6777b538SAndroid Build Coastguard Worker   virtual std::unique_ptr<SampleCountIterator> ExtractingIterator() = 0;
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker   // Returns true if |this| is empty (has no samples, has a |sum| of zero, and
171*6777b538SAndroid Build Coastguard Worker   // has a |redundant_count| of zero), which is indicative that the caller does
172*6777b538SAndroid Build Coastguard Worker   // not need to process |this|.
173*6777b538SAndroid Build Coastguard Worker   // - Note 1: This should only be called when |this| is only manipulated on one
174*6777b538SAndroid Build Coastguard Worker   // thread at a time (e.g., the underlying data does not change on another
175*6777b538SAndroid Build Coastguard Worker   // thread). If this is not the case, then the returned value cannot be trusted
176*6777b538SAndroid Build Coastguard Worker   // at all.
177*6777b538SAndroid Build Coastguard Worker   // - Note 2: For performance reasons, this is not guaranteed to return the
178*6777b538SAndroid Build Coastguard Worker   // correct value. If false is returned, |this| may or may not be empty.
179*6777b538SAndroid Build Coastguard Worker   // However, if true is returned, then |this| is guaranteed to be empty (no
180*6777b538SAndroid Build Coastguard Worker   // false positives). Of course, this assumes that "Note 1" is respected.
181*6777b538SAndroid Build Coastguard Worker   //  - Note 3: The base implementation of this method checks for |sum| and
182*6777b538SAndroid Build Coastguard Worker   // |redundant_count|, but the child implementations should also check for
183*6777b538SAndroid Build Coastguard Worker   // samples.
184*6777b538SAndroid Build Coastguard Worker   virtual bool IsDefinitelyEmpty() const;
185*6777b538SAndroid Build Coastguard Worker 
186*6777b538SAndroid Build Coastguard Worker   void Serialize(Pickle* pickle) const;
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   // Returns ASCII representation of histograms data for histogram samples.
189*6777b538SAndroid Build Coastguard Worker   // The dictionary returned will be of the form
190*6777b538SAndroid Build Coastguard Worker   // {"name":<string>, "header":<string>, "body": <string>}
191*6777b538SAndroid Build Coastguard Worker   base::Value::Dict ToGraphDict(std::string_view histogram_name,
192*6777b538SAndroid Build Coastguard Worker                                 int32_t flags) const;
193*6777b538SAndroid Build Coastguard Worker 
194*6777b538SAndroid Build Coastguard Worker   // Accessor functions.
id()195*6777b538SAndroid Build Coastguard Worker   uint64_t id() const { return meta_->id; }
sum()196*6777b538SAndroid Build Coastguard Worker   int64_t sum() const {
197*6777b538SAndroid Build Coastguard Worker #ifdef ARCH_CPU_64_BITS
198*6777b538SAndroid Build Coastguard Worker     return subtle::NoBarrier_Load(&meta_->sum);
199*6777b538SAndroid Build Coastguard Worker #else
200*6777b538SAndroid Build Coastguard Worker     return meta_->sum;
201*6777b538SAndroid Build Coastguard Worker #endif
202*6777b538SAndroid Build Coastguard Worker   }
redundant_count()203*6777b538SAndroid Build Coastguard Worker   HistogramBase::Count redundant_count() const {
204*6777b538SAndroid Build Coastguard Worker     return subtle::NoBarrier_Load(&meta_->redundant_count);
205*6777b538SAndroid Build Coastguard Worker   }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker  protected:
208*6777b538SAndroid Build Coastguard Worker   enum NegativeSampleReason {
209*6777b538SAndroid Build Coastguard Worker     SAMPLES_HAVE_LOGGED_BUT_NOT_SAMPLE,
210*6777b538SAndroid Build Coastguard Worker     SAMPLES_SAMPLE_LESS_THAN_LOGGED,
211*6777b538SAndroid Build Coastguard Worker     SAMPLES_ADDED_NEGATIVE_COUNT,
212*6777b538SAndroid Build Coastguard Worker     SAMPLES_ADD_WENT_NEGATIVE,
213*6777b538SAndroid Build Coastguard Worker     SAMPLES_ADD_OVERFLOW,
214*6777b538SAndroid Build Coastguard Worker     SAMPLES_ACCUMULATE_NEGATIVE_COUNT,
215*6777b538SAndroid Build Coastguard Worker     SAMPLES_ACCUMULATE_WENT_NEGATIVE,
216*6777b538SAndroid Build Coastguard Worker     DEPRECATED_SAMPLES_ACCUMULATE_OVERFLOW,
217*6777b538SAndroid Build Coastguard Worker     SAMPLES_ACCUMULATE_OVERFLOW,
218*6777b538SAndroid Build Coastguard Worker     MAX_NEGATIVE_SAMPLE_REASONS
219*6777b538SAndroid Build Coastguard Worker   };
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker   HistogramSamples(uint64_t id, Metadata* meta);
222*6777b538SAndroid Build Coastguard Worker   HistogramSamples(uint64_t id, std::unique_ptr<Metadata> meta);
223*6777b538SAndroid Build Coastguard Worker 
224*6777b538SAndroid Build Coastguard Worker   // Based on |op| type, add or subtract sample counts data from the iterator.
225*6777b538SAndroid Build Coastguard Worker   enum Operator { ADD, SUBTRACT };
226*6777b538SAndroid Build Coastguard Worker   virtual bool AddSubtractImpl(SampleCountIterator* iter, Operator op) = 0;
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker   // Accumulates to the embedded single-sample field if possible. Returns true
229*6777b538SAndroid Build Coastguard Worker   // on success, false otherwise. Sum and redundant-count are also updated in
230*6777b538SAndroid Build Coastguard Worker   // the success case.
231*6777b538SAndroid Build Coastguard Worker   bool AccumulateSingleSample(HistogramBase::Sample value,
232*6777b538SAndroid Build Coastguard Worker                               HistogramBase::Count count,
233*6777b538SAndroid Build Coastguard Worker                               size_t bucket);
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker   // Atomically adjust the sum and redundant-count.
236*6777b538SAndroid Build Coastguard Worker   void IncreaseSumAndCount(int64_t sum, HistogramBase::Count count);
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker   // Record a negative-sample observation and the reason why.
239*6777b538SAndroid Build Coastguard Worker   void RecordNegativeSample(NegativeSampleReason reason,
240*6777b538SAndroid Build Coastguard Worker                             HistogramBase::Count increment);
241*6777b538SAndroid Build Coastguard Worker 
single_sample()242*6777b538SAndroid Build Coastguard Worker   AtomicSingleSample& single_sample() { return meta_->single_sample; }
single_sample()243*6777b538SAndroid Build Coastguard Worker   const AtomicSingleSample& single_sample() const {
244*6777b538SAndroid Build Coastguard Worker     return meta_->single_sample;
245*6777b538SAndroid Build Coastguard Worker   }
246*6777b538SAndroid Build Coastguard Worker 
247*6777b538SAndroid Build Coastguard Worker   // Produces an actual graph (set of blank vs non blank char's) for a bucket.
248*6777b538SAndroid Build Coastguard Worker   static void WriteAsciiBucketGraph(double x_count,
249*6777b538SAndroid Build Coastguard Worker                                     int line_length,
250*6777b538SAndroid Build Coastguard Worker                                     std::string* output);
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker   // Writes textual description of the bucket contents (relative to histogram).
253*6777b538SAndroid Build Coastguard Worker   // Output is the count in the buckets, as well as the percentage.
254*6777b538SAndroid Build Coastguard Worker   void WriteAsciiBucketValue(HistogramBase::Count current,
255*6777b538SAndroid Build Coastguard Worker                              double scaled_sum,
256*6777b538SAndroid Build Coastguard Worker                              std::string* output) const;
257*6777b538SAndroid Build Coastguard Worker 
258*6777b538SAndroid Build Coastguard Worker   // Gets a body for this histogram samples.
259*6777b538SAndroid Build Coastguard Worker   virtual std::string GetAsciiBody() const;
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker   // Gets a header message describing this histogram samples.
262*6777b538SAndroid Build Coastguard Worker   virtual std::string GetAsciiHeader(std::string_view histogram_name,
263*6777b538SAndroid Build Coastguard Worker                                      int32_t flags) const;
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker   // Returns a string description of what goes in a given bucket.
266*6777b538SAndroid Build Coastguard Worker   const std::string GetSimpleAsciiBucketRange(
267*6777b538SAndroid Build Coastguard Worker       HistogramBase::Sample sample) const;
268*6777b538SAndroid Build Coastguard Worker 
meta()269*6777b538SAndroid Build Coastguard Worker   Metadata* meta() { return meta_; }
270*6777b538SAndroid Build Coastguard Worker 
271*6777b538SAndroid Build Coastguard Worker  private:
272*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(HistogramSamplesTest, WriteAsciiBucketGraph);
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker   // Depending on derived class `meta_` can come from:
275*6777b538SAndroid Build Coastguard Worker   // - Local storage: Then `meta_owned_` is set and meta_ points to it.
276*6777b538SAndroid Build Coastguard Worker   // - External storage: Then `meta_owned_` is null, and `meta_` point toward an
277*6777b538SAndroid Build Coastguard Worker   //   external object. The callers guarantees the value will outlive this
278*6777b538SAndroid Build Coastguard Worker   //   instance.
279*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<Metadata> meta_owned_;
280*6777b538SAndroid Build Coastguard Worker   raw_ptr<Metadata> meta_;
281*6777b538SAndroid Build Coastguard Worker };
282*6777b538SAndroid Build Coastguard Worker 
283*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT SampleCountIterator {
284*6777b538SAndroid Build Coastguard Worker  public:
285*6777b538SAndroid Build Coastguard Worker   virtual ~SampleCountIterator();
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   virtual bool Done() const = 0;
288*6777b538SAndroid Build Coastguard Worker   virtual void Next() = 0;
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   // Get the sample and count at current position.
291*6777b538SAndroid Build Coastguard Worker   // Note: |max| is int64_t because histograms support logged values in the
292*6777b538SAndroid Build Coastguard Worker   // full int32_t range and bucket max is exclusive, so it needs to support
293*6777b538SAndroid Build Coastguard Worker   // values up to MAXINT32+1.
294*6777b538SAndroid Build Coastguard Worker   // Requires: !Done();
295*6777b538SAndroid Build Coastguard Worker   virtual void Get(HistogramBase::Sample* min,
296*6777b538SAndroid Build Coastguard Worker                    int64_t* max,
297*6777b538SAndroid Build Coastguard Worker                    HistogramBase::Count* count) = 0;
298*6777b538SAndroid Build Coastguard Worker   static_assert(std::numeric_limits<HistogramBase::Sample>::max() <
299*6777b538SAndroid Build Coastguard Worker                     std::numeric_limits<int64_t>::max(),
300*6777b538SAndroid Build Coastguard Worker                 "Get() |max| must be able to hold Histogram::Sample max + 1");
301*6777b538SAndroid Build Coastguard Worker 
302*6777b538SAndroid Build Coastguard Worker   // Get the index of current histogram bucket.
303*6777b538SAndroid Build Coastguard Worker   // For histograms that don't use predefined buckets, it returns false.
304*6777b538SAndroid Build Coastguard Worker   // Requires: !Done();
305*6777b538SAndroid Build Coastguard Worker   virtual bool GetBucketIndex(size_t* index) const;
306*6777b538SAndroid Build Coastguard Worker };
307*6777b538SAndroid Build Coastguard Worker 
308*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT SingleSampleIterator : public SampleCountIterator {
309*6777b538SAndroid Build Coastguard Worker  public:
310*6777b538SAndroid Build Coastguard Worker   SingleSampleIterator(HistogramBase::Sample min,
311*6777b538SAndroid Build Coastguard Worker                        int64_t max,
312*6777b538SAndroid Build Coastguard Worker                        HistogramBase::Count count,
313*6777b538SAndroid Build Coastguard Worker                        size_t bucket_index,
314*6777b538SAndroid Build Coastguard Worker                        bool value_was_extracted);
315*6777b538SAndroid Build Coastguard Worker   ~SingleSampleIterator() override;
316*6777b538SAndroid Build Coastguard Worker 
317*6777b538SAndroid Build Coastguard Worker   // SampleCountIterator:
318*6777b538SAndroid Build Coastguard Worker   bool Done() const override;
319*6777b538SAndroid Build Coastguard Worker   void Next() override;
320*6777b538SAndroid Build Coastguard Worker   void Get(HistogramBase::Sample* min,
321*6777b538SAndroid Build Coastguard Worker            int64_t* max,
322*6777b538SAndroid Build Coastguard Worker            HistogramBase::Count* count) override;
323*6777b538SAndroid Build Coastguard Worker 
324*6777b538SAndroid Build Coastguard Worker   // SampleVector uses predefined buckets so iterator can return bucket index.
325*6777b538SAndroid Build Coastguard Worker   bool GetBucketIndex(size_t* index) const override;
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker  private:
328*6777b538SAndroid Build Coastguard Worker   // Information about the single value to return.
329*6777b538SAndroid Build Coastguard Worker   const HistogramBase::Sample min_;
330*6777b538SAndroid Build Coastguard Worker   const int64_t max_;
331*6777b538SAndroid Build Coastguard Worker   const size_t bucket_index_;
332*6777b538SAndroid Build Coastguard Worker   HistogramBase::Count count_;
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker   // Whether the value that this iterator holds was extracted from the
335*6777b538SAndroid Build Coastguard Worker   // underlying data (i.e., reset to 0).
336*6777b538SAndroid Build Coastguard Worker   const bool value_was_extracted_;
337*6777b538SAndroid Build Coastguard Worker };
338*6777b538SAndroid Build Coastguard Worker 
339*6777b538SAndroid Build Coastguard Worker }  // namespace base
340*6777b538SAndroid Build Coastguard Worker 
341*6777b538SAndroid Build Coastguard Worker #endif  // BASE_METRICS_HISTOGRAM_SAMPLES_H_
342