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

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

Issue 887863002: The ReadFile API on Windows invoked by the FileStream::Context class which is used by URLRequestFil… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Pass the result of ReadFile on failure only 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/file_stream_unittest.cc » ('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"
12 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
12 #include "base/profiler/scoped_tracker.h" 14 #include "base/profiler/scoped_tracker.h"
13 #include "base/task_runner.h" 15 #include "base/task_runner.h"
16 #include "base/threading/worker_pool.h"
14 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
16 19
17 namespace net { 20 namespace net {
18 21
19 namespace { 22 namespace {
20 23
21 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { 24 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
22 overlapped->Offset = offset.LowPart; 25 overlapped->Offset = offset.LowPart;
23 overlapped->OffsetHigh = offset.HighPart; 26 overlapped->OffsetHigh = offset.HighPart;
24 } 27 }
25 28
26 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) { 29 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
27 LARGE_INTEGER offset; 30 LARGE_INTEGER offset;
28 offset.LowPart = overlapped->Offset; 31 offset.LowPart = overlapped->Offset;
29 offset.HighPart = overlapped->OffsetHigh; 32 offset.HighPart = overlapped->OffsetHigh;
30 offset.QuadPart += static_cast<LONGLONG>(count); 33 offset.QuadPart += static_cast<LONGLONG>(count);
31 SetOffset(overlapped, offset); 34 SetOffset(overlapped, offset);
32 } 35 }
33 36
34 } // namespace 37 } // namespace
35 38
36 FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner) 39 FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner)
37 : io_context_(), 40 : io_context_(),
38 async_in_progress_(false), 41 async_in_progress_(false),
39 orphaned_(false), 42 orphaned_(false),
40 task_runner_(task_runner) { 43 task_runner_(task_runner),
44 weak_ptr_factory_(this) {
41 io_context_.handler = this; 45 io_context_.handler = this;
42 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); 46 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
43 } 47 }
44 48
45 FileStream::Context::Context(base::File file, 49 FileStream::Context::Context(base::File file,
46 const scoped_refptr<base::TaskRunner>& task_runner) 50 const scoped_refptr<base::TaskRunner>& task_runner)
47 : io_context_(), 51 : io_context_(),
48 file_(file.Pass()), 52 file_(file.Pass()),
49 async_in_progress_(false), 53 async_in_progress_(false),
50 orphaned_(false), 54 orphaned_(false),
51 task_runner_(task_runner) { 55 task_runner_(task_runner),
56 weak_ptr_factory_(this) {
52 io_context_.handler = this; 57 io_context_.handler = this;
53 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped)); 58 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
54 if (file_.IsValid()) { 59 if (file_.IsValid()) {
55 // TODO(hashimoto): Check that file_ is async. 60 // TODO(hashimoto): Check that file_ is async.
56 OnFileOpened(); 61 OnFileOpened();
57 } 62 }
58 } 63 }
59 64
60 FileStream::Context::~Context() { 65 FileStream::Context::~Context() {
61 } 66 }
62 67
63 int FileStream::Context::Read(IOBuffer* buf, 68 int FileStream::Context::Read(IOBuffer* buf,
64 int buf_len, 69 int buf_len,
65 const CompletionCallback& callback) { 70 const CompletionCallback& callback) {
66 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed. 71 // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
67 tracked_objects::ScopedTracker tracking_profile( 72 tracked_objects::ScopedTracker tracking_profile(
68 FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 FileStream::Context::Read")); 73 FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 FileStream::Context::Read"));
69 74
70 DCHECK(!async_in_progress_); 75 DCHECK(!async_in_progress_);
71 76
72 DWORD bytes_read; 77 IOCompletionIsPending(callback, buf);
73 if (!ReadFile(file_.GetPlatformFile(), buf->data(), buf_len,
74 &bytes_read, &io_context_.overlapped)) {
75 IOResult error = IOResult::FromOSError(GetLastError());
76 if (error.os_error == ERROR_HANDLE_EOF)
77 return 0; // Report EOF by returning 0 bytes read.
78 if (error.os_error == ERROR_IO_PENDING)
79 IOCompletionIsPending(callback, buf);
80 else
81 LOG(WARNING) << "ReadFile failed: " << error.os_error;
82 return static_cast<int>(error.result);
83 }
84 78
85 IOCompletionIsPending(callback, buf); 79 base::WorkerPool::PostTask(
80 FROM_HERE,
81 base::Bind(&FileStream::Context::ReadAsync,
82 weak_ptr_factory_.GetWeakPtr(), file_.GetPlatformFile(),
rvargas (doing something else) 2015/02/03 20:04:37 Isn't _this_ pointer being used from multiple thre
rvargas (doing something else) 2015/02/03 20:04:37 This passes a raw handle across a thread boundary
ananta 2015/02/04 01:55:38 Ditto about the context object living as long as t
ananta 2015/02/04 01:55:38 The weakptr is only used for passing the results b
83 make_scoped_refptr(buf), buf_len, &io_context_.overlapped,
84 base::MessageLoop::current()->message_loop_proxy()),
85 false);
86
86 return ERR_IO_PENDING; 87 return ERR_IO_PENDING;
87 } 88 }
88 89
89 int FileStream::Context::Write(IOBuffer* buf, 90 int FileStream::Context::Write(IOBuffer* buf,
90 int buf_len, 91 int buf_len,
91 const CompletionCallback& callback) { 92 const CompletionCallback& callback) {
92 DWORD bytes_written = 0; 93 DWORD bytes_written = 0;
93 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len, 94 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len,
94 &bytes_written, &io_context_.overlapped)) { 95 &bytes_written, &io_context_.overlapped)) {
95 IOResult error = IOResult::FromOSError(GetLastError()); 96 IOResult error = IOResult::FromOSError(GetLastError());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 IncrementOffset(&io_context_.overlapped, bytes_read); 159 IncrementOffset(&io_context_.overlapped, bytes_read);
159 } 160 }
160 161
161 CompletionCallback temp_callback = callback_; 162 CompletionCallback temp_callback = callback_;
162 callback_.Reset(); 163 callback_.Reset();
163 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; 164 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
164 in_flight_buf_ = NULL; 165 in_flight_buf_ = NULL;
165 temp_callback.Run(result); 166 temp_callback.Run(result);
166 } 167 }
167 168
169 // static
170 void FileStream::Context::ReadAsync(
171 const base::WeakPtr<FileStream::Context>& context,
172 HANDLE file,
173 scoped_refptr<net::IOBuffer> buf,
174 int buf_len,
175 OVERLAPPED* overlapped,
176 scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
177 DWORD bytes_read = 0;
178 if (!ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped)) {
179 origin_thread_loop->PostTask(
180 FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, context,
181 ::GetLastError()));
182 }
183 }
184
185 void FileStream::Context::ReadAsyncResult(DWORD os_error) {
186 IOResult error = IOResult::FromOSError(os_error);
187 if (error.os_error == ERROR_HANDLE_EOF) {
188 // Report EOF by returning 0 bytes read.
189 OnIOCompleted(&io_context_, 0, error.os_error);
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);
196 }
197 }
198
168 } // namespace net 199 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_context.cc ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698