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

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

Issue 10701050: net: Implement canceling of all async operations in FileStream. (Closed) Base URL: https://src.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 1 month 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
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/file_path.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/task_runner_util.h"
13 #include "base/threading/worker_pool.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16
17 namespace net {
18
19 // Ensure that we can just use our Whence values directly.
20 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin);
21 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current);
22 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end);
23
24 namespace {
25
26 void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
27 overlapped->Offset = offset.LowPart;
28 overlapped->OffsetHigh = offset.HighPart;
29 }
30
31 void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
32 LARGE_INTEGER offset;
33 offset.LowPart = overlapped->Offset;
34 offset.HighPart = overlapped->OffsetHigh;
35 offset.QuadPart += static_cast<LONGLONG>(count);
36 SetOffset(overlapped, offset);
37 }
38
39 } // namespace
40
41 FileStream::Context::Context(const BoundNetLog& bound_net_log)
42 : io_context_(),
43 file_(base::kInvalidPlatformFileValue),
44 record_uma_(false),
45 async_in_progress_(false),
46 orphaned_(false),
47 bound_net_log_(bound_net_log),
48 error_source_(FILE_ERROR_SOURCE_COUNT) {
49 io_context_.handler = this;
50 }
51
52 FileStream::Context::Context(base::PlatformFile file,
53 const BoundNetLog& bound_net_log,
54 int open_flags)
55 : io_context_(),
56 file_(file),
57 record_uma_(false),
58 async_in_progress_(false),
59 orphaned_(false),
60 bound_net_log_(bound_net_log),
61 error_source_(FILE_ERROR_SOURCE_COUNT) {
62 io_context_.handler = this;
63 if (file_ != base::kInvalidPlatformFileValue &&
64 (open_flags & base::PLATFORM_FILE_ASYNC)) {
65 OnAsyncFileOpened();
66 }
67 }
68
69 FileStream::Context::~Context() {
70 }
71
72 int64 FileStream::Context::GetFileSize() const {
73 LARGE_INTEGER file_size;
74 if (!GetFileSizeEx(file_, &file_size)) {
75 DWORD error = GetLastError();
76 LOG(WARNING) << "GetFileSizeEx failed: " << error;
77 return RecordAndMapError(error, FILE_ERROR_SOURCE_GET_SIZE);
78 }
79
80 return file_size.QuadPart;
81 }
82
83 int FileStream::Context::ReadAsync(IOBuffer* buf,
84 int buf_len,
85 const CompletionCallback& callback) {
86 DCHECK(!async_in_progress_);
87 error_source_ = FILE_ERROR_SOURCE_READ;
88
89 int rv = 0;
90
91 DWORD bytes_read;
92 if (!ReadFile(file_, buf->data(), buf_len,
93 &bytes_read, &io_context_.overlapped)) {
94 DWORD error = GetLastError();
95 if (error == ERROR_IO_PENDING) {
96 IOCompletionIsPending(callback, buf);
97 rv = ERR_IO_PENDING;
98 } else if (error == ERROR_HANDLE_EOF) {
99 rv = 0; // Report EOF by returning 0 bytes read.
100 } else {
101 LOG(WARNING) << "ReadFile failed: " << error;
102 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ);
103 }
104 } else {
105 IOCompletionIsPending(callback, buf);
106 rv = ERR_IO_PENDING;
107 }
108 return rv;
109 }
110
111 int FileStream::Context::ReadSync(char* buf, int buf_len) {
112 int rv = 0;
113
114 DWORD bytes_read;
115 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) {
116 DWORD error = GetLastError();
117 if (error == ERROR_HANDLE_EOF) {
118 rv = 0; // Report EOF by returning 0 bytes read.
119 } else {
120 LOG(WARNING) << "ReadFile failed: " << error;
121 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ);
122 }
123 } else {
124 rv = static_cast<int>(bytes_read);
125 }
126 return rv;
127 }
128
129 int FileStream::Context::WriteAsync(IOBuffer* buf,
130 int buf_len,
131 const CompletionCallback& callback) {
132 error_source_ = FILE_ERROR_SOURCE_WRITE;
133
134 int rv = 0;
135 DWORD bytes_written = 0;
136 if (!WriteFile(file_, buf->data(), buf_len,
137 &bytes_written, &io_context_.overlapped)) {
138 DWORD error = GetLastError();
139 if (error == ERROR_IO_PENDING) {
140 IOCompletionIsPending(callback, buf);
141 rv = ERR_IO_PENDING;
142 } else {
143 LOG(WARNING) << "WriteFile failed: " << error;
144 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE);
145 }
146 } else {
147 IOCompletionIsPending(callback, buf);
148 rv = ERR_IO_PENDING;
149 }
150 return rv;
151 }
152
153 int FileStream::Context::WriteSync(const char* buf, int buf_len) {
154 int rv = 0;
155 DWORD bytes_written = 0;
156 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) {
157 DWORD error = GetLastError();
158 LOG(WARNING) << "WriteFile failed: " << error;
159 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE);
160 } else {
161 rv = static_cast<int>(bytes_written);
162 }
163 return rv;
164 }
165
166 int FileStream::Context::Truncate(int64 bytes) {
167 BOOL result = SetEndOfFile(file_);
168 if (result)
169 return bytes;
170
171 DWORD error = GetLastError();
172 LOG(WARNING) << "SetEndOfFile failed: " << error;
173 return RecordAndMapError(error, FILE_ERROR_SOURCE_SET_EOF);
174 }
175
176 void FileStream::Context::OnAsyncFileOpened() {
177 MessageLoopForIO::current()->RegisterIOHandler(file_, this);
178 }
179
180 int64 FileStream::Context::SeekFileImpl(Whence whence, int64 offset) {
181 LARGE_INTEGER distance, res;
182 distance.QuadPart = offset;
183 DWORD move_method = static_cast<DWORD>(whence);
184 if (SetFilePointerEx(file_, distance, &res, move_method)) {
185 SetOffset(&io_context_.overlapped, res);
186 return res.QuadPart;
187 }
188
189 return -static_cast<int>(GetLastError());
190 }
191
192 int64 FileStream::Context::FlushFileImpl() {
193 if (FlushFileBuffers(file_))
194 return OK;
195
196 return -static_cast<int>(GetLastError());
197 }
198
199 void FileStream::Context::IOCompletionIsPending(
200 const CompletionCallback& callback,
201 IOBuffer* buf) {
202 DCHECK(callback_.is_null());
203 callback_ = callback;
204 in_flight_buf_ = buf; // Hold until the async operation ends.
205 async_in_progress_ = true;
206 }
207
208 void FileStream::Context::OnIOCompleted(MessageLoopForIO::IOContext* context,
209 DWORD bytes_read,
210 DWORD error) {
211 DCHECK_EQ(&io_context_, context);
212 DCHECK(!callback_.is_null());
213 DCHECK(async_in_progress_);
214
215 async_in_progress_ = false;
216 if (orphaned_) {
217 callback_.Reset();
218 in_flight_buf_ = NULL;
219 CloseAndDelete();
220 return;
221 }
222
223 int result = static_cast<int>(bytes_read);
224 if (error && error != ERROR_HANDLE_EOF)
225 result = RecordAndMapError(error, error_source_);
226
227 if (bytes_read)
228 IncrementOffset(&io_context_.overlapped, bytes_read);
229
230 CompletionCallback temp_callback = callback_;
231 callback_.Reset();
232 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
233 in_flight_buf_ = NULL;
234 temp_callback.Run(result);
235 }
236
237 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698