mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2025-02-27 04:13:18 +03:00
155 lines
6.1 KiB
C
155 lines
6.1 KiB
C
|
// 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();
|
||
|
|
||
|
// Returns the upper-bound time. Files with modification times older than this
|
||
|
// are assumed to have been orphaned by a previous instance of the process.
|
||
|
base::Time GetUpperBoundTimeForTest() const;
|
||
|
|
||
|
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_
|