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

Side by Side Diff: net/base/file_stream_context.cc

Issue 10701050: net: Implement canceling of all async operations in FileStream. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 1 month 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 (c) 2012 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 "net/base/file_stream_context.h"
6
7 #include "base/location.h"
8 #include "base/message_loop_proxy.h"
9 #include "base/task_runner_util.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "base/threading/worker_pool.h"
12 #include "net/base/file_stream_net_log_parameters.h"
13 #include "net/base/net_errors.h"
14
15 namespace {
16
17 void CallInt64ToInt(const net::CompletionCallback& callback, int64 result) {
18 callback.Run(static_cast<int>(result));
19 }
20
21 }
22
23 namespace net {
24
25 void FileStream::Context::Orphan() {
26 DCHECK(!orphaned_);
27
28 orphaned_ = true;
29 if (file_ != base::kInvalidPlatformFileValue)
30 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_OPEN);
31
32 if (!async_in_progress_) {
33 CloseAndDelete();
34 } else if (file_ != base::kInvalidPlatformFileValue) {
35 CancelIo(file_);
36 }
37 }
38
39 void FileStream::Context::OpenAsync(const FilePath& path,
40 int open_flags,
41 const CompletionCallback& callback) {
42 DCHECK(!async_in_progress_);
43
44 BeginOpenEvent(path);
45
46 const bool posted = base::PostTaskAndReplyWithResult(
47 base::WorkerPool::GetTaskRunner(true /* task_is_slow */),
48 FROM_HERE,
49 base::Bind(&Context::OpenFileImpl,
50 base::Unretained(this), path, open_flags),
51 base::Bind(&Context::OnOpenCompleted,
52 base::Unretained(this), callback));
53 DCHECK(posted);
54
55 async_in_progress_ = true;
56 }
57
58 int FileStream::Context::OpenSync(const FilePath& path, int open_flags) {
59 DCHECK(!async_in_progress_);
60
61 BeginOpenEvent(path);
62 OpenResult result = OpenFileImpl(path, open_flags);
63 file_ = result.file;
64 if (file_ == base::kInvalidPlatformFileValue) {
65 result.error_code = ProcessOpenError(result.error_code);
66 } else {
67 // TODO(satorux): Remove this once all async clients are migrated to use
68 // Open(). crbug.com/114783
69 if (open_flags & base::PLATFORM_FILE_ASYNC)
70 OnAsyncFileOpened();
71 }
72 return result.error_code;
73 }
74
75 void FileStream::Context::CloseSync() {
76 DCHECK(!async_in_progress_);
77 if (file_ != base::kInvalidPlatformFileValue) {
78 base::ClosePlatformFile(file_);
79 file_ = base::kInvalidPlatformFileValue;
80 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_OPEN);
81 }
82 }
83
84 void FileStream::Context::SeekAsync(Whence whence,
85 int64 offset,
86 const Int64CompletionCallback& callback) {
87 DCHECK(!async_in_progress_);
88
89 const bool posted = base::PostTaskAndReplyWithResult(
90 base::WorkerPool::GetTaskRunner(true /* task is slow */),
91 FROM_HERE,
92 base::Bind(&Context::SeekFileImpl,
93 base::Unretained(this), whence, offset),
94 base::Bind(&Context::ProcessAsyncResult,
95 base::Unretained(this), callback, FILE_ERROR_SOURCE_SEEK));
96 DCHECK(posted);
97
98 async_in_progress_ = true;
99 }
100
101 int64 FileStream::Context::SeekSync(Whence whence, int64 offset) {
102 int64 result = SeekFileImpl(whence, offset);
103 CheckForIOError(&result, FILE_ERROR_SOURCE_SEEK);
104 return result;
105 }
106
107 void FileStream::Context::FlushAsync(const CompletionCallback& callback) {
108 DCHECK(!async_in_progress_);
109
110 const bool posted = base::PostTaskAndReplyWithResult(
111 base::WorkerPool::GetTaskRunner(true /* task is slow */),
112 FROM_HERE,
113 base::Bind(&Context::FlushFileImpl,
114 base::Unretained(this)),
115 base::Bind(&Context::ProcessAsyncResult,
116 base::Unretained(this), IntToInt64(callback),
117 FILE_ERROR_SOURCE_FLUSH));
118 DCHECK(posted);
119
120 async_in_progress_ = true;
121 }
122
123 int FileStream::Context::FlushSync() {
124 int64 result = FlushFileImpl();
125 CheckForIOError(&result, FILE_ERROR_SOURCE_FLUSH);
126 return result;
127 }
128
129 int FileStream::Context::RecordAndMapError(int error,
130 FileErrorSource source) const {
131 // The following check is against incorrect use or bug. File descriptor
132 // shouldn't ever be closed outside of FileStream while it still tries to do
133 // something with it.
134 DCHECK(error != ERROR_BAD_FILE);
135 Error net_error = MapSystemError(error);
136
137 if (!orphaned_) {
138 bound_net_log_.AddEvent(NetLog::TYPE_FILE_STREAM_ERROR,
139 base::Bind(&NetLogFileStreamErrorCallback,
140 source, error, net_error));
141 }
142 RecordFileError(error, source, record_uma_);
143 return net_error;
144 }
145
146 void FileStream::Context::BeginOpenEvent(const FilePath& path) {
147 std::string file_name = path.AsUTF8Unsafe();
148 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_OPEN,
149 NetLog::StringCallback("file_name", &file_name));
150 }
151
152 FileStream::Context::OpenResult FileStream::Context::OpenFileImpl(
153 const FilePath& path, int open_flags) {
154 OpenResult result;
155 result.error_code = OK;
156 result.file = base::CreatePlatformFile(path, open_flags, NULL, NULL);
157 if (result.file == base::kInvalidPlatformFileValue)
158 result.error_code = GetLastErrno();
159
160 return result;
161 }
162
163 int FileStream::Context::ProcessOpenError(int error_code) {
164 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_OPEN);
165 return RecordAndMapError(error_code, FILE_ERROR_SOURCE_OPEN);
166 }
167
168 void FileStream::Context::OnOpenCompleted(const CompletionCallback& callback,
169 OpenResult result) {
170 file_ = result.file;
171 if (file_ == base::kInvalidPlatformFileValue)
172 result.error_code = ProcessOpenError(result.error_code);
173 else if (!orphaned_)
174 OnAsyncFileOpened();
175 OnAsyncCompleted(IntToInt64(callback), result.error_code);
176 }
177
178 void FileStream::Context::CloseAndDelete() {
179 DCHECK(!async_in_progress_);
180
181 if (file_ == base::kInvalidPlatformFileValue) {
182 delete this;
183 } else {
184 const bool posted = base::WorkerPool::PostTaskAndReply(
185 FROM_HERE,
186 base::Bind(base::IgnoreResult(&base::ClosePlatformFile), file_),
187 base::Bind(&Context::OnCloseCompleted, base::Unretained(this)),
188 true /* task_is_slow */);
189 DCHECK(posted);
190 file_ = base::kInvalidPlatformFileValue;
191 }
192 }
193
194 void FileStream::Context::OnCloseCompleted() {
195 delete this;
196 }
197
198 Int64CompletionCallback FileStream::Context::IntToInt64(
199 const CompletionCallback& callback) {
200 return base::Bind(&CallInt64ToInt, callback);
201 }
202
203 void FileStream::Context::CheckForIOError(int64* result,
204 FileErrorSource source) {
205 if (*result < 0)
206 *result = RecordAndMapError(static_cast<int>(*result), source);
207 }
208
209 void FileStream::Context::ProcessAsyncResult(
210 const Int64CompletionCallback& callback,
211 FileErrorSource source,
212 int64 result) {
213 CheckForIOError(&result, source);
214 OnAsyncCompleted(callback, result);
215 }
216
217 void FileStream::Context::OnAsyncCompleted(
218 const Int64CompletionCallback& callback,
219 int64 result) {
220 // Reset this before Run() as Run() may issue a new async operation. Also it
221 // should be reset before CloseAsync() because it shouldn't run if any async
222 // operation is in progress.
223 async_in_progress_ = false;
224 if (orphaned_)
225 CloseAndDelete();
226 else
227 callback.Run(result);
228 }
229
230 } // namespace net
231
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698