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

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

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 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_posix.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
(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 <windows.h>
8
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/message_loop/message_loop_proxy.h"
13 #include "base/metrics/histogram.h"
14 #include "base/task_runner.h"
15 #include "base/threading/worker_pool.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/net_errors.h"
18
19 namespace net {
20
21 namespace {
22
23 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
24 overlapped->Offset = offset.LowPart;
25 overlapped->OffsetHigh = offset.HighPart;
26 }
27
28 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
29 LARGE_INTEGER offset;
30 offset.LowPart = overlapped->Offset;
31 offset.HighPart = overlapped->OffsetHigh;
32 offset.QuadPart += static_cast<LONGLONG>(count);
33 SetOffset(overlapped, offset);
34 }
35
36 } // namespace
37
38 FileStream::Context::Context(const scoped_refptr<base::TaskRunner>& task_runner)
39 : io_context_(),
40 async_in_progress_(false),
41 orphaned_(false),
42 task_runner_(task_runner),
43 async_read_initiated_(false),
44 async_read_completed_(false),
45 io_complete_for_read_received_(false),
46 result_(0) {
47 io_context_.handler = this;
48 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
49 }
50
51 FileStream::Context::Context(base::File file,
52 const scoped_refptr<base::TaskRunner>& task_runner)
53 : io_context_(),
54 file_(file.Pass()),
55 async_in_progress_(false),
56 orphaned_(false),
57 task_runner_(task_runner),
58 async_read_initiated_(false),
59 async_read_completed_(false),
60 io_complete_for_read_received_(false),
61 result_(0) {
62 io_context_.handler = this;
63 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
64 if (file_.IsValid()) {
65 // TODO(hashimoto): Check that file_ is async.
66 OnFileOpened();
67 }
68 }
69
70 FileStream::Context::~Context() {
71 }
72
73 int FileStream::Context::Read(IOBuffer* buf,
74 int buf_len,
75 const CompletionCallback& callback) {
76 CHECK(!async_in_progress_);
77 DCHECK(!async_read_initiated_);
78 DCHECK(!async_read_completed_);
79 DCHECK(!io_complete_for_read_received_);
80
81 IOCompletionIsPending(callback, buf);
82
83 async_read_initiated_ = true;
84 result_ = 0;
85
86 task_runner_->PostTask(
87 FROM_HERE,
88 base::Bind(&FileStream::Context::ReadAsync, base::Unretained(this),
89 file_.GetPlatformFile(), make_scoped_refptr(buf), buf_len,
90 &io_context_.overlapped,
91 base::MessageLoop::current()->message_loop_proxy()));
92 return ERR_IO_PENDING;
93 }
94
95 int FileStream::Context::Write(IOBuffer* buf,
96 int buf_len,
97 const CompletionCallback& callback) {
98 CHECK(!async_in_progress_);
99
100 result_ = 0;
101
102 DWORD bytes_written = 0;
103 if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len,
104 &bytes_written, &io_context_.overlapped)) {
105 IOResult error = IOResult::FromOSError(GetLastError());
106 if (error.os_error == ERROR_IO_PENDING)
107 IOCompletionIsPending(callback, buf);
108 else
109 LOG(WARNING) << "WriteFile failed: " << error.os_error;
110 return static_cast<int>(error.result);
111 }
112
113 IOCompletionIsPending(callback, buf);
114 return ERR_IO_PENDING;
115 }
116
117 FileStream::Context::IOResult FileStream::Context::SeekFileImpl(
118 base::File::Whence whence,
119 int64 offset) {
120 LARGE_INTEGER result;
121 result.QuadPart = file_.Seek(whence, offset);
122 if (result.QuadPart >= 0) {
123 SetOffset(&io_context_.overlapped, result);
124 return IOResult(result.QuadPart, 0);
125 }
126
127 return IOResult::FromOSError(GetLastError());
128 }
129
130 void FileStream::Context::OnFileOpened() {
131 base::MessageLoopForIO::current()->RegisterIOHandler(file_.GetPlatformFile(),
132 this);
133 }
134
135 void FileStream::Context::IOCompletionIsPending(
136 const CompletionCallback& callback,
137 IOBuffer* buf) {
138 DCHECK(callback_.is_null());
139 callback_ = callback;
140 in_flight_buf_ = buf; // Hold until the async operation ends.
141 async_in_progress_ = true;
142 }
143
144 void FileStream::Context::OnIOCompleted(
145 base::MessageLoopForIO::IOContext* context,
146 DWORD bytes_read,
147 DWORD error) {
148 DCHECK_EQ(&io_context_, context);
149 DCHECK(!callback_.is_null());
150 DCHECK(async_in_progress_);
151
152 if (!async_read_initiated_)
153 async_in_progress_ = false;
154
155 if (orphaned_) {
156 io_complete_for_read_received_ = true;
157 // If we are called due to a pending read and the asynchronous read task
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();
162 return;
163 }
164
165 if (error == ERROR_HANDLE_EOF) {
166 result_ = 0;
167 } else if (error) {
168 IOResult error_result = IOResult::FromOSError(error);
169 result_ = static_cast<int>(error_result.result);
170 } else {
171 if (result_)
172 DCHECK_EQ(result_, static_cast<int>(bytes_read));
173 result_ = bytes_read;
174 IncrementOffset(&io_context_.overlapped, bytes_read);
175 }
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 }
195 CompletionCallback temp_callback = callback_;
196 callback_.Reset();
197 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
198 in_flight_buf_ = NULL;
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();
207 }
208
209 // static
210 void FileStream::Context::ReadAsync(
211 FileStream::Context* context,
212 HANDLE file,
213 scoped_refptr<net::IOBuffer> buf,
214 int buf_len,
215 OVERLAPPED* overlapped,
216 scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
217 DWORD bytes_read = 0;
218 BOOL ret = ::ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped);
219 origin_thread_loop->PostTask(
220 FROM_HERE,
221 base::Bind(&FileStream::Context::ReadAsyncResult,
222 base::Unretained(context), ret, bytes_read, ::GetLastError()));
223 }
224
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
242 IOResult error = IOResult::FromOSError(os_error);
243 if (error.os_error == ERROR_IO_PENDING) {
244 InvokeUserCallback();
245 } else {
246 OnIOCompleted(&io_context_, 0, error.os_error);
247 }
248 }
249
250 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_context_posix.cc ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698