important_file_writer_cleaner.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright 2020 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_CLEANER_H_
  5. #define BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_
  6. #include <atomic>
  7. #include <vector>
  8. #include "base/base_export.h"
  9. #include "base/containers/flat_set.h"
  10. #include "base/files/file_path.h"
  11. #include "base/memory/scoped_refptr.h"
  12. #include "base/no_destructor.h"
  13. #include "base/numerics/clamped_math.h"
  14. #include "base/optional.h"
  15. #include "base/sequence_checker.h"
  16. #include "base/synchronization/lock.h"
  17. #include "base/thread_annotations.h"
  18. #include "base/time/time.h"
  19. namespace base {
  20. class SequencedTaskRunner;
  21. // A cleaner for forgotten .tmp files left behind by ImportantFileWriter; see
  22. // https://crbug.com/1075917.
  23. //
  24. // ImportantFileWriter has the potential to leak .tmp files in case of a crash
  25. // or power failure during processing, or in case of interference by third-party
  26. // software. This class implements a singleton that makes a single scan over
  27. // given directories to delete any *.tmp files older than the current process.
  28. // Processes that use ImportantFileWriter are expected to call the instance's
  29. // Start method at some point during startup to enable the cleaner.
  30. // ImportantFileWriter calls the AddDirectory method to provide the directory
  31. // hosting an "important" file. Hosting processes are expected to call the Stop
  32. // method at shutdown so that metrics of an in-process execution can be
  33. // recorded.
  34. //
  35. // The deletion scan takes place in a background task. Metrics are recorded when
  36. // a directory is fully processed, or shortly after the hosting process calls
  37. // the Stop method.
  38. class BASE_EXPORT ImportantFileWriterCleaner {
  39. public:
  40. // Gets the process-wide single instance of the cleaner.
  41. static ImportantFileWriterCleaner& GetInstance();
  42. ImportantFileWriterCleaner(const ImportantFileWriterCleaner&) = delete;
  43. ImportantFileWriterCleaner& operator=(const ImportantFileWriterCleaner&) =
  44. delete;
  45. ~ImportantFileWriterCleaner() = delete;
  46. // Adds |directory| to the set to be cleaned if it has not already been
  47. // handled. If the Start method has already been called, the cleaner will
  48. // begin processing |directory| after all others that have previously been
  49. // added have been cleaned (immediately, if there are no others). Any calls to
  50. // this method prior to Initialize are ignored.
  51. static void AddDirectory(const FilePath& directory);
  52. // Initializes the instance on the hosting process's main sequence (the one on
  53. // which Start and Stop will ultimately be called). It is safe to call this
  54. // any number of times from the main sequence.
  55. void Initialize();
  56. // Starts the instance. If any directories have already been added, the
  57. // background task is posted immediately to begin processing them. Otherwise,
  58. // the next call to AddDirectory will begin processing.
  59. void Start();
  60. // Stops the instance. The background task, if it is active, is notified to
  61. // record metrics on the directory in progress and exit.
  62. void Stop();
  63. // Brings the instance back to the uninitialized state. This should be used in
  64. // tests that call Initialize so that the instance forgets about the test's
  65. // main thread task runner.
  66. void UninitializeForTesting();
  67. private:
  68. friend class NoDestructor<ImportantFileWriterCleaner>;
  69. ImportantFileWriterCleaner();
  70. // True once Start() has been called; false following Stop();
  71. bool is_started() const {
  72. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  73. return started_;
  74. }
  75. // True once the background task has been posted; false once it returns.
  76. bool is_running() const {
  77. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  78. return running_;
  79. }
  80. // The workhorse for AddDirectory.
  81. void AddDirectoryImpl(const FilePath& directory);
  82. // Schedules the background task to run, processing all directories that have
  83. // accumulated.
  84. void ScheduleTask();
  85. // Iterates over the contents of |directories|, deleting all *.tmp files older
  86. // than |upper_bound_time|. Checks |stop_flag| after each deletion to see if
  87. // the instance has been stopped by the host process. Returns false if
  88. // processing was interrupted by |stop_flag| having been set, or true
  89. // indicating that all directories were fully processed.
  90. static bool CleanInBackground(Time upper_bound_time,
  91. std::vector<FilePath> directories,
  92. std::atomic_bool& stop_flag);
  93. // Cleans up after completion of the background task. |processing_completed|
  94. // is true when all directories were fully processed, or false if the task
  95. // potentially exited early in response to Stop().
  96. void OnBackgroundTaskFinished(bool processing_completed);
  97. // Finalizes a request to stop after the background task returns.
  98. void DoStop();
  99. // Provides exclusive access to the instance's task runner.
  100. Lock task_runner_lock_;
  101. // The hosting process's main thread task runner.
  102. scoped_refptr<SequencedTaskRunner> task_runner_ GUARDED_BY(task_runner_lock_);
  103. // The time before which any discovered temporary file is presumed to be
  104. // unused, and therefore safe to delete.
  105. const Time upper_bound_time_;
  106. // The set of all directories hosting files written by an ImportantFileWriter.
  107. flat_set<FilePath> important_directories_
  108. GUARDED_BY_CONTEXT(sequence_checker_);
  109. // Directories added to the instance waiting either for a call to Start() or
  110. // waiting for an existing background task to complete.
  111. std::vector<FilePath> pending_directories_
  112. GUARDED_BY_CONTEXT(sequence_checker_);
  113. std::atomic_bool stop_flag_{false};
  114. bool started_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
  115. bool running_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
  116. SEQUENCE_CHECKER(sequence_checker_);
  117. };
  118. } // namespace base
  119. #endif // BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_