Home | History | Annotate | Download | only in files
      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/strings/string_piece.h"
     16 #include "base/threading/non_thread_safe.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 : public NonThreadSafe {
     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() {}
     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, StringPiece data);
     57 
     58   // Initialize the writer.
     59   // |path| is the name of file to write.
     60   // |task_runner| is the SequencedTaskRunner instance where on which we will
     61   // execute file I/O operations.
     62   // All non-const methods, ctor and dtor must be called on the same thread.
     63   ImportantFileWriter(const FilePath& path,
     64                       scoped_refptr<SequencedTaskRunner> task_runner);
     65 
     66   // Same as above, but with a custom commit interval.
     67   ImportantFileWriter(const FilePath& path,
     68                       scoped_refptr<SequencedTaskRunner> task_runner,
     69                       TimeDelta interval);
     70 
     71   // You have to ensure that there are no pending writes at the moment
     72   // of destruction.
     73   ~ImportantFileWriter();
     74 
     75   const FilePath& path() const { return path_; }
     76 
     77   // Returns true if there is a scheduled write pending which has not yet
     78   // been started.
     79   bool HasPendingWrite() const;
     80 
     81   // Save |data| to target filename. Does not block. If there is a pending write
     82   // scheduled by ScheduleWrite(), it is cancelled.
     83   void WriteNow(std::unique_ptr<std::string> data);
     84 
     85   // Schedule a save to target filename. Data will be serialized and saved
     86   // to disk after the commit interval. If another ScheduleWrite is issued
     87   // before that, only one serialization and write to disk will happen, and
     88   // the most recent |serializer| will be used. This operation does not block.
     89   // |serializer| should remain valid through the lifetime of
     90   // ImportantFileWriter.
     91   void ScheduleWrite(DataSerializer* serializer);
     92 
     93   // Serialize data pending to be saved and execute write on backend thread.
     94   void DoScheduledWrite();
     95 
     96   // Registers |before_next_write_callback| and |after_next_write_callback| to
     97   // be synchronously invoked from WriteFileAtomically() before its next write
     98   // and after its next write, respectively. The boolean passed to
     99   // |after_next_write_callback| indicates whether the write was successful.
    100   // Both callbacks must be thread safe as they will be called on |task_runner_|
    101   // and may be called during Chrome shutdown.
    102   // If called more than once before a write is scheduled on |task_runner|, the
    103   // latest callbacks clobber the others.
    104   void RegisterOnNextWriteCallbacks(
    105       const Closure& before_next_write_callback,
    106       const Callback<void(bool success)>& after_next_write_callback);
    107 
    108   TimeDelta commit_interval() const {
    109     return commit_interval_;
    110   }
    111 
    112  private:
    113   // Invoked synchronously on the next write event.
    114   Closure before_next_write_callback_;
    115   Callback<void(bool success)> after_next_write_callback_;
    116 
    117   // Path being written to.
    118   const FilePath path_;
    119 
    120   // TaskRunner for the thread on which file I/O can be done.
    121   const scoped_refptr<SequencedTaskRunner> task_runner_;
    122 
    123   // Timer used to schedule commit after ScheduleWrite.
    124   OneShotTimer timer_;
    125 
    126   // Serializer which will provide the data to be saved.
    127   DataSerializer* serializer_;
    128 
    129   // Time delta after which scheduled data will be written to disk.
    130   const TimeDelta commit_interval_;
    131 
    132   WeakPtrFactory<ImportantFileWriter> weak_factory_;
    133 
    134   DISALLOW_COPY_AND_ASSIGN(ImportantFileWriter);
    135 };
    136 
    137 }  // namespace base
    138 
    139 #endif  // BASE_FILES_IMPORTANT_FILE_WRITER_H_
    140