important_file_writer.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // Copyright (c) 2012 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. #ifndef BASE_FILES_IMPORTANT_FILE_WRITER_H_
  5. #define BASE_FILES_IMPORTANT_FILE_WRITER_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/base_export.h"
  9. #include "base/callback.h"
  10. #include "base/files/file_path.h"
  11. #include "base/macros.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/sequence_checker.h"
  14. #include "base/strings/string_piece.h"
  15. #include "base/time/time.h"
  16. #include "base/timer/timer.h"
  17. namespace base {
  18. class SequencedTaskRunner;
  19. // Helper for atomically writing a file to ensure that it won't be corrupted by
  20. // *application* crash during write (implemented as create, flush, rename).
  21. //
  22. // As an added benefit, ImportantFileWriter makes it less likely that the file
  23. // is corrupted by *system* crash, though even if the ImportantFileWriter call
  24. // has already returned at the time of the crash it is not specified which
  25. // version of the file (old or new) is preserved. And depending on system
  26. // configuration (hardware and software) a significant likelihood of file
  27. // corruption may remain, thus using ImportantFileWriter is not a valid
  28. // substitute for file integrity checks and recovery codepaths for malformed
  29. // files.
  30. //
  31. // Also note that ImportantFileWriter can be *really* slow (cf. File::Flush()
  32. // for details) and thus please don't block shutdown on ImportantFileWriter.
  33. class BASE_EXPORT ImportantFileWriter {
  34. public:
  35. // Used by ScheduleSave to lazily provide the data to be saved. Allows us
  36. // to also batch data serializations.
  37. class BASE_EXPORT DataSerializer {
  38. public:
  39. // Should put serialized string in |data| and return true on successful
  40. // serialization. Will be called on the same thread on which
  41. // ImportantFileWriter has been created.
  42. virtual bool SerializeData(std::string* data) = 0;
  43. protected:
  44. virtual ~DataSerializer() = default;
  45. };
  46. // Save |data| to |path| in an atomic manner. Blocks and writes data on the
  47. // current thread. Does not guarantee file integrity across system crash (see
  48. // the class comment above).
  49. static bool WriteFileAtomically(const FilePath& path,
  50. StringPiece data,
  51. StringPiece histogram_suffix = StringPiece());
  52. // Initialize the writer.
  53. // |path| is the name of file to write.
  54. // |task_runner| is the SequencedTaskRunner instance where on which we will
  55. // execute file I/O operations.
  56. // All non-const methods, ctor and dtor must be called on the same thread.
  57. ImportantFileWriter(const FilePath& path,
  58. scoped_refptr<SequencedTaskRunner> task_runner,
  59. const char* histogram_suffix = nullptr);
  60. // Same as above, but with a custom commit interval.
  61. ImportantFileWriter(const FilePath& path,
  62. scoped_refptr<SequencedTaskRunner> task_runner,
  63. TimeDelta interval,
  64. const char* histogram_suffix = nullptr);
  65. // You have to ensure that there are no pending writes at the moment
  66. // of destruction.
  67. ~ImportantFileWriter();
  68. const FilePath& path() const { return path_; }
  69. // Returns true if there is a scheduled write pending which has not yet
  70. // been started.
  71. bool HasPendingWrite() const;
  72. // Save |data| to target filename. Does not block. If there is a pending write
  73. // scheduled by ScheduleWrite(), it is cancelled.
  74. void WriteNow(std::unique_ptr<std::string> data);
  75. // Schedule a save to target filename. Data will be serialized and saved
  76. // to disk after the commit interval. If another ScheduleWrite is issued
  77. // before that, only one serialization and write to disk will happen, and
  78. // the most recent |serializer| will be used. This operation does not block.
  79. // |serializer| should remain valid through the lifetime of
  80. // ImportantFileWriter.
  81. void ScheduleWrite(DataSerializer* serializer);
  82. // Serialize data pending to be saved and execute write on backend thread.
  83. void DoScheduledWrite();
  84. // Registers |before_next_write_callback| and |after_next_write_callback| to
  85. // be synchronously invoked from WriteFileAtomically() before its next write
  86. // and after its next write, respectively. The boolean passed to
  87. // |after_next_write_callback| indicates whether the write was successful.
  88. // Both callbacks must be thread safe as they will be called on |task_runner_|
  89. // and may be called during Chrome shutdown.
  90. // If called more than once before a write is scheduled on |task_runner|, the
  91. // latest callbacks clobber the others.
  92. void RegisterOnNextWriteCallbacks(
  93. OnceClosure before_next_write_callback,
  94. OnceCallback<void(bool success)> after_next_write_callback);
  95. TimeDelta commit_interval() const {
  96. return commit_interval_;
  97. }
  98. // Overrides the timer to use for scheduling writes with |timer_override|.
  99. void SetTimerForTesting(OneShotTimer* timer_override);
  100. private:
  101. const OneShotTimer& timer() const {
  102. return timer_override_ ? *timer_override_ : timer_;
  103. }
  104. OneShotTimer& timer() { return timer_override_ ? *timer_override_ : timer_; }
  105. // Helper function to call WriteFileAtomically() with a
  106. // std::unique_ptr<std::string>.
  107. static void WriteScopedStringToFileAtomically(
  108. const FilePath& path,
  109. std::unique_ptr<std::string> data,
  110. OnceClosure before_write_callback,
  111. OnceCallback<void(bool success)> after_write_callback,
  112. const std::string& histogram_suffix);
  113. // Writes |data| to |path|, recording histograms with an optional
  114. // |histogram_suffix|. |from_instance| indicates whether the call originates
  115. // from an instance of ImportantFileWriter or a direct call to
  116. // WriteFileAtomically. When false, the directory containing |path| is added
  117. // to the set cleaned by the ImportantFileWriterCleaner (Windows only).
  118. static bool WriteFileAtomicallyImpl(const FilePath& path,
  119. StringPiece data,
  120. StringPiece histogram_suffix,
  121. bool from_instance);
  122. void ClearPendingWrite();
  123. // Invoked synchronously on the next write event.
  124. OnceClosure before_next_write_callback_;
  125. OnceCallback<void(bool success)> after_next_write_callback_;
  126. // Path being written to.
  127. const FilePath path_;
  128. // TaskRunner for the thread on which file I/O can be done.
  129. const scoped_refptr<SequencedTaskRunner> task_runner_;
  130. // Timer used to schedule commit after ScheduleWrite.
  131. OneShotTimer timer_;
  132. // An override for |timer_| used for testing.
  133. OneShotTimer* timer_override_ = nullptr;
  134. // Serializer which will provide the data to be saved.
  135. DataSerializer* serializer_;
  136. // Time delta after which scheduled data will be written to disk.
  137. const TimeDelta commit_interval_;
  138. // Custom histogram suffix.
  139. const std::string histogram_suffix_;
  140. SEQUENCE_CHECKER(sequence_checker_);
  141. WeakPtrFactory<ImportantFileWriter> weak_factory_{this};
  142. DISALLOW_COPY_AND_ASSIGN(ImportantFileWriter);
  143. };
  144. } // namespace base
  145. #endif // BASE_FILES_IMPORTANT_FILE_WRITER_H_