OLD | NEW |
---|---|
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(), | |
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 Loading... | |
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 ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped); | |
179 | |
180 origin_thread_loop->PostTask( | |
181 FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, context, | |
182 ::GetLastError())); | |
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 return; | |
ramant (doing other things)
2015/01/31 05:23:22
nit: return is not needed. Or "} else if" ->
"}
i
ananta
2015/02/03 00:33:43
Done.
| |
191 } else if (error.os_error != ERROR_IO_PENDING) { | |
192 // We don't need to inform the caller about ERROR_PENDING_IO as that was | |
193 // already done when the ReadFile call was queued to the worker pool. | |
194 if (error.os_error) | |
195 LOG(WARNING) << "ReadFile failed: " << error.os_error; | |
196 OnIOCompleted(&io_context_, 0, error.os_error); | |
197 } | |
198 } | |
199 | |
168 } // namespace net | 200 } // namespace net |
OLD | NEW |