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

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

Issue 7583049: Record UMA statistics for file_stream operations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Hopefully fixed crash bug in file stream UMA stats. Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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.h" 5 #include "net/base/file_stream.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 default: 45 default:
46 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 46 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
47 return ERR_FAILED; 47 return ERR_FAILED;
48 } 48 }
49 } 49 }
50 50
51 // FileStream::AsyncContext ---------------------------------------------- 51 // FileStream::AsyncContext ----------------------------------------------
52 52
53 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { 53 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler {
54 public: 54 public:
55 AsyncContext(FileStream* owner) 55 AsyncContext(FileStream* owner, int class_flags)
56 : owner_(owner), context_(), callback_(NULL), is_closing_(false) { 56 : owner_(owner), context_(), callback_(NULL), is_closing_(false),
57 class_flags_(class_flags) {
57 context_.handler = this; 58 context_.handler = this;
58 } 59 }
59 ~AsyncContext(); 60 ~AsyncContext();
60 61
61 void IOCompletionIsPending(CompletionCallback* callback); 62 void IOCompletionIsPending(CompletionCallback* callback);
62 63
63 OVERLAPPED* overlapped() { return &context_.overlapped; } 64 OVERLAPPED* overlapped() { return &context_.overlapped; }
64 CompletionCallback* callback() const { return callback_; } 65 CompletionCallback* callback() const { return callback_; }
65 66
67 void EnableRecording(bool enable, int class_flags) {
68 if (enable)
69 class_flags_ |= class_flags;
70 else
71 class_flags_ &= ~class_flags;
72 }
73
66 private: 74 private:
67 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 75 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
68 DWORD bytes_read, DWORD error); 76 DWORD bytes_read, DWORD error);
69 77
70 FileStream* owner_; 78 FileStream* owner_;
71 MessageLoopForIO::IOContext context_; 79 MessageLoopForIO::IOContext context_;
72 CompletionCallback* callback_; 80 CompletionCallback* callback_;
73 bool is_closing_; 81 bool is_closing_;
82 int class_flags_;
74 }; 83 };
75 84
76 FileStream::AsyncContext::~AsyncContext() { 85 FileStream::AsyncContext::~AsyncContext() {
77 is_closing_ = true; 86 is_closing_ = true;
78 bool waited = false; 87 bool waited = false;
79 base::TimeTicks start = base::TimeTicks::Now(); 88 base::TimeTicks start = base::TimeTicks::Now();
80 while (callback_) { 89 while (callback_) {
81 waited = true; 90 waited = true;
82 MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); 91 MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
83 } 92 }
(...skipping 14 matching lines...) Expand all
98 MessageLoopForIO::IOContext* context, DWORD bytes_read, DWORD error) { 107 MessageLoopForIO::IOContext* context, DWORD bytes_read, DWORD error) {
99 DCHECK_EQ(&context_, context); 108 DCHECK_EQ(&context_, context);
100 DCHECK(callback_); 109 DCHECK(callback_);
101 110
102 if (is_closing_) { 111 if (is_closing_) {
103 callback_ = NULL; 112 callback_ = NULL;
104 return; 113 return;
105 } 114 }
106 115
107 int result = static_cast<int>(bytes_read); 116 int result = static_cast<int>(bytes_read);
108 if (error && error != ERROR_HANDLE_EOF) 117 if (error && error != ERROR_HANDLE_EOF) {
118 RecordFileError(error, FILE_ERROR_TYPES_READ, class_flags_);
109 result = MapErrorCode(error); 119 result = MapErrorCode(error);
120 }
110 121
111 if (bytes_read) 122 if (bytes_read)
112 IncrementOffset(&context->overlapped, bytes_read); 123 IncrementOffset(&context->overlapped, bytes_read);
113 124
114 CompletionCallback* temp = NULL; 125 CompletionCallback* temp = NULL;
115 std::swap(temp, callback_); 126 std::swap(temp, callback_);
116 temp->Run(result); 127 temp->Run(result);
117 } 128 }
118 129
119 // FileStream ------------------------------------------------------------ 130 // FileStream ------------------------------------------------------------
120 131
121 FileStream::FileStream() 132 FileStream::FileStream()
122 : file_(INVALID_HANDLE_VALUE), 133 : file_(INVALID_HANDLE_VALUE),
123 open_flags_(0), 134 open_flags_(0),
124 auto_closed_(true) { 135 auto_closed_(true),
136 class_flags_(0) {
137 }
138
139 FileStream::FileStream(int class_flags)
140 : file_(INVALID_HANDLE_VALUE),
141 open_flags_(0),
142 auto_closed_(true),
143 class_flags_(class_flags) {
125 } 144 }
126 145
127 FileStream::FileStream(base::PlatformFile file, int flags) 146 FileStream::FileStream(base::PlatformFile file, int flags)
128 : file_(file), 147 : file_(file),
129 open_flags_(flags), 148 open_flags_(flags),
130 auto_closed_(false) { 149 auto_closed_(false),
150 class_flags_(0) {
131 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to 151 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to
132 // make sure we will perform asynchronous File IO to it. 152 // make sure we will perform asynchronous File IO to it.
133 if (flags & base::PLATFORM_FILE_ASYNC) { 153 if (flags & base::PLATFORM_FILE_ASYNC) {
134 async_context_.reset(new AsyncContext(this)); 154 async_context_.reset(new AsyncContext(this, class_flags_));
135 MessageLoopForIO::current()->RegisterIOHandler(file_, 155 MessageLoopForIO::current()->RegisterIOHandler(file_,
136 async_context_.get()); 156 async_context_.get());
137 } 157 }
158 }
159
160 FileStream::FileStream(base::PlatformFile file, int flags, int class_flags)
161 : file_(file),
162 open_flags_(flags),
163 auto_closed_(false),
164 class_flags_(class_flags) {
165 // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to
166 // make sure we will perform asynchronous File IO to it.
167 if (flags & base::PLATFORM_FILE_ASYNC) {
168 async_context_.reset(new AsyncContext(this, class_flags_));
169 MessageLoopForIO::current()->RegisterIOHandler(file_,
170 async_context_.get());
171 }
138 } 172 }
139 173
140 FileStream::~FileStream() { 174 FileStream::~FileStream() {
141 if (auto_closed_) 175 if (auto_closed_)
142 Close(); 176 Close();
143 } 177 }
144 178
145 void FileStream::Close() { 179 void FileStream::Close() {
146 if (file_ != INVALID_HANDLE_VALUE) 180 if (file_ != INVALID_HANDLE_VALUE)
147 CancelIo(file_); 181 CancelIo(file_);
148 182
149 async_context_.reset(); 183 async_context_.reset();
150 if (file_ != INVALID_HANDLE_VALUE) { 184 if (file_ != INVALID_HANDLE_VALUE) {
151 CloseHandle(file_); 185 CloseHandle(file_);
152 file_ = INVALID_HANDLE_VALUE; 186 file_ = INVALID_HANDLE_VALUE;
153 } 187 }
154 } 188 }
155 189
156 int FileStream::Open(const FilePath& path, int open_flags) { 190 int FileStream::Open(const FilePath& path, int open_flags) {
157 if (IsOpen()) { 191 if (IsOpen()) {
158 DLOG(FATAL) << "File is already open!"; 192 DLOG(FATAL) << "File is already open!";
159 return ERR_UNEXPECTED; 193 return ERR_UNEXPECTED;
160 } 194 }
161 195
162 open_flags_ = open_flags; 196 open_flags_ = open_flags;
163 file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); 197 file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL);
164 if (file_ == INVALID_HANDLE_VALUE) { 198 if (file_ == INVALID_HANDLE_VALUE) {
165 DWORD error = GetLastError(); 199 DWORD error = GetLastError();
166 LOG(WARNING) << "Failed to open file: " << error; 200 LOG(WARNING) << "Failed to open file: " << error;
201 RecordFileError(error, FILE_ERROR_TYPES_OPEN, class_flags_);
167 return MapErrorCode(error); 202 return MapErrorCode(error);
168 } 203 }
169 204
170 if (open_flags_ & base::PLATFORM_FILE_ASYNC) { 205 if (open_flags_ & base::PLATFORM_FILE_ASYNC) {
171 async_context_.reset(new AsyncContext(this)); 206 async_context_.reset(new AsyncContext(this, class_flags_));
172 MessageLoopForIO::current()->RegisterIOHandler(file_, 207 MessageLoopForIO::current()->RegisterIOHandler(file_,
173 async_context_.get()); 208 async_context_.get());
174 } 209 }
175 210
176 return OK; 211 return OK;
177 } 212 }
178 213
179 bool FileStream::IsOpen() const { 214 bool FileStream::IsOpen() const {
180 return file_ != INVALID_HANDLE_VALUE; 215 return file_ != INVALID_HANDLE_VALUE;
181 } 216 }
182 217
183 int64 FileStream::Seek(Whence whence, int64 offset) { 218 int64 FileStream::Seek(Whence whence, int64 offset) {
184 if (!IsOpen()) 219 if (!IsOpen()) {
220 RecordFileError(ERROR_INVALID_HANDLE, FILE_ERROR_TYPES_IS_NOT_OPEN,
221 class_flags_);
185 return ERR_UNEXPECTED; 222 return ERR_UNEXPECTED;
223 }
224
186 DCHECK(!async_context_.get() || !async_context_->callback()); 225 DCHECK(!async_context_.get() || !async_context_->callback());
187 226
188 LARGE_INTEGER distance, result; 227 LARGE_INTEGER distance, result;
189 distance.QuadPart = offset; 228 distance.QuadPart = offset;
190 DWORD move_method = static_cast<DWORD>(whence); 229 DWORD move_method = static_cast<DWORD>(whence);
191 if (!SetFilePointerEx(file_, distance, &result, move_method)) { 230 if (!SetFilePointerEx(file_, distance, &result, move_method)) {
192 DWORD error = GetLastError(); 231 DWORD error = GetLastError();
193 LOG(WARNING) << "SetFilePointerEx failed: " << error; 232 LOG(WARNING) << "SetFilePointerEx failed: " << error;
233 RecordFileError(error, FILE_ERROR_TYPES_SEEK, class_flags_);
194 return MapErrorCode(error); 234 return MapErrorCode(error);
195 } 235 }
196 if (async_context_.get()) 236 if (async_context_.get())
197 SetOffset(async_context_->overlapped(), result); 237 SetOffset(async_context_->overlapped(), result);
198 return result.QuadPart; 238 return result.QuadPart;
199 } 239 }
200 240
201 int64 FileStream::Available() { 241 int64 FileStream::Available() {
202 base::ThreadRestrictions::AssertIOAllowed(); 242 base::ThreadRestrictions::AssertIOAllowed();
203 243
204 if (!IsOpen()) 244 if (!IsOpen()) {
245 RecordFileError(ERROR_INVALID_HANDLE, FILE_ERROR_TYPES_IS_NOT_OPEN,
246 class_flags_);
205 return ERR_UNEXPECTED; 247 return ERR_UNEXPECTED;
248 }
206 249
207 int64 cur_pos = Seek(FROM_CURRENT, 0); 250 int64 cur_pos = Seek(FROM_CURRENT, 0);
208 if (cur_pos < 0) 251 if (cur_pos < 0)
209 return cur_pos; 252 return cur_pos;
210 253
211 LARGE_INTEGER file_size; 254 LARGE_INTEGER file_size;
212 if (!GetFileSizeEx(file_, &file_size)) { 255 if (!GetFileSizeEx(file_, &file_size)) {
213 DWORD error = GetLastError(); 256 DWORD error = GetLastError();
214 LOG(WARNING) << "GetFileSizeEx failed: " << error; 257 LOG(WARNING) << "GetFileSizeEx failed: " << error;
258 RecordFileError(error, FILE_ERROR_TYPES_GET_SIZE, class_flags_);
215 return MapErrorCode(error); 259 return MapErrorCode(error);
216 } 260 }
217 261
218 return file_size.QuadPart - cur_pos; 262 return file_size.QuadPart - cur_pos;
219 } 263 }
220 264
221 int FileStream::Read( 265 int FileStream::Read(
222 char* buf, int buf_len, CompletionCallback* callback) { 266 char* buf, int buf_len, CompletionCallback* callback) {
223 if (!IsOpen()) 267 if (!IsOpen()) {
268 RecordFileError(ERROR_INVALID_HANDLE, FILE_ERROR_TYPES_IS_NOT_OPEN,
269 class_flags_);
224 return ERR_UNEXPECTED; 270 return ERR_UNEXPECTED;
271 }
272
225 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); 273 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
226 274
227 OVERLAPPED* overlapped = NULL; 275 OVERLAPPED* overlapped = NULL;
228 if (async_context_.get()) { 276 if (async_context_.get()) {
229 DCHECK(callback); 277 DCHECK(callback);
230 DCHECK(!async_context_->callback()); 278 DCHECK(!async_context_->callback());
231 overlapped = async_context_->overlapped(); 279 overlapped = async_context_->overlapped();
232 } else { 280 } else {
233 DCHECK(!callback); 281 DCHECK(!callback);
234 base::ThreadRestrictions::AssertIOAllowed(); 282 base::ThreadRestrictions::AssertIOAllowed();
235 } 283 }
236 284
237 int rv; 285 int rv;
238 286
239 DWORD bytes_read; 287 DWORD bytes_read;
240 if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) { 288 if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) {
241 DWORD error = GetLastError(); 289 DWORD error = GetLastError();
242 if (async_context_.get() && error == ERROR_IO_PENDING) { 290 if (async_context_.get() && error == ERROR_IO_PENDING) {
243 async_context_->IOCompletionIsPending(callback); 291 async_context_->IOCompletionIsPending(callback);
244 rv = ERR_IO_PENDING; 292 rv = ERR_IO_PENDING;
245 } else if (error == ERROR_HANDLE_EOF) { 293 } else if (error == ERROR_HANDLE_EOF) {
246 rv = 0; // Report EOF by returning 0 bytes read. 294 rv = 0; // Report EOF by returning 0 bytes read.
247 } else { 295 } else {
248 LOG(WARNING) << "ReadFile failed: " << error; 296 LOG(WARNING) << "ReadFile failed: " << error;
297 RecordFileError(error, FILE_ERROR_TYPES_READ, class_flags_);
249 rv = MapErrorCode(error); 298 rv = MapErrorCode(error);
250 } 299 }
251 } else if (overlapped) { 300 } else if (overlapped) {
252 async_context_->IOCompletionIsPending(callback); 301 async_context_->IOCompletionIsPending(callback);
253 rv = ERR_IO_PENDING; 302 rv = ERR_IO_PENDING;
254 } else { 303 } else {
255 rv = static_cast<int>(bytes_read); 304 rv = static_cast<int>(bytes_read);
256 } 305 }
257 return rv; 306 return rv;
258 } 307 }
(...skipping 14 matching lines...) Expand all
273 bytes_total += bytes_read; 322 bytes_total += bytes_read;
274 buf += bytes_read; 323 buf += bytes_read;
275 to_read -= bytes_read; 324 to_read -= bytes_read;
276 } while (bytes_total < buf_len); 325 } while (bytes_total < buf_len);
277 326
278 return bytes_total; 327 return bytes_total;
279 } 328 }
280 329
281 int FileStream::Write( 330 int FileStream::Write(
282 const char* buf, int buf_len, CompletionCallback* callback) { 331 const char* buf, int buf_len, CompletionCallback* callback) {
283 if (!IsOpen()) 332 if (!IsOpen()) {
333 RecordFileError(ERROR_INVALID_HANDLE, FILE_ERROR_TYPES_IS_NOT_OPEN,
334 class_flags_);
284 return ERR_UNEXPECTED; 335 return ERR_UNEXPECTED;
336 }
285 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 337 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
286 338
287 OVERLAPPED* overlapped = NULL; 339 OVERLAPPED* overlapped = NULL;
288 if (async_context_.get()) { 340 if (async_context_.get()) {
289 DCHECK(callback); 341 DCHECK(callback);
290 DCHECK(!async_context_->callback()); 342 DCHECK(!async_context_->callback());
291 overlapped = async_context_->overlapped(); 343 overlapped = async_context_->overlapped();
292 } else { 344 } else {
293 DCHECK(!callback); 345 DCHECK(!callback);
294 base::ThreadRestrictions::AssertIOAllowed(); 346 base::ThreadRestrictions::AssertIOAllowed();
295 } 347 }
296 348
297 int rv; 349 int rv;
298 DWORD bytes_written; 350 DWORD bytes_written;
299 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { 351 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) {
300 DWORD error = GetLastError(); 352 DWORD error = GetLastError();
301 if (async_context_.get() && error == ERROR_IO_PENDING) { 353 if (async_context_.get() && error == ERROR_IO_PENDING) {
302 async_context_->IOCompletionIsPending(callback); 354 async_context_->IOCompletionIsPending(callback);
303 rv = ERR_IO_PENDING; 355 rv = ERR_IO_PENDING;
304 } else { 356 } else {
305 LOG(WARNING) << "WriteFile failed: " << error; 357 LOG(WARNING) << "WriteFile failed: " << error;
358 RecordFileError(error, FILE_ERROR_TYPES_WRITE, class_flags_);
306 rv = MapErrorCode(error); 359 rv = MapErrorCode(error);
307 } 360 }
308 } else if (overlapped) { 361 } else if (overlapped) {
309 async_context_->IOCompletionIsPending(callback); 362 async_context_->IOCompletionIsPending(callback);
310 rv = ERR_IO_PENDING; 363 rv = ERR_IO_PENDING;
311 } else { 364 } else {
312 rv = static_cast<int>(bytes_written); 365 rv = static_cast<int>(bytes_written);
313 } 366 }
314 return rv; 367 return rv;
315 } 368 }
316 369
317 int FileStream::Flush() { 370 int FileStream::Flush() {
318 base::ThreadRestrictions::AssertIOAllowed(); 371 base::ThreadRestrictions::AssertIOAllowed();
319 372
320 if (!IsOpen()) 373 if (!IsOpen()) {
374 RecordFileError(ERROR_INVALID_HANDLE, FILE_ERROR_TYPES_IS_NOT_OPEN,
375 class_flags_);
321 return ERR_UNEXPECTED; 376 return ERR_UNEXPECTED;
377 }
322 378
323 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 379 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
324 if (FlushFileBuffers(file_)) { 380 if (FlushFileBuffers(file_)) {
325 return OK; 381 return OK;
326 } 382 }
327 383
328 int rv; 384 int rv;
329 DWORD error = GetLastError(); 385 DWORD error = GetLastError();
386 RecordFileError(error, FILE_ERROR_TYPES_FLUSH, class_flags_);
330 rv = MapErrorCode(error); 387 rv = MapErrorCode(error);
331 return rv; 388 return rv;
332 } 389 }
333 390
334 int64 FileStream::Truncate(int64 bytes) { 391 int64 FileStream::Truncate(int64 bytes) {
335 base::ThreadRestrictions::AssertIOAllowed(); 392 base::ThreadRestrictions::AssertIOAllowed();
336 393
337 if (!IsOpen()) 394 if (!IsOpen()) {
395 RecordFileError(ERROR_INVALID_HANDLE, FILE_ERROR_TYPES_IS_NOT_OPEN,
396 class_flags_);
338 return ERR_UNEXPECTED; 397 return ERR_UNEXPECTED;
398 }
339 399
340 // We better be open for reading. 400 // We better be open for reading.
341 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 401 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
342 402
343 // Seek to the position to truncate from. 403 // Seek to the position to truncate from.
344 int64 seek_position = Seek(FROM_BEGIN, bytes); 404 int64 seek_position = Seek(FROM_BEGIN, bytes);
345 if (seek_position != bytes) 405 if (seek_position != bytes)
346 return ERR_UNEXPECTED; 406 return ERR_UNEXPECTED;
347 407
348 // And truncate the file. 408 // And truncate the file.
349 BOOL result = SetEndOfFile(file_); 409 BOOL result = SetEndOfFile(file_);
350 if (!result) { 410 if (!result) {
351 DWORD error = GetLastError(); 411 DWORD error = GetLastError();
352 LOG(WARNING) << "SetEndOfFile failed: " << error; 412 LOG(WARNING) << "SetEndOfFile failed: " << error;
413 RecordFileError(error, FILE_ERROR_TYPES_SET_EOF, class_flags_);
353 return MapErrorCode(error); 414 return MapErrorCode(error);
354 } 415 }
355 416
356 // Success. 417 // Success.
357 return seek_position; 418 return seek_position;
358 } 419 }
359 420
421 void FileStream::EnableRecording(bool enable, int class_flags) {
422 if (enable)
423 class_flags_ |= class_flags;
424 else
425 class_flags_ &= ~class_flags;
426
427 if (async_context_.get())
428 async_context_->EnableRecording(enable, class_flags);
429 }
430
360 } // namespace net 431 } // namespace net
OLDNEW
« net/base/file_stream_posix.cc ('K') | « net/base/file_stream_posix.cc ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698