| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507 | 
							- // Copyright 2016 The Chromium Authors. All rights reserved.
 
- // Use of this source code is governed by a BSD-style license that can be
 
- // found in the LICENSE file.
 
- #ifndef BASE_METRICS_PERSISTENT_HISTOGRAM_ALLOCATOR_H_
 
- #define BASE_METRICS_PERSISTENT_HISTOGRAM_ALLOCATOR_H_
 
- #include <map>
 
- #include <memory>
 
- #include <string>
 
- #include <vector>
 
- #include "base/atomicops.h"
 
- #include "base/base_export.h"
 
- #include "base/feature_list.h"
 
- #include "base/metrics/histogram_base.h"
 
- #include "base/metrics/persistent_memory_allocator.h"
 
- #include "base/process/process_handle.h"
 
- #include "base/strings/string_piece.h"
 
- #include "base/synchronization/lock.h"
 
- namespace base {
 
- class BucketRanges;
 
- class FilePath;
 
- class PersistentSampleMapRecords;
 
- class PersistentSparseHistogramDataManager;
 
- class WritableSharedMemoryRegion;
 
- // Feature definition for enabling histogram persistence.
 
- BASE_EXPORT extern const Feature kPersistentHistogramsFeature;
 
- // A data manager for sparse histograms so each instance of such doesn't have
 
- // to separately iterate over the entire memory segment. Though this class
 
- // will generally be accessed through the PersistentHistogramAllocator above,
 
- // it can be used independently on any PersistentMemoryAllocator (making it
 
- // useable for testing). This object supports only one instance of a sparse
 
- // histogram for a given id. Tests that create multiple identical histograms,
 
- // perhaps to simulate multiple processes, should create a separate manager
 
- // for each.
 
- class BASE_EXPORT PersistentSparseHistogramDataManager {
 
-  public:
 
-   // Constructs the data manager. The allocator must live longer than any
 
-   // managers that reference it.
 
-   explicit PersistentSparseHistogramDataManager(
 
-       PersistentMemoryAllocator* allocator);
 
-   ~PersistentSparseHistogramDataManager();
 
-   // Returns the object that manages the persistent-sample-map records for a
 
-   // given |id|. Only one |user| of this data is allowed at a time. This does
 
-   // an automatic Acquire() on the records. The user must call Release() on
 
-   // the returned object when it is finished with it. Ownership of the records
 
-   // object stays with this manager.
 
-   PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id,
 
-                                                   const void* user);
 
-   // Convenience method that gets the object for a given reference so callers
 
-   // don't have to also keep their own pointer to the appropriate allocator.
 
-   template <typename T>
 
-   T* GetAsObject(PersistentMemoryAllocator::Reference ref) {
 
-     return allocator_->GetAsObject<T>(ref);
 
-   }
 
-  private:
 
-   friend class PersistentSampleMapRecords;
 
-   // Gets the object holding records for a given sample-map id.
 
-   PersistentSampleMapRecords* GetSampleMapRecordsWhileLocked(uint64_t id)
 
-       EXCLUSIVE_LOCKS_REQUIRED(lock_);
 
-   // Loads sample-map records looking for those belonging to the specified
 
-   // |load_id|. Records found for other sample-maps are held for later use
 
-   // without having to iterate again. This should be called only from a
 
-   // PersistentSampleMapRecords object because those objects have a contract
 
-   // that there are no other threads accessing the internal records_ field
 
-   // of the object that is passed in.
 
-   bool LoadRecords(PersistentSampleMapRecords* sample_map_records);
 
-   // Weak-pointer to the allocator used by the sparse histograms.
 
-   PersistentMemoryAllocator* allocator_;
 
-   // Iterator within the allocator for finding sample records.
 
-   PersistentMemoryAllocator::Iterator record_iterator_ GUARDED_BY(lock_);
 
-   // Mapping of sample-map IDs to their sample records.
 
-   std::map<uint64_t, std::unique_ptr<PersistentSampleMapRecords>>
 
-       sample_records_ GUARDED_BY(lock_);
 
-   base::Lock lock_;
 
-   DISALLOW_COPY_AND_ASSIGN(PersistentSparseHistogramDataManager);
 
- };
 
- // This class manages sample-records used by a PersistentSampleMap container
 
- // that underlies a persistent SparseHistogram object. It is broken out into a
 
- // top-level class so that it can be forward-declared in other header files
 
- // rather than include this entire file as would be necessary if it were
 
- // declared within the PersistentSparseHistogramDataManager class above.
 
- class BASE_EXPORT PersistentSampleMapRecords {
 
-  public:
 
-   // Constructs an instance of this class. The manager object must live longer
 
-   // than all instances of this class that reference it, which is not usually
 
-   // a problem since these objects are generally managed from within that
 
-   // manager instance.
 
-   PersistentSampleMapRecords(PersistentSparseHistogramDataManager* data_manager,
 
-                              uint64_t sample_map_id);
 
-   ~PersistentSampleMapRecords();
 
-   // Resets the internal state for a new object using this data. The return
 
-   // value is "this" as a convenience.
 
-   PersistentSampleMapRecords* Acquire(const void* user);
 
-   // Indicates that the using object is done with this data.
 
-   void Release(const void* user);
 
-   // Gets the next reference to a persistent sample-map record. The type and
 
-   // layout of the data being referenced is defined entirely within the
 
-   // PersistentSampleMap class.
 
-   PersistentMemoryAllocator::Reference GetNext();
 
-   // Creates a new persistent sample-map record for sample |value| and returns
 
-   // a reference to it.
 
-   PersistentMemoryAllocator::Reference CreateNew(HistogramBase::Sample value);
 
-   // Convenience method that gets the object for a given reference so callers
 
-   // don't have to also keep their own pointer to the appropriate allocator.
 
-   // This is expected to be used with the SampleRecord structure defined inside
 
-   // the persistent_sample_map.cc file but since that isn't exported (for
 
-   // cleanliness of the interface), a template is defined that will be
 
-   // resolved when used inside that file.
 
-   template <typename T>
 
-   T* GetAsObject(PersistentMemoryAllocator::Reference ref) {
 
-     return data_manager_->GetAsObject<T>(ref);
 
-   }
 
-  private:
 
-   friend PersistentSparseHistogramDataManager;
 
-   // Weak-pointer to the parent data-manager object.
 
-   PersistentSparseHistogramDataManager* data_manager_;
 
-   // ID of PersistentSampleMap to which these records apply.
 
-   const uint64_t sample_map_id_;
 
-   // The current user of this set of records. It is used to ensure that no
 
-   // more than one object is using these records at a given time.
 
-   const void* user_ = nullptr;
 
-   // This is the count of how many "records" have already been read by the
 
-   // owning sample-map.
 
-   size_t seen_ = 0;
 
-   // This is the set of records previously found for a sample map. Because
 
-   // there is ever only one object with a given ID (typically a hash of a
 
-   // histogram name) and because the parent SparseHistogram has acquired
 
-   // its own lock before accessing the PersistentSampleMap it controls, this
 
-   // list can be accessed without acquiring any additional lock.
 
-   std::vector<PersistentMemoryAllocator::Reference> records_;
 
-   // This is the set of records found during iteration through memory. It
 
-   // is appended in bulk to "records". Access to this vector can be done
 
-   // only while holding the parent manager's lock.
 
-   std::vector<PersistentMemoryAllocator::Reference> found_;
 
-   DISALLOW_COPY_AND_ASSIGN(PersistentSampleMapRecords);
 
- };
 
- // This class manages histograms created within a PersistentMemoryAllocator.
 
- class BASE_EXPORT PersistentHistogramAllocator {
 
-  public:
 
-   // A reference to a histogram. While this is implemented as PMA::Reference,
 
-   // it is not conceptually the same thing. Outside callers should always use
 
-   // a Reference matching the class it is for and not mix the two.
 
-   using Reference = PersistentMemoryAllocator::Reference;
 
-   // Iterator used for fetching persistent histograms from an allocator.
 
-   // It is lock-free and thread-safe.
 
-   // See PersistentMemoryAllocator::Iterator for more information.
 
-   class BASE_EXPORT Iterator {
 
-    public:
 
-     // Constructs an iterator on a given |allocator|, starting at the beginning.
 
-     // The allocator must live beyond the lifetime of the iterator.
 
-     explicit Iterator(PersistentHistogramAllocator* allocator);
 
-     // Gets the next histogram from persistent memory; returns null if there
 
-     // are no more histograms to be found. This may still be called again
 
-     // later to retrieve any new histograms added in the meantime.
 
-     std::unique_ptr<HistogramBase> GetNext() { return GetNextWithIgnore(0); }
 
-     // Gets the next histogram from persistent memory, ignoring one particular
 
-     // reference in the process. Pass |ignore| of zero (0) to ignore nothing.
 
-     std::unique_ptr<HistogramBase> GetNextWithIgnore(Reference ignore);
 
-    private:
 
-     // Weak-pointer to histogram allocator being iterated over.
 
-     PersistentHistogramAllocator* allocator_;
 
-     // The iterator used for stepping through objects in persistent memory.
 
-     // It is lock-free and thread-safe which is why this class is also such.
 
-     PersistentMemoryAllocator::Iterator memory_iter_;
 
-     DISALLOW_COPY_AND_ASSIGN(Iterator);
 
-   };
 
-   // A PersistentHistogramAllocator is constructed from a PersistentMemory-
 
-   // Allocator object of which it takes ownership.
 
-   explicit PersistentHistogramAllocator(
 
-       std::unique_ptr<PersistentMemoryAllocator> memory);
 
-   virtual ~PersistentHistogramAllocator();
 
-   // Direct access to underlying memory allocator. If the segment is shared
 
-   // across threads or processes, reading data through these values does
 
-   // not guarantee consistency. Use with care. Do not write.
 
-   PersistentMemoryAllocator* memory_allocator() {
 
-     return memory_allocator_.get();
 
-   }
 
-   // Implement the "metadata" API of a PersistentMemoryAllocator, forwarding
 
-   // those requests to the real one.
 
-   uint64_t Id() const { return memory_allocator_->Id(); }
 
-   const char* Name() const { return memory_allocator_->Name(); }
 
-   const void* data() const { return memory_allocator_->data(); }
 
-   size_t length() const { return memory_allocator_->length(); }
 
-   size_t size() const { return memory_allocator_->size(); }
 
-   size_t used() const { return memory_allocator_->used(); }
 
-   // Recreate a Histogram from data held in persistent memory. Though this
 
-   // object will be local to the current process, the sample data will be
 
-   // shared with all other threads referencing it. This method takes a |ref|
 
-   // to where the top-level histogram data may be found in this allocator.
 
-   // This method will return null if any problem is detected with the data.
 
-   std::unique_ptr<HistogramBase> GetHistogram(Reference ref);
 
-   // Allocate a new persistent histogram. The returned histogram will not
 
-   // be able to be located by other allocators until it is "finalized".
 
-   std::unique_ptr<HistogramBase> AllocateHistogram(
 
-       HistogramType histogram_type,
 
-       const std::string& name,
 
-       int minimum,
 
-       int maximum,
 
-       const BucketRanges* bucket_ranges,
 
-       int32_t flags,
 
-       Reference* ref_ptr);
 
-   // Finalize the creation of the histogram, making it available to other
 
-   // processes if |registered| (as in: added to the StatisticsRecorder) is
 
-   // True, forgetting it otherwise.
 
-   void FinalizeHistogram(Reference ref, bool registered);
 
-   // Merges the data in a persistent histogram with one held globally by the
 
-   // StatisticsRecorder, updating the "logged" samples within the passed
 
-   // object so that repeated merges are allowed. Don't call this on a "global"
 
-   // allocator because histograms created there will already be in the SR.
 
-   void MergeHistogramDeltaToStatisticsRecorder(HistogramBase* histogram);
 
-   // As above but merge the "final" delta. No update of "logged" samples is
 
-   // done which means it can operate on read-only objects. It's essential,
 
-   // however, not to call this more than once or those final samples will
 
-   // get recorded again.
 
-   void MergeHistogramFinalDeltaToStatisticsRecorder(
 
-       const HistogramBase* histogram);
 
-   // Returns the object that manages the persistent-sample-map records for a
 
-   // given |id|. Only one |user| of this data is allowed at a time. This does
 
-   // an automatic Acquire() on the records. The user must call Release() on
 
-   // the returned object when it is finished with it. Ownership stays with
 
-   // this allocator.
 
-   PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id,
 
-                                                   const void* user);
 
-   // Create internal histograms for tracking memory use and allocation sizes
 
-   // for allocator of |name| (which can simply be the result of Name()). This
 
-   // is done seperately from construction for situations such as when the
 
-   // histograms will be backed by memory provided by this very allocator.
 
-   //
 
-   // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml
 
-   // with the following histograms:
 
-   //    UMA.PersistentAllocator.name.Allocs
 
-   //    UMA.PersistentAllocator.name.UsedPct
 
-   void CreateTrackingHistograms(StringPiece name);
 
-   void UpdateTrackingHistograms();
 
-   // Clears the internal |last_created_| reference so testing can validate
 
-   // operation without that optimization.
 
-   void ClearLastCreatedReferenceForTesting();
 
-  protected:
 
-   // The structure used to hold histogram data in persistent memory. It is
 
-   // defined and used entirely within the .cc file.
 
-   struct PersistentHistogramData;
 
-   // Gets the reference of the last histogram created, used to avoid
 
-   // trying to import what was just created.
 
-   PersistentHistogramAllocator::Reference last_created() {
 
-     return subtle::NoBarrier_Load(&last_created_);
 
-   }
 
-   // Gets the next histogram in persistent data based on iterator while
 
-   // ignoring a particular reference if it is found.
 
-   std::unique_ptr<HistogramBase> GetNextHistogramWithIgnore(Iterator* iter,
 
-                                                             Reference ignore);
 
-  private:
 
-   // Create a histogram based on saved (persistent) information about it.
 
-   std::unique_ptr<HistogramBase> CreateHistogram(
 
-       PersistentHistogramData* histogram_data_ptr);
 
-   // Gets or creates an object in the global StatisticsRecorder matching
 
-   // the |histogram| passed. Null is returned if one was not found and
 
-   // one could not be created.
 
-   HistogramBase* GetOrCreateStatisticsRecorderHistogram(
 
-       const HistogramBase* histogram);
 
-   // The memory allocator that provides the actual histogram storage.
 
-   std::unique_ptr<PersistentMemoryAllocator> memory_allocator_;
 
-   // The data-manager used to improve performance of sparse histograms.
 
-   PersistentSparseHistogramDataManager sparse_histogram_data_manager_;
 
-   // A reference to the last-created histogram in the allocator, used to avoid
 
-   // trying to import what was just created.
 
-   // TODO(bcwhite): Change this to std::atomic<PMA::Reference> when available.
 
-   subtle::Atomic32 last_created_ = 0;
 
-   DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocator);
 
- };
 
- // A special case of the PersistentHistogramAllocator that operates on a
 
- // global scale, collecting histograms created through standard macros and
 
- // the FactoryGet() method.
 
- class BASE_EXPORT GlobalHistogramAllocator
 
-     : public PersistentHistogramAllocator {
 
-  public:
 
-   ~GlobalHistogramAllocator() override;
 
-   // Create a global allocator using the passed-in memory |base|, |size|, and
 
-   // other parameters. Ownership of the memory segment remains with the caller.
 
-   static void CreateWithPersistentMemory(void* base,
 
-                                          size_t size,
 
-                                          size_t page_size,
 
-                                          uint64_t id,
 
-                                          StringPiece name);
 
-   // Create a global allocator using an internal block of memory of the
 
-   // specified |size| taken from the heap.
 
-   static void CreateWithLocalMemory(size_t size, uint64_t id, StringPiece name);
 
- #if !defined(OS_NACL)
 
-   // Create a global allocator by memory-mapping a |file|. If the file does
 
-   // not exist, it will be created with the specified |size|. If the file does
 
-   // exist, the allocator will use and add to its contents, ignoring the passed
 
-   // size in favor of the existing size. Returns whether the global allocator
 
-   // was set.
 
-   static bool CreateWithFile(const FilePath& file_path,
 
-                              size_t size,
 
-                              uint64_t id,
 
-                              StringPiece name);
 
-   // Creates a new file at |active_path|. If it already exists, it will first be
 
-   // moved to |base_path|. In all cases, any old file at |base_path| will be
 
-   // removed. If |spare_path| is non-empty and exists, that will be renamed and
 
-   // used as the active file. Otherwise, the file will be created using the
 
-   // given size, id, and name. Returns whether the global allocator was set.
 
-   static bool CreateWithActiveFile(const FilePath& base_path,
 
-                                    const FilePath& active_path,
 
-                                    const FilePath& spare_path,
 
-                                    size_t size,
 
-                                    uint64_t id,
 
-                                    StringPiece name);
 
-   // Uses ConstructBaseActivePairFilePaths() to build a pair of file names which
 
-   // are then used for CreateWithActiveFile(). |name| is used for both the
 
-   // internal name for the allocator and also for the name of the file inside
 
-   // |dir|.
 
-   static bool CreateWithActiveFileInDir(const FilePath& dir,
 
-                                         size_t size,
 
-                                         uint64_t id,
 
-                                         StringPiece name);
 
-   // Constructs a filename using a name.
 
-   static FilePath ConstructFilePath(const FilePath& dir, StringPiece name);
 
-   // Like above but with timestamp and pid for use in upload directories.
 
-   static FilePath ConstructFilePathForUploadDir(const FilePath& dir,
 
-                                                 StringPiece name,
 
-                                                 base::Time stamp,
 
-                                                 ProcessId pid);
 
-   // Parses a filename to extract name, timestamp, and pid.
 
-   static bool ParseFilePath(const FilePath& path,
 
-                             std::string* out_name,
 
-                             Time* out_stamp,
 
-                             ProcessId* out_pid);
 
-   // Constructs a set of names in |dir| based on name that can be used for a
 
-   // base + active persistent memory mapped location for CreateWithActiveFile().
 
-   // The spare path is a file that can be pre-created and moved to be active
 
-   // without any startup penalty that comes from constructing the file. |name|
 
-   // will be used as the basename of the file inside |dir|. |out_base_path|,
 
-   // |out_active_path|, or |out_spare_path| may be null if not needed.
 
-   static void ConstructFilePaths(const FilePath& dir,
 
-                                  StringPiece name,
 
-                                  FilePath* out_base_path,
 
-                                  FilePath* out_active_path,
 
-                                  FilePath* out_spare_path);
 
-   // As above but puts the base files in a different "upload" directory. This
 
-   // is useful when moving all completed files into a single directory for easy
 
-   // upload management.
 
-   static void ConstructFilePathsForUploadDir(const FilePath& active_dir,
 
-                                              const FilePath& upload_dir,
 
-                                              const std::string& name,
 
-                                              FilePath* out_upload_path,
 
-                                              FilePath* out_active_path,
 
-                                              FilePath* out_spare_path);
 
-   // Create a "spare" file that can later be made the "active" file. This
 
-   // should be done on a background thread if possible.
 
-   static bool CreateSpareFile(const FilePath& spare_path, size_t size);
 
-   // Same as above but uses standard names. |name| is the name of the allocator
 
-   // and is also used to create the correct filename.
 
-   static bool CreateSpareFileInDir(const FilePath& dir_path,
 
-                                    size_t size,
 
-                                    StringPiece name);
 
- #endif
 
-   // Create a global allocator using a block of shared memory accessed
 
-   // through the given |region|. The allocator maps the shared memory into
 
-   // current process's virtual address space and frees it upon destruction.
 
-   // The memory will continue to live if other processes have access to it.
 
-   static void CreateWithSharedMemoryRegion(
 
-       const WritableSharedMemoryRegion& region);
 
-   // Sets a GlobalHistogramAllocator for globally storing histograms in
 
-   // a space that can be persisted or shared between processes. There is only
 
-   // ever one allocator for all such histograms created by a single process.
 
-   // This takes ownership of the object and should be called as soon as
 
-   // possible during startup to capture as many histograms as possible and
 
-   // while operating single-threaded so there are no race-conditions.
 
-   static void Set(std::unique_ptr<GlobalHistogramAllocator> allocator);
 
-   // Gets a pointer to the global histogram allocator. Returns null if none
 
-   // exists.
 
-   static GlobalHistogramAllocator* Get();
 
-   // This access to the persistent allocator is only for testing; it extracts
 
-   // the current allocator completely. This allows easy creation of histograms
 
-   // within persistent memory segments which can then be extracted and used in
 
-   // other ways.
 
-   static std::unique_ptr<GlobalHistogramAllocator> ReleaseForTesting();
 
-   // Stores a pathname to which the contents of this allocator should be saved
 
-   // in order to persist the data for a later use.
 
-   void SetPersistentLocation(const FilePath& location);
 
-   // Retrieves a previously set pathname to which the contents of this allocator
 
-   // are to be saved.
 
-   const FilePath& GetPersistentLocation() const;
 
-   // Writes the internal data to a previously set location. This is generally
 
-   // called when a process is exiting from a section of code that may not know
 
-   // the filesystem. The data is written in an atomic manner. The return value
 
-   // indicates success.
 
-   bool WriteToPersistentLocation();
 
-   // If there is a global metrics file being updated on disk, mark it to be
 
-   // deleted when the process exits.
 
-   void DeletePersistentLocation();
 
-  private:
 
-   friend class StatisticsRecorder;
 
-   // Creates a new global histogram allocator.
 
-   explicit GlobalHistogramAllocator(
 
-       std::unique_ptr<PersistentMemoryAllocator> memory);
 
-   // Import new histograms from the global histogram allocator. It's possible
 
-   // for other processes to create histograms in the active memory segment;
 
-   // this adds those to the internal list of known histograms to avoid creating
 
-   // duplicates that would have to be merged during reporting. Every call to
 
-   // this method resumes from the last entry it saw; it costs nothing if
 
-   // nothing new has been added.
 
-   void ImportHistogramsToStatisticsRecorder();
 
-   // Builds a FilePath for a metrics file.
 
-   static FilePath MakeMetricsFilePath(const FilePath& dir, StringPiece name);
 
-   // Import always continues from where it left off, making use of a single
 
-   // iterator to continue the work.
 
-   Iterator import_iterator_;
 
-   // The location to which the data should be persisted.
 
-   FilePath persistent_location_;
 
-   DISALLOW_COPY_AND_ASSIGN(GlobalHistogramAllocator);
 
- };
 
- }  // namespace base
 
- #endif  // BASE_METRICS_PERSISTENT_HISTOGRAM_ALLOCATOR_H__
 
 
  |