// Copyright (c) 2012 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_FILES_IMPORTANT_FILE_WRITER_H_
#define BASE_FILES_IMPORTANT_FILE_WRITER_H_

#include <string>

#include "base/base_export.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/timer/timer.h"

namespace base {

class SequencedTaskRunner;

// Helper for atomically writing a file to ensure that it won't be corrupted by
// *application* crash during write (implemented as create, flush, rename).
//
// As an added benefit, ImportantFileWriter makes it less likely that the file
// is corrupted by *system* crash, though even if the ImportantFileWriter call
// has already returned at the time of the crash it is not specified which
// version of the file (old or new) is preserved. And depending on system
// configuration (hardware and software) a significant likelihood of file
// corruption may remain, thus using ImportantFileWriter is not a valid
// substitute for file integrity checks and recovery codepaths for malformed
// files.
//
// Also note that ImportantFileWriter can be *really* slow (cf. File::Flush()
// for details) and thus please don't block shutdown on ImportantFileWriter.
class BASE_EXPORT ImportantFileWriter {
 public:
  // Used by ScheduleSave to lazily provide the data to be saved. Allows us
  // to also batch data serializations.
  class BASE_EXPORT DataSerializer {
   public:
    // Should put serialized string in |data| and return true on successful
    // serialization. Will be called on the same thread on which
    // ImportantFileWriter has been created.
    virtual bool SerializeData(std::string* data) = 0;

   protected:
    virtual ~DataSerializer() = default;
  };

  // Save |data| to |path| in an atomic manner. Blocks and writes data on the
  // current thread. Does not guarantee file integrity across system crash (see
  // the class comment above).
  static bool WriteFileAtomically(const FilePath& path,
                                  StringPiece data,
                                  StringPiece histogram_suffix = StringPiece());

  // Initialize the writer.
  // |path| is the name of file to write.
  // |task_runner| is the SequencedTaskRunner instance where on which we will
  // execute file I/O operations.
  // All non-const methods, ctor and dtor must be called on the same thread.
  ImportantFileWriter(const FilePath& path,
                      scoped_refptr<SequencedTaskRunner> task_runner,
                      const char* histogram_suffix = nullptr);

  // Same as above, but with a custom commit interval.
  ImportantFileWriter(const FilePath& path,
                      scoped_refptr<SequencedTaskRunner> task_runner,
                      TimeDelta interval,
                      const char* histogram_suffix = nullptr);

  // You have to ensure that there are no pending writes at the moment
  // of destruction.
  ~ImportantFileWriter();

  const FilePath& path() const { return path_; }

  // Returns true if there is a scheduled write pending which has not yet
  // been started.
  bool HasPendingWrite() const;

  // Save |data| to target filename. Does not block. If there is a pending write
  // scheduled by ScheduleWrite(), it is cancelled.
  void WriteNow(std::unique_ptr<std::string> data);

  // Schedule a save to target filename. Data will be serialized and saved
  // to disk after the commit interval. If another ScheduleWrite is issued
  // before that, only one serialization and write to disk will happen, and
  // the most recent |serializer| will be used. This operation does not block.
  // |serializer| should remain valid through the lifetime of
  // ImportantFileWriter.
  void ScheduleWrite(DataSerializer* serializer);

  // Serialize data pending to be saved and execute write on backend thread.
  void DoScheduledWrite();

  // Registers |before_next_write_callback| and |after_next_write_callback| to
  // be synchronously invoked from WriteFileAtomically() before its next write
  // and after its next write, respectively. The boolean passed to
  // |after_next_write_callback| indicates whether the write was successful.
  // Both callbacks must be thread safe as they will be called on |task_runner_|
  // and may be called during Chrome shutdown.
  // If called more than once before a write is scheduled on |task_runner|, the
  // latest callbacks clobber the others.
  void RegisterOnNextWriteCallbacks(
      const Closure& before_next_write_callback,
      const Callback<void(bool success)>& after_next_write_callback);

  TimeDelta commit_interval() const {
    return commit_interval_;
  }

  // Overrides the timer to use for scheduling writes with |timer_override|.
  void SetTimerForTesting(OneShotTimer* timer_override);

 private:
  const OneShotTimer& timer() const {
    return timer_override_ ? *timer_override_ : timer_;
  }
  OneShotTimer& timer() { return timer_override_ ? *timer_override_ : timer_; }

  void ClearPendingWrite();

  // Invoked synchronously on the next write event.
  Closure before_next_write_callback_;
  Callback<void(bool success)> after_next_write_callback_;

  // Path being written to.
  const FilePath path_;

  // TaskRunner for the thread on which file I/O can be done.
  const scoped_refptr<SequencedTaskRunner> task_runner_;

  // Timer used to schedule commit after ScheduleWrite.
  OneShotTimer timer_;

  // An override for |timer_| used for testing.
  OneShotTimer* timer_override_ = nullptr;

  // Serializer which will provide the data to be saved.
  DataSerializer* serializer_;

  // Time delta after which scheduled data will be written to disk.
  const TimeDelta commit_interval_;

  // Custom histogram suffix.
  const std::string histogram_suffix_;

  SEQUENCE_CHECKER(sequence_checker_);

  WeakPtrFactory<ImportantFileWriter> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(ImportantFileWriter);
};

}  // namespace base

#endif  // BASE_FILES_IMPORTANT_FILE_WRITER_H_
