[sql] Callback and scoped-ignore tests for sql::Statement.
[chromium-blink-merge.git] / net / base / file_stream_context.cc
blobabc058a9ca8dfa1f8c41536edb5e84ce2e017129
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.
5 #include "net/base/file_stream_context.h"
7 #include "base/location.h"
8 #include "base/message_loop/message_loop_proxy.h"
9 #include "base/task_runner_util.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "net/base/file_stream_net_log_parameters.h"
12 #include "net/base/net_errors.h"
14 namespace {
16 void CallInt64ToInt(const net::CompletionCallback& callback, int64 result) {
17 callback.Run(static_cast<int>(result));
22 namespace net {
24 FileStream::Context::IOResult::IOResult()
25 : result(OK),
26 os_error(0) {
29 FileStream::Context::IOResult::IOResult(int64 result, int os_error)
30 : result(result),
31 os_error(os_error) {
34 // static
35 FileStream::Context::IOResult FileStream::Context::IOResult::FromOSError(
36 int64 os_error) {
37 return IOResult(MapSystemError(os_error), os_error);
40 FileStream::Context::OpenResult::OpenResult()
41 : file(base::kInvalidPlatformFileValue) {
44 FileStream::Context::OpenResult::OpenResult(base::PlatformFile file,
45 IOResult error_code)
46 : file(file),
47 error_code(error_code) {
50 void FileStream::Context::Orphan() {
51 DCHECK(!orphaned_);
53 orphaned_ = true;
54 if (file_ != base::kInvalidPlatformFileValue)
55 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_OPEN);
57 if (!async_in_progress_) {
58 CloseAndDelete();
59 } else if (file_ != base::kInvalidPlatformFileValue) {
60 CancelIo(file_);
64 void FileStream::Context::OpenAsync(const base::FilePath& path,
65 int open_flags,
66 const CompletionCallback& callback) {
67 DCHECK(!async_in_progress_);
69 BeginOpenEvent(path);
71 const bool posted = base::PostTaskAndReplyWithResult(
72 task_runner_.get(),
73 FROM_HERE,
74 base::Bind(
75 &Context::OpenFileImpl, base::Unretained(this), path, open_flags),
76 base::Bind(&Context::OnOpenCompleted, base::Unretained(this), callback));
77 DCHECK(posted);
79 async_in_progress_ = true;
82 int FileStream::Context::OpenSync(const base::FilePath& path, int open_flags) {
83 DCHECK(!async_in_progress_);
85 BeginOpenEvent(path);
86 OpenResult result = OpenFileImpl(path, open_flags);
87 file_ = result.file;
88 if (file_ == base::kInvalidPlatformFileValue) {
89 ProcessOpenError(result.error_code);
90 } else {
91 // TODO(satorux): Remove this once all async clients are migrated to use
92 // Open(). crbug.com/114783
93 if (open_flags & base::PLATFORM_FILE_ASYNC)
94 OnAsyncFileOpened();
96 return result.error_code.result;
99 void FileStream::Context::CloseSync() {
100 DCHECK(!async_in_progress_);
101 if (file_ != base::kInvalidPlatformFileValue) {
102 base::ClosePlatformFile(file_);
103 file_ = base::kInvalidPlatformFileValue;
104 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_OPEN);
108 void FileStream::Context::SeekAsync(Whence whence,
109 int64 offset,
110 const Int64CompletionCallback& callback) {
111 DCHECK(!async_in_progress_);
113 const bool posted = base::PostTaskAndReplyWithResult(
114 task_runner_.get(),
115 FROM_HERE,
116 base::Bind(
117 &Context::SeekFileImpl, base::Unretained(this), whence, offset),
118 base::Bind(&Context::ProcessAsyncResult,
119 base::Unretained(this),
120 callback,
121 FILE_ERROR_SOURCE_SEEK));
122 DCHECK(posted);
124 async_in_progress_ = true;
127 int64 FileStream::Context::SeekSync(Whence whence, int64 offset) {
128 IOResult result = SeekFileImpl(whence, offset);
129 RecordError(result, FILE_ERROR_SOURCE_SEEK);
130 return result.result;
133 void FileStream::Context::FlushAsync(const CompletionCallback& callback) {
134 DCHECK(!async_in_progress_);
136 const bool posted = base::PostTaskAndReplyWithResult(
137 task_runner_.get(),
138 FROM_HERE,
139 base::Bind(&Context::FlushFileImpl, base::Unretained(this)),
140 base::Bind(&Context::ProcessAsyncResult,
141 base::Unretained(this),
142 IntToInt64(callback),
143 FILE_ERROR_SOURCE_FLUSH));
144 DCHECK(posted);
146 async_in_progress_ = true;
149 int FileStream::Context::FlushSync() {
150 IOResult result = FlushFileImpl();
151 RecordError(result, FILE_ERROR_SOURCE_FLUSH);
152 return result.result;
155 void FileStream::Context::RecordError(const IOResult& result,
156 FileErrorSource source) const {
157 if (result.result >= 0) {
158 // |result| is not an error.
159 return;
162 // The following check is against incorrect use or bug. File descriptor
163 // shouldn't ever be closed outside of FileStream while it still tries to do
164 // something with it.
165 DCHECK_NE(result.result, ERR_INVALID_HANDLE);
167 if (!orphaned_) {
168 bound_net_log_.AddEvent(
169 NetLog::TYPE_FILE_STREAM_ERROR,
170 base::Bind(&NetLogFileStreamErrorCallback,
171 source, result.os_error,
172 static_cast<net::Error>(result.result)));
175 RecordFileError(result.os_error, source, record_uma_);
178 void FileStream::Context::BeginOpenEvent(const base::FilePath& path) {
179 std::string file_name = path.AsUTF8Unsafe();
180 bound_net_log_.BeginEvent(NetLog::TYPE_FILE_STREAM_OPEN,
181 NetLog::StringCallback("file_name", &file_name));
184 FileStream::Context::OpenResult FileStream::Context::OpenFileImpl(
185 const base::FilePath& path, int open_flags) {
186 // FileStream::Context actually closes the file asynchronously, independently
187 // from FileStream's destructor. It can cause problems for users wanting to
188 // delete the file right after FileStream deletion. Thus we are always
189 // adding SHARE_DELETE flag to accommodate such use case.
190 open_flags |= base::PLATFORM_FILE_SHARE_DELETE;
191 base::PlatformFile file =
192 base::CreatePlatformFile(path, open_flags, NULL, NULL);
193 if (file == base::kInvalidPlatformFileValue)
194 return OpenResult(file, IOResult::FromOSError(GetLastErrno()));
196 return OpenResult(file, IOResult(OK, 0));
199 void FileStream::Context::ProcessOpenError(const IOResult& error_code) {
200 bound_net_log_.EndEvent(NetLog::TYPE_FILE_STREAM_OPEN);
201 RecordError(error_code, FILE_ERROR_SOURCE_OPEN);
204 void FileStream::Context::OnOpenCompleted(const CompletionCallback& callback,
205 OpenResult open_result) {
206 file_ = open_result.file;
207 if (file_ == base::kInvalidPlatformFileValue)
208 ProcessOpenError(open_result.error_code);
209 else if (!orphaned_)
210 OnAsyncFileOpened();
211 OnAsyncCompleted(IntToInt64(callback), open_result.error_code.result);
214 void FileStream::Context::CloseAndDelete() {
215 DCHECK(!async_in_progress_);
217 if (file_ == base::kInvalidPlatformFileValue) {
218 delete this;
219 } else {
220 const bool posted = task_runner_->PostTaskAndReply(
221 FROM_HERE,
222 base::Bind(base::IgnoreResult(&base::ClosePlatformFile), file_),
223 base::Bind(&Context::OnCloseCompleted, base::Unretained(this)));
224 DCHECK(posted);
225 file_ = base::kInvalidPlatformFileValue;
229 void FileStream::Context::OnCloseCompleted() {
230 delete this;
233 Int64CompletionCallback FileStream::Context::IntToInt64(
234 const CompletionCallback& callback) {
235 return base::Bind(&CallInt64ToInt, callback);
238 void FileStream::Context::ProcessAsyncResult(
239 const Int64CompletionCallback& callback,
240 FileErrorSource source,
241 const IOResult& result) {
242 RecordError(result, source);
243 OnAsyncCompleted(callback, result.result);
246 void FileStream::Context::OnAsyncCompleted(
247 const Int64CompletionCallback& callback,
248 int64 result) {
249 // Reset this before Run() as Run() may issue a new async operation. Also it
250 // should be reset before CloseAsync() because it shouldn't run if any async
251 // operation is in progress.
252 async_in_progress_ = false;
253 if (orphaned_)
254 CloseAndDelete();
255 else
256 callback.Run(result);
259 } // namespace net