#ifndef BASE_METRICS_SAMPLE_VECTOR_H_
#define BASE_METRICS_SAMPLE_VECTOR_H_
#include <stddef.h>
#include <stdint.h>
#include <atomic>
#include <memory>
#include <string>
#include <vector>
#include "base/base_export.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/bucket_ranges.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/persistent_memory_allocator.h"
namespace base {
class BucketRanges;
class BASE_EXPORT SampleVectorBase : public HistogramSamples {
public:
SampleVectorBase(const SampleVectorBase&) = delete;
SampleVectorBase& operator=(const SampleVectorBase&) = delete;
~SampleVectorBase() override;
void Accumulate(HistogramBase::Sample value,
HistogramBase::Count count) override;
HistogramBase::Count GetCount(HistogramBase::Sample value) const override;
HistogramBase::Count TotalCount() const override;
std::unique_ptr<SampleCountIterator> Iterator() const override;
std::unique_ptr<SampleCountIterator> ExtractingIterator() override;
HistogramBase::Count GetCountAtIndex(size_t bucket_index) const;
const BucketRanges* bucket_ranges() const { return bucket_ranges_; }
protected:
SampleVectorBase(uint64_t id,
Metadata* meta,
const BucketRanges* bucket_ranges);
SampleVectorBase(uint64_t id,
std::unique_ptr<Metadata> meta,
const BucketRanges* bucket_ranges);
bool AddSubtractImpl(
SampleCountIterator* iter,
HistogramSamples::Operator op) override;
virtual size_t GetBucketIndex(HistogramBase::Sample value) const;
void MoveSingleSampleToCounts();
void MountCountsStorageAndMoveSingleSample();
virtual bool MountExistingCountsStorage() const = 0;
virtual HistogramBase::Count* CreateCountsStorageWhileLocked() = 0;
HistogramBase::AtomicCount* counts() {
return counts_.load(std::memory_order_acquire);
}
const HistogramBase::AtomicCount* counts() const {
return counts_.load(std::memory_order_acquire);
}
void set_counts(HistogramBase::AtomicCount* counts) const {
counts_.store(counts, std::memory_order_release);
}
size_t counts_size() const { return bucket_ranges_->bucket_count(); }
private:
friend class SampleVectorTest;
FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts);
FRIEND_TEST_ALL_PREFIXES(SharedHistogramTest, CorruptSampleCounts);
mutable std::atomic<HistogramBase::AtomicCount*> counts_{nullptr};
const raw_ptr<const BucketRanges> bucket_ranges_;
};
class BASE_EXPORT SampleVector : public SampleVectorBase {
public:
explicit SampleVector(const BucketRanges* bucket_ranges);
SampleVector(uint64_t id, const BucketRanges* bucket_ranges);
SampleVector(const SampleVector&) = delete;
SampleVector& operator=(const SampleVector&) = delete;
~SampleVector() override;
private:
FRIEND_TEST_ALL_PREFIXES(SampleVectorTest, GetPeakBucketSize);
std::string GetAsciiBody() const override;
std::string GetAsciiHeader(StringPiece histogram_name,
int32_t flags) const override;
bool MountExistingCountsStorage() const override;
HistogramBase::Count* CreateCountsStorageWhileLocked() override;
void WriteAsciiBucketContext(int64_t past,
HistogramBase::Count current,
int64_t remaining,
uint32_t current_bucket_index,
std::string* output) const;
double GetPeakBucketSize() const;
size_t bucket_count() const { return bucket_ranges()->bucket_count(); }
mutable std::vector<HistogramBase::AtomicCount> local_counts_;
};
class BASE_EXPORT PersistentSampleVector : public SampleVectorBase {
public:
PersistentSampleVector(uint64_t id,
const BucketRanges* bucket_ranges,
Metadata* meta,
const DelayedPersistentAllocation& counts);
PersistentSampleVector(const PersistentSampleVector&) = delete;
PersistentSampleVector& operator=(const PersistentSampleVector&) = delete;
~PersistentSampleVector() override;
private:
bool MountExistingCountsStorage() const override;
HistogramBase::Count* CreateCountsStorageWhileLocked() override;
DelayedPersistentAllocation persistent_counts_;
};
}
#endif