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