Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: chrome/browser/chromeos/base/file_flusher.cc

Issue 1815853002: cros: Flush profile files at critical moments (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nits and create test files to fix trybots Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 #include "chrome/browser/chromeos/base/file_flusher.h"
6
7 #include <set>
8
9 #include "base/bind.h"
10 #include "base/files/file.h"
11 #include "base/files/file_enumerator.h"
12 #include "base/logging.h"
13 #include "base/synchronization/cancellation_flag.h"
14 #include "content/public/browser/browser_thread.h"
15
16 namespace chromeos {
17
18 namespace {
19
20 std::set<base::FilePath> MakeAbsoutePathSet(
21 const base::FilePath& base,
22 const std::vector<base::FilePath>& paths) {
23 std::set<base::FilePath> result;
24 for (const auto& path : paths) {
25 result.insert(path.IsAbsolute() ? path : base.Append(path));
26 }
27 return result;
28 }
29
30 } // namespace
31
32 ////////////////////////////////////////////////////////////////////////////////
33 // FileFlusher::Job
34
35 class FileFlusher::Job {
36 public:
37 Job(const base::WeakPtr<FileFlusher>& master,
38 const base::FilePath& path,
39 const std::vector<base::FilePath>& excludes,
40 const FileFlusher::OnFlushCallback& on_flush_callback,
41 const base::Closure& callback);
42 ~Job() = default;
43
44 void Start();
45 void Cancel();
46
47 const base::FilePath& path() const { return path_; }
48 bool started() const { return started_; }
49
50 private:
51 // Flush files on a blocking pool thread.
52 void FlushOnBlockingPool();
53
54 // Whether to exclude the |path| from flushing.
55 bool ShouldExclude(const base::FilePath& path) const;
56
57 // Schedule a FinishOnUIThread task to run on the UI thread.
58 void ScheduleFinish();
59
60 // Finish the job by notifying |master_| and self destruct on the UI thread.
61 void FinishOnUIThread();
62
63 base::WeakPtr<FileFlusher> master_;
64 const base::FilePath path_;
65 const std::set<base::FilePath> excludes_;
66 const FileFlusher::OnFlushCallback on_flush_callback_;
67 const base::Closure callback_;
68
69 bool started_ = false;
70 base::CancellationFlag cancel_flag_;
71
72 DISALLOW_COPY_AND_ASSIGN(Job);
73 };
74
75 FileFlusher::Job::Job(const base::WeakPtr<FileFlusher>& master,
76 const base::FilePath& path,
77 const std::vector<base::FilePath>& excludes,
78 const FileFlusher::OnFlushCallback& on_flush_callback,
79 const base::Closure& callback)
80 : master_(master),
81 path_(path),
82 excludes_(MakeAbsoutePathSet(path, excludes)),
83 on_flush_callback_(on_flush_callback),
84 callback_(callback) {}
85
86 void FileFlusher::Job::Start() {
87 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
88 DCHECK(!started());
89
90 started_ = true;
91
92 if (cancel_flag_.IsSet()) {
93 ScheduleFinish();
94 return;
95 }
96
97 content::BrowserThread::PostBlockingPoolTaskAndReply(
98 FROM_HERE, base::Bind(&FileFlusher::Job::FlushOnBlockingPool,
99 base::Unretained(this)),
100 base::Bind(&FileFlusher::Job::FinishOnUIThread, base::Unretained(this)));
101 }
102
103 void FileFlusher::Job::Cancel() {
104 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
105
106 cancel_flag_.Set();
107
108 // Cancel() could be called in an iterator/range loop in master thus don't
109 // invoke FinishOnUIThread in-place.
110 if (!started())
111 ScheduleFinish();
112 }
113
114 void FileFlusher::Job::FlushOnBlockingPool() {
115 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
116
117 VLOG(1) << "Flushing files under " << path_.value();
118
119 base::FileEnumerator traversal(path_, true /* recursive */,
120 base::FileEnumerator::FILES);
121 for (base::FilePath current = traversal.Next();
122 !current.empty() && !cancel_flag_.IsSet(); current = traversal.Next()) {
123 if (ShouldExclude(current))
124 continue;
125
126 base::File currentFile(current,
127 base::File::FLAG_OPEN | base::File::FLAG_WRITE);
128 if (!currentFile.IsValid()) {
129 VLOG(1) << "Unable to flush file:" << current.value();
130 continue;
131 }
132
133 currentFile.Flush();
134 currentFile.Close();
135
136 if (!on_flush_callback_.is_null())
137 on_flush_callback_.Run(current);
138 }
139 }
140
141 bool FileFlusher::Job::ShouldExclude(const base::FilePath& path) const {
142 return excludes_.find(path) != excludes_.end();
143 }
144
145 void FileFlusher::Job::ScheduleFinish() {
146 content::BrowserThread::PostTask(
147 content::BrowserThread::UI, FROM_HERE,
148 base::Bind(&Job::FinishOnUIThread, base::Unretained(this)));
149 }
150
151 void FileFlusher::Job::FinishOnUIThread() {
152 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
153
154 if (!callback_.is_null())
155 callback_.Run();
156
157 if (master_)
158 master_->OnJobDone(this);
159
160 delete this;
161 }
162
163 ////////////////////////////////////////////////////////////////////////////////
164 // FileFlusher
165
166 FileFlusher::FileFlusher() : weak_factory_(this) {}
167
168 FileFlusher::~FileFlusher() {
169 for (const auto& job : jobs_)
170 job->Cancel();
171 }
172
173 void FileFlusher::RequestFlush(const base::FilePath& path,
174 const std::vector<base::FilePath>& excludes,
175 const base::Closure& callback) {
176 for (const auto& job : jobs_) {
177 if (path == job->path() || path.IsParent(job->path()))
178 job->Cancel();
179 }
180
181 jobs_.push_back(new Job(weak_factory_.GetWeakPtr(), path, excludes,
182 on_flush_callback_for_test_, callback));
183 ScheduleJob();
184 }
185
186 void FileFlusher::ScheduleJob() {
187 if (jobs_.empty())
188 return;
189
190 auto job = jobs_.front();
191 if (!job->started())
192 job->Start();
193 }
194
195 void FileFlusher::OnJobDone(FileFlusher::Job* job) {
196 for (auto it = jobs_.begin(); it != jobs_.end(); ++it) {
197 if (*it == job) {
198 jobs_.erase(it);
199 break;
200 }
201 }
202
203 ScheduleJob();
204 }
205
206 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/base/file_flusher.h ('k') | chrome/browser/chromeos/base/file_flusher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698