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

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

Issue 935333002: Update from https://crrev.com/316786 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « net/base/file_stream_context.cc ('k') | net/base/mime_util.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/file_stream_context.h" 5 #include "net/base/file_stream_context.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h" 12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/profiler/scoped_tracker.h"
15 #include "base/task_runner.h" 14 #include "base/task_runner.h"
16 #include "base/threading/worker_pool.h" 15 #include "base/threading/worker_pool.h"
17 #include "net/base/io_buffer.h" 16 #include "net/base/io_buffer.h"
18 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
19 18
20 namespace net { 19 namespace net {
21 20
22 namespace { 21 namespace {
23 22
24 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { 23 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
25 overlapped->Offset = offset.LowPart; 24 overlapped->Offset = offset.LowPart;
26 overlapped->OffsetHigh = offset.HighPart; 25 overlapped->OffsetHigh = offset.HighPart;
27 } 26 }
28 27
29 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) { 28 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
30 LARGE_INTEGER offset; 29 LARGE_INTEGER offset;
31 offset.LowPart = overlapped->Offset; 30 offset.LowPart = overlapped->Offset;
32 offset.HighPart = overlapped->OffsetHigh; 31 offset.HighPart = overlapped->OffsetHigh;
33 offset.QuadPart += static_cast<LONGLONG>(count); 32 offset.QuadPart += static_cast<LONGLONG>(count);
34 SetOffset(overlapped, offset); 33 SetOffset(overlapped, offset);
35 } 34 }
36 35
37 } // namespace 36 } // namespace
38 37
39 FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner) 38 FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner)
40 : io_context_(), 39 : io_context_(),
41 async_in_progress_(false), 40 async_in_progress_(false),
42 orphaned_(false), 41 orphaned_(false),
43 task_runner_(task_runner), 42 task_runner_(task_runner),
44 weak_ptr_factory_(this) { 43 async_read_initiated_(false),
44 async_read_completed_(false),
45 io_complete_for_read_received_(false),
46 result_(0) {
45 io_context_.handler = this; 47 io_context_.handler = this;
46 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); 48 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
47 } 49 }
48 50
49 FileStream::Context::Context(base::File file, 51 FileStream::Context::Context(base::File file,
50 const scoped_refptr<base::TaskRunner>& task_runner) 52 const scoped_refptr<base::TaskRunner>& task_runner)
51 : io_context_(), 53 : io_context_(),
52 file_(file.Pass()), 54 file_(file.Pass()),
53 async_in_progress_(false), 55 async_in_progress_(false),
54 orphaned_(false), 56 orphaned_(false),
55 task_runner_(task_runner), 57 task_runner_(task_runner),
56 weak_ptr_factory_(this) { 58 async_read_initiated_(false),
59 async_read_completed_(false),
60 io_complete_for_read_received_(false),
61 result_(0) {
57 io_context_.handler = this; 62 io_context_.handler = this;
58 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); 63 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
59 if (file_.IsValid()) { 64 if (file_.IsValid()) {
60 // TODO(hashimoto): Check that file_ is async. 65 // TODO(hashimoto): Check that file_ is async.
61 OnFileOpened(); 66 OnFileOpened();
62 } 67 }
63 } 68 }
64 69
65 FileStream::Context::~Context() { 70 FileStream::Context::~Context() {
66 } 71 }
67 72
68 int FileStream::Context::Read(IOBuffer* buf, 73 int FileStream::Context::Read(IOBuffer* buf,
69 int buf_len, 74 int buf_len,
70 const CompletionCallback& callback) { 75 const CompletionCallback& callback) {
71 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. 76 CHECK(!async_in_progress_);
72 tracked_objects::ScopedTracker tracking_profile( 77 DCHECK(!async_read_initiated_);
73 FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 FileStream::Context::Read")); 78 DCHECK(!async_read_completed_);
74 79 DCHECK(!io_complete_for_read_received_);
75 DCHECK(!async_in_progress_);
76 80
77 IOCompletionIsPending(callback, buf); 81 IOCompletionIsPending(callback, buf);
78 82
79 base::WorkerPool::PostTask( 83 async_read_initiated_ = true;
84 result_ = 0;
85
86 task_runner_->PostTask(
80 FROM_HERE, 87 FROM_HERE,
81 base::Bind(&FileStream::Context::ReadAsync, 88 base::Bind(&FileStream::Context::ReadAsync, base::Unretained(this),
82 weak_ptr_factory_.GetWeakPtr(), file_.GetPlatformFile(), 89 file_.GetPlatformFile(), make_scoped_refptr(buf), buf_len,
83 make_scoped_refptr(buf), buf_len, &io_context_.overlapped, 90 &io_context_.overlapped,
84 base::MessageLoop::current()->message_loop_proxy()), 91 base::MessageLoop::current()->message_loop_proxy()));
85 false);
86
87 return ERR_IO_PENDING; 92 return ERR_IO_PENDING;
88 } 93 }
89 94
90 int FileStream::Context::Write(IOBuffer* buf, 95 int FileStream::Context::Write(IOBuffer* buf,
91 int buf_len, 96 int buf_len,
92 const CompletionCallback& callback) { 97 const CompletionCallback& callback) {
98 CHECK(!async_in_progress_);
99
100 result_ = 0;
101
93 DWORD bytes_written = 0; 102 DWORD bytes_written = 0;
94 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len, 103 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len,
95 &bytes_written, &io_context_.overlapped)) { 104 &bytes_written, &io_context_.overlapped)) {
96 IOResult error = IOResult::FromOSError(GetLastError()); 105 IOResult error = IOResult::FromOSError(GetLastError());
97 if (error.os_error == ERROR_IO_PENDING) 106 if (error.os_error == ERROR_IO_PENDING)
98 IOCompletionIsPending(callback, buf); 107 IOCompletionIsPending(callback, buf);
99 else 108 else
100 LOG(WARNING) << "WriteFile failed: " << error.os_error; 109 LOG(WARNING) << "WriteFile failed: " << error.os_error;
101 return static_cast<int>(error.result); 110 return static_cast<int>(error.result);
102 } 111 }
(...skipping 30 matching lines...) Expand all
133 } 142 }
134 143
135 void FileStream::Context::OnIOCompleted( 144 void FileStream::Context::OnIOCompleted(
136 base::MessageLoopForIO::IOContext* context, 145 base::MessageLoopForIO::IOContext* context,
137 DWORD bytes_read, 146 DWORD bytes_read,
138 DWORD error) { 147 DWORD error) {
139 DCHECK_EQ(&io_context_, context); 148 DCHECK_EQ(&io_context_, context);
140 DCHECK(!callback_.is_null()); 149 DCHECK(!callback_.is_null());
141 DCHECK(async_in_progress_); 150 DCHECK(async_in_progress_);
142 151
143 async_in_progress_ = false; 152 if (!async_read_initiated_)
153 async_in_progress_ = false;
154
144 if (orphaned_) { 155 if (orphaned_) {
145 callback_.Reset(); 156 io_complete_for_read_received_ = true;
146 in_flight_buf_ = NULL; 157 // If we are called due to a pending read and the asynchronous read task
147 CloseAndDelete(); 158 // has not completed we have to keep the context around until it completes.
159 if (async_read_initiated_ && !async_read_completed_)
160 return;
161 DeleteOrphanedContext();
148 return; 162 return;
149 } 163 }
150 164
151 int result;
152 if (error == ERROR_HANDLE_EOF) { 165 if (error == ERROR_HANDLE_EOF) {
153 result = 0; 166 result_ = 0;
154 } else if (error) { 167 } else if (error) {
155 IOResult error_result = IOResult::FromOSError(error); 168 IOResult error_result = IOResult::FromOSError(error);
156 result = static_cast<int>(error_result.result); 169 result_ = static_cast<int>(error_result.result);
157 } else { 170 } else {
158 result = bytes_read; 171 if (result_)
172 DCHECK_EQ(result_, static_cast<int>(bytes_read));
173 result_ = bytes_read;
159 IncrementOffset(&io_context_.overlapped, bytes_read); 174 IncrementOffset(&io_context_.overlapped, bytes_read);
160 } 175 }
161 176
177 if (async_read_initiated_)
178 io_complete_for_read_received_ = true;
179
180 InvokeUserCallback();
181 }
182
183 void FileStream::Context::InvokeUserCallback() {
184 // For an asynchonous Read operation don't invoke the user callback until
185 // we receive the IO completion notification and the asynchronous Read
186 // completion notification.
187 if (async_read_initiated_) {
188 if (!io_complete_for_read_received_ || !async_read_completed_)
189 return;
190 async_read_initiated_ = false;
191 io_complete_for_read_received_ = false;
192 async_read_completed_ = false;
193 async_in_progress_ = false;
194 }
162 CompletionCallback temp_callback = callback_; 195 CompletionCallback temp_callback = callback_;
163 callback_.Reset(); 196 callback_.Reset();
164 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; 197 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
165 in_flight_buf_ = NULL; 198 in_flight_buf_ = NULL;
166 temp_callback.Run(result); 199 temp_callback.Run(result_);
200 }
201
202 void FileStream::Context::DeleteOrphanedContext() {
203 async_in_progress_ = false;
204 callback_.Reset();
205 in_flight_buf_ = NULL;
206 CloseAndDelete();
167 } 207 }
168 208
169 // static 209 // static
170 void FileStream::Context::ReadAsync( 210 void FileStream::Context::ReadAsync(
171 const base::WeakPtr<FileStream::Context>& context, 211 FileStream::Context* context,
172 HANDLE file, 212 HANDLE file,
173 scoped_refptr<net::IOBuffer> buf, 213 scoped_refptr<net::IOBuffer> buf,
174 int buf_len, 214 int buf_len,
175 OVERLAPPED* overlapped, 215 OVERLAPPED* overlapped,
176 scoped_refptr<base::MessageLoopProxy> origin_thread_loop) { 216 scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
177 DWORD bytes_read = 0; 217 DWORD bytes_read = 0;
178 if (!ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped)) { 218 BOOL ret = ::ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped);
179 origin_thread_loop->PostTask( 219 origin_thread_loop->PostTask(
180 FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, context, 220 FROM_HERE,
181 ::GetLastError())); 221 base::Bind(&FileStream::Context::ReadAsyncResult,
182 } 222 base::Unretained(context), ret, bytes_read, ::GetLastError()));
183 } 223 }
184 224
185 void FileStream::Context::ReadAsyncResult(DWORD os_error) { 225 void FileStream::Context::ReadAsyncResult(BOOL read_file_ret,
226 DWORD bytes_read,
227 DWORD os_error) {
228 // If the context is orphaned and we already received the io completion
229 // notification then we should delete the context and get out.
230 if (orphaned_ && io_complete_for_read_received_) {
231 DeleteOrphanedContext();
232 return;
233 }
234
235 async_read_completed_ = true;
236 if (read_file_ret) {
237 result_ = bytes_read;
238 InvokeUserCallback();
239 return;
240 }
241
186 IOResult error = IOResult::FromOSError(os_error); 242 IOResult error = IOResult::FromOSError(os_error);
187 if (error.os_error == ERROR_HANDLE_EOF) { 243 if (error.os_error == ERROR_IO_PENDING) {
188 // Report EOF by returning 0 bytes read. 244 InvokeUserCallback();
189 OnIOCompleted(&io_context_, 0, error.os_error); 245 } else {
190 } else if (error.os_error != ERROR_IO_PENDING) {
191 // We don't need to inform the caller about ERROR_PENDING_IO as that was
192 // already done when the ReadFile call was queued to the worker pool.
193 if (error.os_error)
194 LOG(WARNING) << "ReadFile failed: " << error.os_error;
195 OnIOCompleted(&io_context_, 0, error.os_error); 246 OnIOCompleted(&io_context_, 0, error.os_error);
196 } 247 }
197 } 248 }
198 249
199 } // namespace net 250 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_context.cc ('k') | net/base/mime_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698