123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- // Copyright 2020 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_CLEANER_H_
- #define BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_
- #include <atomic>
- #include <vector>
- #include "base/base_export.h"
- #include "base/containers/flat_set.h"
- #include "base/files/file_path.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/no_destructor.h"
- #include "base/numerics/clamped_math.h"
- #include "base/optional.h"
- #include "base/sequence_checker.h"
- #include "base/synchronization/lock.h"
- #include "base/thread_annotations.h"
- #include "base/time/time.h"
- namespace base {
- class SequencedTaskRunner;
- // A cleaner for forgotten .tmp files left behind by ImportantFileWriter; see
- // https://crbug.com/1075917.
- //
- // ImportantFileWriter has the potential to leak .tmp files in case of a crash
- // or power failure during processing, or in case of interference by third-party
- // software. This class implements a singleton that makes a single scan over
- // given directories to delete any *.tmp files older than the current process.
- // Processes that use ImportantFileWriter are expected to call the instance's
- // Start method at some point during startup to enable the cleaner.
- // ImportantFileWriter calls the AddDirectory method to provide the directory
- // hosting an "important" file. Hosting processes are expected to call the Stop
- // method at shutdown so that metrics of an in-process execution can be
- // recorded.
- //
- // The deletion scan takes place in a background task. Metrics are recorded when
- // a directory is fully processed, or shortly after the hosting process calls
- // the Stop method.
- class BASE_EXPORT ImportantFileWriterCleaner {
- public:
- // Gets the process-wide single instance of the cleaner.
- static ImportantFileWriterCleaner& GetInstance();
- ImportantFileWriterCleaner(const ImportantFileWriterCleaner&) = delete;
- ImportantFileWriterCleaner& operator=(const ImportantFileWriterCleaner&) =
- delete;
- ~ImportantFileWriterCleaner() = delete;
- // Adds |directory| to the set to be cleaned if it has not already been
- // handled. If the Start method has already been called, the cleaner will
- // begin processing |directory| after all others that have previously been
- // added have been cleaned (immediately, if there are no others). Any calls to
- // this method prior to Initialize are ignored.
- static void AddDirectory(const FilePath& directory);
- // Initializes the instance on the hosting process's main sequence (the one on
- // which Start and Stop will ultimately be called). It is safe to call this
- // any number of times from the main sequence.
- void Initialize();
- // Starts the instance. If any directories have already been added, the
- // background task is posted immediately to begin processing them. Otherwise,
- // the next call to AddDirectory will begin processing.
- void Start();
- // Stops the instance. The background task, if it is active, is notified to
- // record metrics on the directory in progress and exit.
- void Stop();
- // Brings the instance back to the uninitialized state. This should be used in
- // tests that call Initialize so that the instance forgets about the test's
- // main thread task runner.
- void UninitializeForTesting();
- private:
- friend class NoDestructor<ImportantFileWriterCleaner>;
- ImportantFileWriterCleaner();
- // True once Start() has been called; false following Stop();
- bool is_started() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return started_;
- }
- // True once the background task has been posted; false once it returns.
- bool is_running() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return running_;
- }
- // The workhorse for AddDirectory.
- void AddDirectoryImpl(const FilePath& directory);
- // Schedules the background task to run, processing all directories that have
- // accumulated.
- void ScheduleTask();
- // Iterates over the contents of |directories|, deleting all *.tmp files older
- // than |upper_bound_time|. Checks |stop_flag| after each deletion to see if
- // the instance has been stopped by the host process. Returns false if
- // processing was interrupted by |stop_flag| having been set, or true
- // indicating that all directories were fully processed.
- static bool CleanInBackground(Time upper_bound_time,
- std::vector<FilePath> directories,
- std::atomic_bool& stop_flag);
- // Cleans up after completion of the background task. |processing_completed|
- // is true when all directories were fully processed, or false if the task
- // potentially exited early in response to Stop().
- void OnBackgroundTaskFinished(bool processing_completed);
- // Finalizes a request to stop after the background task returns.
- void DoStop();
- // Provides exclusive access to the instance's task runner.
- Lock task_runner_lock_;
- // The hosting process's main thread task runner.
- scoped_refptr<SequencedTaskRunner> task_runner_ GUARDED_BY(task_runner_lock_);
- // The time before which any discovered temporary file is presumed to be
- // unused, and therefore safe to delete.
- const Time upper_bound_time_;
- // The set of all directories hosting files written by an ImportantFileWriter.
- flat_set<FilePath> important_directories_
- GUARDED_BY_CONTEXT(sequence_checker_);
- // Directories added to the instance waiting either for a call to Start() or
- // waiting for an existing background task to complete.
- std::vector<FilePath> pending_directories_
- GUARDED_BY_CONTEXT(sequence_checker_);
- std::atomic_bool stop_flag_{false};
- bool started_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
- bool running_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
- SEQUENCE_CHECKER(sequence_checker_);
- };
- } // namespace base
- #endif // BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_
|