blob: 2eb28dfaf5b4258d32b926bd63710c61891b0da1 [file] [log] [blame]
Alex Vakulenko45779222016-03-17 10:36:19 -07001// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_METRICS_HISTOGRAM_PERSISTENCE_H_
6#define BASE_METRICS_HISTOGRAM_PERSISTENCE_H_
7
Luis Hector Chavez94ffa552016-05-25 15:29:35 -07008#include <map>
9#include <memory>
10
Alex Vakulenko45779222016-03-17 10:36:19 -070011#include "base/atomicops.h"
12#include "base/base_export.h"
13#include "base/feature_list.h"
Alex Vakulenko45779222016-03-17 10:36:19 -070014#include "base/memory/shared_memory.h"
15#include "base/metrics/histogram_base.h"
16#include "base/metrics/persistent_memory_allocator.h"
17#include "base/strings/string_piece.h"
Luis Hector Chavez94ffa552016-05-25 15:29:35 -070018#include "base/synchronization/lock.h"
Alex Vakulenko45779222016-03-17 10:36:19 -070019
20namespace base {
21
Jay Civelli3a83cdd2017-03-22 17:31:44 -070022class BucketRanges;
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -070023class FilePath;
Luis Hector Chavez94ffa552016-05-25 15:29:35 -070024class PersistentSampleMapRecords;
25class PersistentSparseHistogramDataManager;
26
Alex Vakulenko45779222016-03-17 10:36:19 -070027// Feature definition for enabling histogram persistence.
28BASE_EXPORT extern const Feature kPersistentHistogramsFeature;
29
Luis Hector Chavez94ffa552016-05-25 15:29:35 -070030
31// A data manager for sparse histograms so each instance of such doesn't have
32// to separately iterate over the entire memory segment. Though this class
33// will generally be accessed through the PersistentHistogramAllocator above,
34// it can be used independently on any PersistentMemoryAllocator (making it
35// useable for testing). This object supports only one instance of a sparse
36// histogram for a given id. Tests that create multiple identical histograms,
37// perhaps to simulate multiple processes, should create a separate manager
38// for each.
39class BASE_EXPORT PersistentSparseHistogramDataManager {
40 public:
41 // Constructs the data manager. The allocator must live longer than any
42 // managers that reference it.
43 explicit PersistentSparseHistogramDataManager(
44 PersistentMemoryAllocator* allocator);
45
46 ~PersistentSparseHistogramDataManager();
47
48 // Returns the object that manages the persistent-sample-map records for a
49 // given |id|. Only one |user| of this data is allowed at a time. This does
50 // an automatic Acquire() on the records. The user must call Release() on
51 // the returned object when it is finished with it. Ownership of the records
52 // object stays with this manager.
53 PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id,
54 const void* user);
55
56 // Convenience method that gets the object for a given reference so callers
57 // don't have to also keep their own pointer to the appropriate allocator.
58 template <typename T>
Jay Civelli3a83cdd2017-03-22 17:31:44 -070059 T* GetAsObject(PersistentMemoryAllocator::Reference ref) {
60 return allocator_->GetAsObject<T>(ref);
Luis Hector Chavez94ffa552016-05-25 15:29:35 -070061 }
62
63 private:
64 friend class PersistentSampleMapRecords;
65
66 // Gets the object holding records for a given sample-map id when |lock_|
67 // has already been acquired.
68 PersistentSampleMapRecords* GetSampleMapRecordsWhileLocked(uint64_t id);
69
70 // Loads sample-map records looking for those belonging to the specified
71 // |load_id|. Records found for other sample-maps are held for later use
72 // without having to iterate again. This should be called only from a
73 // PersistentSampleMapRecords object because those objects have a contract
74 // that there are no other threads accessing the internal records_ field
75 // of the object that is passed in.
76 bool LoadRecords(PersistentSampleMapRecords* sample_map_records);
77
78 // Weak-pointer to the allocator used by the sparse histograms.
79 PersistentMemoryAllocator* allocator_;
80
81 // Iterator within the allocator for finding sample records.
82 PersistentMemoryAllocator::Iterator record_iterator_;
83
84 // Mapping of sample-map IDs to their sample records.
85 std::map<uint64_t, std::unique_ptr<PersistentSampleMapRecords>>
86 sample_records_;
87
88 // A lock used for synchronizing changes to sample_records_.
89 base::Lock lock_;
90
91 DISALLOW_COPY_AND_ASSIGN(PersistentSparseHistogramDataManager);
92};
93
94
95// This class manages sample-records used by a PersistentSampleMap container
96// that underlies a persistent SparseHistogram object. It is broken out into a
97// top-level class so that it can be forward-declared in other header files
98// rather than include this entire file as would be necessary if it were
99// declared within the PersistentSparseHistogramDataManager class above.
100class BASE_EXPORT PersistentSampleMapRecords {
101 public:
102 // Constructs an instance of this class. The manager object must live longer
103 // than all instances of this class that reference it, which is not usually
104 // a problem since these objects are generally managed from within that
105 // manager instance.
106 PersistentSampleMapRecords(PersistentSparseHistogramDataManager* data_manager,
107 uint64_t sample_map_id);
108
109 ~PersistentSampleMapRecords();
110
111 // Resets the internal state for a new object using this data. The return
112 // value is "this" as a convenience.
113 PersistentSampleMapRecords* Acquire(const void* user);
114
115 // Indicates that the using object is done with this data.
116 void Release(const void* user);
117
118 // Gets the next reference to a persistent sample-map record. The type and
119 // layout of the data being referenced is defined entirely within the
120 // PersistentSampleMap class.
121 PersistentMemoryAllocator::Reference GetNext();
122
123 // Creates a new persistent sample-map record for sample |value| and returns
124 // a reference to it.
125 PersistentMemoryAllocator::Reference CreateNew(HistogramBase::Sample value);
126
127 // Convenience method that gets the object for a given reference so callers
128 // don't have to also keep their own pointer to the appropriate allocator.
129 // This is expected to be used with the SampleRecord structure defined inside
130 // the persistent_sample_map.cc file but since that isn't exported (for
131 // cleanliness of the interface), a template is defined that will be
132 // resolved when used inside that file.
133 template <typename T>
Jay Civelli3a83cdd2017-03-22 17:31:44 -0700134 T* GetAsObject(PersistentMemoryAllocator::Reference ref) {
135 return data_manager_->GetAsObject<T>(ref);
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700136 }
137
138 private:
139 friend PersistentSparseHistogramDataManager;
140
141 // Weak-pointer to the parent data-manager object.
142 PersistentSparseHistogramDataManager* data_manager_;
143
144 // ID of PersistentSampleMap to which these records apply.
145 const uint64_t sample_map_id_;
146
147 // The current user of this set of records. It is used to ensure that no
148 // more than one object is using these records at a given time.
149 const void* user_ = nullptr;
150
151 // This is the count of how many "records" have already been read by the
152 // owning sample-map.
153 size_t seen_ = 0;
154
155 // This is the set of records previously found for a sample map. Because
156 // there is ever only one object with a given ID (typically a hash of a
157 // histogram name) and because the parent SparseHistogram has acquired
158 // its own lock before accessing the PersistentSampleMap it controls, this
159 // list can be accessed without acquiring any additional lock.
160 std::vector<PersistentMemoryAllocator::Reference> records_;
161
162 // This is the set of records found during iteration through memory. It
163 // is appended in bulk to "records". Access to this vector can be done
164 // only while holding the parent manager's lock.
165 std::vector<PersistentMemoryAllocator::Reference> found_;
166
167 DISALLOW_COPY_AND_ASSIGN(PersistentSampleMapRecords);
168};
169
170
Alex Vakulenko45779222016-03-17 10:36:19 -0700171// This class manages histograms created within a PersistentMemoryAllocator.
172class BASE_EXPORT PersistentHistogramAllocator {
173 public:
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700174 // A reference to a histogram. While this is implemented as PMA::Reference,
175 // it is not conceptually the same thing. Outside callers should always use
176 // a Reference matching the class it is for and not mix the two.
177 using Reference = PersistentMemoryAllocator::Reference;
178
179 // Iterator used for fetching persistent histograms from an allocator.
180 // It is lock-free and thread-safe.
181 // See PersistentMemoryAllocator::Iterator for more information.
182 class BASE_EXPORT Iterator {
Alex Vakulenko45779222016-03-17 10:36:19 -0700183 public:
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700184 // Constructs an iterator on a given |allocator|, starting at the beginning.
185 // The allocator must live beyond the lifetime of the iterator.
186 explicit Iterator(PersistentHistogramAllocator* allocator);
187
188 // Gets the next histogram from persistent memory; returns null if there
189 // are no more histograms to be found. This may still be called again
190 // later to retrieve any new histograms added in the meantime.
191 std::unique_ptr<HistogramBase> GetNext() { return GetNextWithIgnore(0); }
192
193 // Gets the next histogram from persistent memory, ignoring one particular
194 // reference in the process. Pass |ignore| of zero (0) to ignore nothing.
195 std::unique_ptr<HistogramBase> GetNextWithIgnore(Reference ignore);
Alex Vakulenko45779222016-03-17 10:36:19 -0700196
197 private:
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700198 // Weak-pointer to histogram allocator being iterated over.
199 PersistentHistogramAllocator* allocator_;
Alex Vakulenko45779222016-03-17 10:36:19 -0700200
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700201 // The iterator used for stepping through objects in persistent memory.
202 // It is lock-free and thread-safe which is why this class is also such.
203 PersistentMemoryAllocator::Iterator memory_iter_;
204
205 DISALLOW_COPY_AND_ASSIGN(Iterator);
Alex Vakulenko45779222016-03-17 10:36:19 -0700206 };
207
Alex Vakulenko45779222016-03-17 10:36:19 -0700208 // A PersistentHistogramAllocator is constructed from a PersistentMemory-
209 // Allocator object of which it takes ownership.
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700210 explicit PersistentHistogramAllocator(
211 std::unique_ptr<PersistentMemoryAllocator> memory);
212 virtual ~PersistentHistogramAllocator();
Alex Vakulenko45779222016-03-17 10:36:19 -0700213
214 // Direct access to underlying memory allocator. If the segment is shared
215 // across threads or processes, reading data through these values does
216 // not guarantee consistency. Use with care. Do not write.
217 PersistentMemoryAllocator* memory_allocator() {
218 return memory_allocator_.get();
219 }
220
221 // Implement the "metadata" API of a PersistentMemoryAllocator, forwarding
222 // those requests to the real one.
223 uint64_t Id() const { return memory_allocator_->Id(); }
224 const char* Name() const { return memory_allocator_->Name(); }
225 const void* data() const { return memory_allocator_->data(); }
226 size_t length() const { return memory_allocator_->length(); }
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700227 size_t size() const { return memory_allocator_->size(); }
Alex Vakulenko45779222016-03-17 10:36:19 -0700228 size_t used() const { return memory_allocator_->used(); }
229
230 // Recreate a Histogram from data held in persistent memory. Though this
231 // object will be local to the current process, the sample data will be
232 // shared with all other threads referencing it. This method takes a |ref|
233 // to where the top-level histogram data may be found in this allocator.
234 // This method will return null if any problem is detected with the data.
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700235 std::unique_ptr<HistogramBase> GetHistogram(Reference ref);
Alex Vakulenko45779222016-03-17 10:36:19 -0700236
237 // Allocate a new persistent histogram. The returned histogram will not
238 // be able to be located by other allocators until it is "finalized".
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700239 std::unique_ptr<HistogramBase> AllocateHistogram(
Alex Vakulenko45779222016-03-17 10:36:19 -0700240 HistogramType histogram_type,
241 const std::string& name,
242 int minimum,
243 int maximum,
244 const BucketRanges* bucket_ranges,
245 int32_t flags,
246 Reference* ref_ptr);
247
248 // Finalize the creation of the histogram, making it available to other
249 // processes if |registered| (as in: added to the StatisticsRecorder) is
250 // True, forgetting it otherwise.
251 void FinalizeHistogram(Reference ref, bool registered);
252
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -0700253 // Merges the data in a persistent histogram with one held globally by the
254 // StatisticsRecorder, updating the "logged" samples within the passed
255 // object so that repeated merges are allowed. Don't call this on a "global"
256 // allocator because histograms created there will already be in the SR.
257 void MergeHistogramDeltaToStatisticsRecorder(HistogramBase* histogram);
258
259 // As above but merge the "final" delta. No update of "logged" samples is
260 // done which means it can operate on read-only objects. It's essential,
261 // however, not to call this more than once or those final samples will
262 // get recorded again.
263 void MergeHistogramFinalDeltaToStatisticsRecorder(
264 const HistogramBase* histogram);
265
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700266 // Returns the object that manages the persistent-sample-map records for a
267 // given |id|. Only one |user| of this data is allowed at a time. This does
268 // an automatic Acquire() on the records. The user must call Release() on
269 // the returned object when it is finished with it. Ownership stays with
270 // this allocator.
271 PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id,
272 const void* user);
273
Alex Vakulenko45779222016-03-17 10:36:19 -0700274 // Create internal histograms for tracking memory use and allocation sizes
275 // for allocator of |name| (which can simply be the result of Name()). This
276 // is done seperately from construction for situations such as when the
277 // histograms will be backed by memory provided by this very allocator.
278 //
279 // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml
280 // with the following histograms:
281 // UMA.PersistentAllocator.name.Allocs
282 // UMA.PersistentAllocator.name.UsedPct
283 void CreateTrackingHistograms(StringPiece name);
284 void UpdateTrackingHistograms();
285
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700286 // Clears the internal |last_created_| reference so testing can validate
287 // operation without that optimization.
288 void ClearLastCreatedReferenceForTesting();
Alex Vakulenko45779222016-03-17 10:36:19 -0700289
290 // Histogram containing creation results. Visible for testing.
291 static HistogramBase* GetCreateHistogramResultHistogram();
292
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700293 protected:
294 // The structure used to hold histogram data in persistent memory. It is
295 // defined and used entirely within the .cc file.
296 struct PersistentHistogramData;
297
298 // Gets the reference of the last histogram created, used to avoid
299 // trying to import what was just created.
300 PersistentHistogramAllocator::Reference last_created() {
301 return subtle::NoBarrier_Load(&last_created_);
302 }
303
304 // Gets the next histogram in persistent data based on iterator while
305 // ignoring a particular reference if it is found.
306 std::unique_ptr<HistogramBase> GetNextHistogramWithIgnore(Iterator* iter,
307 Reference ignore);
308
Alex Vakulenko45779222016-03-17 10:36:19 -0700309 private:
310 // Enumerate possible creation results for reporting.
311 enum CreateHistogramResultType {
312 // Everything was fine.
313 CREATE_HISTOGRAM_SUCCESS = 0,
314
315 // Pointer to metadata was not valid.
316 CREATE_HISTOGRAM_INVALID_METADATA_POINTER,
317
318 // Histogram metadata was not valid.
319 CREATE_HISTOGRAM_INVALID_METADATA,
320
321 // Ranges information was not valid.
322 CREATE_HISTOGRAM_INVALID_RANGES_ARRAY,
323
324 // Counts information was not valid.
325 CREATE_HISTOGRAM_INVALID_COUNTS_ARRAY,
326
327 // Could not allocate histogram memory due to corruption.
328 CREATE_HISTOGRAM_ALLOCATOR_CORRUPT,
329
330 // Could not allocate histogram memory due to lack of space.
331 CREATE_HISTOGRAM_ALLOCATOR_FULL,
332
333 // Could not allocate histogram memory due to unknown error.
334 CREATE_HISTOGRAM_ALLOCATOR_ERROR,
335
336 // Histogram was of unknown type.
337 CREATE_HISTOGRAM_UNKNOWN_TYPE,
338
339 // Instance has detected a corrupt allocator (recorded only once).
340 CREATE_HISTOGRAM_ALLOCATOR_NEWLY_CORRUPT,
341
342 // Always keep this at the end.
343 CREATE_HISTOGRAM_MAX
344 };
345
Alex Vakulenko45779222016-03-17 10:36:19 -0700346 // Create a histogram based on saved (persistent) information about it.
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700347 std::unique_ptr<HistogramBase> CreateHistogram(
Alex Vakulenko45779222016-03-17 10:36:19 -0700348 PersistentHistogramData* histogram_data_ptr);
349
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -0700350 // Gets or creates an object in the global StatisticsRecorder matching
351 // the |histogram| passed. Null is returned if one was not found and
352 // one could not be created.
353 HistogramBase* GetOrCreateStatisticsRecorderHistogram(
354 const HistogramBase* histogram);
355
Alex Vakulenko45779222016-03-17 10:36:19 -0700356 // Record the result of a histogram creation.
357 static void RecordCreateHistogramResult(CreateHistogramResultType result);
358
359 // The memory allocator that provides the actual histogram storage.
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700360 std::unique_ptr<PersistentMemoryAllocator> memory_allocator_;
361
362 // The data-manager used to improve performance of sparse histograms.
363 PersistentSparseHistogramDataManager sparse_histogram_data_manager_;
Alex Vakulenko45779222016-03-17 10:36:19 -0700364
365 // A reference to the last-created histogram in the allocator, used to avoid
366 // trying to import what was just created.
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700367 // TODO(bcwhite): Change this to std::atomic<PMA::Reference> when available.
368 subtle::Atomic32 last_created_ = 0;
Alex Vakulenko45779222016-03-17 10:36:19 -0700369
370 DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocator);
371};
372
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700373
374// A special case of the PersistentHistogramAllocator that operates on a
375// global scale, collecting histograms created through standard macros and
376// the FactoryGet() method.
377class BASE_EXPORT GlobalHistogramAllocator
378 : public PersistentHistogramAllocator {
379 public:
380 ~GlobalHistogramAllocator() override;
381
382 // Create a global allocator using the passed-in memory |base|, |size|, and
383 // other parameters. Ownership of the memory segment remains with the caller.
384 static void CreateWithPersistentMemory(void* base,
385 size_t size,
386 size_t page_size,
387 uint64_t id,
388 StringPiece name);
389
390 // Create a global allocator using an internal block of memory of the
391 // specified |size| taken from the heap.
392 static void CreateWithLocalMemory(size_t size, uint64_t id, StringPiece name);
393
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -0700394#if !defined(OS_NACL)
395 // Create a global allocator by memory-mapping a |file|. If the file does
396 // not exist, it will be created with the specified |size|. If the file does
397 // exist, the allocator will use and add to its contents, ignoring the passed
Jay Civelli3a83cdd2017-03-22 17:31:44 -0700398 // size in favor of the existing size. Returns whether the global allocator
399 // was set.
400 static bool CreateWithFile(const FilePath& file_path,
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -0700401 size_t size,
402 uint64_t id,
403 StringPiece name);
Jay Civelli3a83cdd2017-03-22 17:31:44 -0700404
405 // Creates a new file at |active_path|. If it already exists, it will first be
406 // moved to |base_path|. In all cases, any old file at |base_path| will be
407 // removed. The file will be created using the given size, id, and name.
408 // Returns whether the global allocator was set.
409 static bool CreateWithActiveFile(const FilePath& base_path,
410 const FilePath& active_path,
411 size_t size,
412 uint64_t id,
413 StringPiece name);
414
415 // Uses ConstructBaseActivePairFilePaths() to build a pair of file names which
416 // are then used for CreateWithActiveFile(). |name| is used for both the
417 // internal name for the allocator and also for the name of the file inside
418 // |dir|.
419 static bool CreateWithActiveFileInDir(const FilePath& dir,
420 size_t size,
421 uint64_t id,
422 StringPiece name);
423
424 // Constructs a pair of names in |dir| based on name that can be used for a
425 // base + active persistent memory mapped location for CreateWithActiveFile().
426 // |name| will be used as the basename of the file inside |dir|.
427 // |out_base_path| or |out_active_path| may be null if not needed.
428 static void ConstructFilePaths(const FilePath& dir,
429 StringPiece name,
430 FilePath* out_base_path,
431 FilePath* out_active_path);
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -0700432#endif
433
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700434 // Create a global allocator using a block of shared |memory| of the
435 // specified |size|. The allocator takes ownership of the shared memory
436 // and releases it upon destruction, though the memory will continue to
437 // live if other processes have access to it.
438 static void CreateWithSharedMemory(std::unique_ptr<SharedMemory> memory,
439 size_t size,
440 uint64_t id,
441 StringPiece name);
442
443 // Create a global allocator using a block of shared memory accessed
444 // through the given |handle| and |size|. The allocator takes ownership
445 // of the handle and closes it upon destruction, though the memory will
446 // continue to live if other processes have access to it.
447 static void CreateWithSharedMemoryHandle(const SharedMemoryHandle& handle,
448 size_t size);
449
450 // Sets a GlobalHistogramAllocator for globally storing histograms in
451 // a space that can be persisted or shared between processes. There is only
452 // ever one allocator for all such histograms created by a single process.
453 // This takes ownership of the object and should be called as soon as
454 // possible during startup to capture as many histograms as possible and
455 // while operating single-threaded so there are no race-conditions.
456 static void Set(std::unique_ptr<GlobalHistogramAllocator> allocator);
457
458 // Gets a pointer to the global histogram allocator. Returns null if none
459 // exists.
460 static GlobalHistogramAllocator* Get();
461
462 // This access to the persistent allocator is only for testing; it extracts
463 // the current allocator completely. This allows easy creation of histograms
464 // within persistent memory segments which can then be extracted and used in
465 // other ways.
466 static std::unique_ptr<GlobalHistogramAllocator> ReleaseForTesting();
467
468 // Stores a pathname to which the contents of this allocator should be saved
469 // in order to persist the data for a later use.
470 void SetPersistentLocation(const FilePath& location);
471
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -0700472 // Retrieves a previously set pathname to which the contents of this allocator
473 // are to be saved.
474 const FilePath& GetPersistentLocation() const;
475
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700476 // Writes the internal data to a previously set location. This is generally
477 // called when a process is exiting from a section of code that may not know
478 // the filesystem. The data is written in an atomic manner. The return value
479 // indicates success.
480 bool WriteToPersistentLocation();
481
Jay Civelli3a83cdd2017-03-22 17:31:44 -0700482 // If there is a global metrics file being updated on disk, mark it to be
483 // deleted when the process exits.
484 void DeletePersistentLocation();
485
Luis Hector Chavez94ffa552016-05-25 15:29:35 -0700486 private:
487 friend class StatisticsRecorder;
488
489 // Creates a new global histogram allocator.
490 explicit GlobalHistogramAllocator(
491 std::unique_ptr<PersistentMemoryAllocator> memory);
492
493 // Import new histograms from the global histogram allocator. It's possible
494 // for other processes to create histograms in the active memory segment;
495 // this adds those to the internal list of known histograms to avoid creating
496 // duplicates that would have to be merged during reporting. Every call to
497 // this method resumes from the last entry it saw; it costs nothing if
498 // nothing new has been added.
499 void ImportHistogramsToStatisticsRecorder();
500
501 // Import always continues from where it left off, making use of a single
502 // iterator to continue the work.
503 Iterator import_iterator_;
504
505 // The location to which the data should be persisted.
506 FilePath persistent_location_;
507
508 DISALLOW_COPY_AND_ASSIGN(GlobalHistogramAllocator);
509};
510
Alex Vakulenko45779222016-03-17 10:36:19 -0700511} // namespace base
512
513#endif // BASE_METRICS_HISTOGRAM_PERSISTENCE_H_