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

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

Issue 9402014: net: FileStream::Read/Write() to take IOBuffer* instead of char* (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 8 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 | Annotate | Revision Log
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.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"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
14 #include "net/base/file_stream_metrics.h" 14 #include "net/base/file_stream_metrics.h"
15 #include "net/base/file_stream_net_log_parameters.h" 15 #include "net/base/file_stream_net_log_parameters.h"
16 #include "net/base/io_buffer.h"
16 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
17 18
18 namespace net { 19 namespace net {
19 20
20 // Ensure that we can just use our Whence values directly. 21 // Ensure that we can just use our Whence values directly.
21 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); 22 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin);
22 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); 23 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current);
23 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); 24 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end);
24 25
25 static void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { 26 static void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { 63 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler {
63 public: 64 public:
64 explicit AsyncContext(const net::BoundNetLog& bound_net_log) 65 explicit AsyncContext(const net::BoundNetLog& bound_net_log)
65 : context_(), is_closing_(false), 66 : context_(), is_closing_(false),
66 record_uma_(false), bound_net_log_(bound_net_log), 67 record_uma_(false), bound_net_log_(bound_net_log),
67 error_source_(FILE_ERROR_SOURCE_COUNT) { 68 error_source_(FILE_ERROR_SOURCE_COUNT) {
68 context_.handler = this; 69 context_.handler = this;
69 } 70 }
70 ~AsyncContext(); 71 ~AsyncContext();
71 72
72 void IOCompletionIsPending(const CompletionCallback& callback); 73 void IOCompletionIsPending(const CompletionCallback& callback,
74 IOBuffer* buf);
73 75
74 OVERLAPPED* overlapped() { return &context_.overlapped; } 76 OVERLAPPED* overlapped() { return &context_.overlapped; }
75 const CompletionCallback& callback() const { return callback_; } 77 const CompletionCallback& callback() const { return callback_; }
76 78
77 void set_error_source(FileErrorSource source) { error_source_ = source; } 79 void set_error_source(FileErrorSource source) { error_source_ = source; }
78 80
79 void EnableErrorStatistics() { 81 void EnableErrorStatistics() {
80 record_uma_ = true; 82 record_uma_ = true;
81 } 83 }
82 84
83 private: 85 private:
84 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 86 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
85 DWORD bytes_read, DWORD error) OVERRIDE; 87 DWORD bytes_read, DWORD error) OVERRIDE;
86 88
87 MessageLoopForIO::IOContext context_; 89 MessageLoopForIO::IOContext context_;
88 CompletionCallback callback_; 90 CompletionCallback callback_;
91 scoped_refptr<IOBuffer> in_flight_buf_;
89 bool is_closing_; 92 bool is_closing_;
90 bool record_uma_; 93 bool record_uma_;
91 const net::BoundNetLog bound_net_log_; 94 const net::BoundNetLog bound_net_log_;
92 FileErrorSource error_source_; 95 FileErrorSource error_source_;
93 }; 96 };
94 97
95 FileStream::AsyncContext::~AsyncContext() { 98 FileStream::AsyncContext::~AsyncContext() {
96 is_closing_ = true; 99 is_closing_ = true;
97 bool waited = false; 100 bool waited = false;
98 base::TimeTicks start = base::TimeTicks::Now(); 101 base::TimeTicks start = base::TimeTicks::Now();
99 while (!callback_.is_null()) { 102 while (!callback_.is_null()) {
100 waited = true; 103 waited = true;
101 MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); 104 MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this);
102 } 105 }
103 if (waited) { 106 if (waited) {
104 // We want to see if we block the message loop for too long. 107 // We want to see if we block the message loop for too long.
105 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose", 108 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose",
106 base::TimeTicks::Now() - start); 109 base::TimeTicks::Now() - start);
107 } 110 }
108 } 111 }
109 112
110 void FileStream::AsyncContext::IOCompletionIsPending( 113 void FileStream::AsyncContext::IOCompletionIsPending(
111 const CompletionCallback& callback) { 114 const CompletionCallback& callback,
115 IOBuffer* buf) {
112 DCHECK(callback_.is_null()); 116 DCHECK(callback_.is_null());
113 callback_ = callback; 117 callback_ = callback;
118 in_flight_buf_ = buf; // Hold until the async operation ends.
114 } 119 }
115 120
116 void FileStream::AsyncContext::OnIOCompleted( 121 void FileStream::AsyncContext::OnIOCompleted(
117 MessageLoopForIO::IOContext* context, DWORD bytes_read, DWORD error) { 122 MessageLoopForIO::IOContext* context, DWORD bytes_read, DWORD error) {
118 DCHECK_EQ(&context_, context); 123 DCHECK_EQ(&context_, context);
119 DCHECK(!callback_.is_null()); 124 DCHECK(!callback_.is_null());
120 125
121 if (is_closing_) { 126 if (is_closing_) {
122 callback_.Reset(); 127 callback_.Reset();
128 in_flight_buf_ = NULL;
123 return; 129 return;
124 } 130 }
125 131
126 int result = static_cast<int>(bytes_read); 132 int result = static_cast<int>(bytes_read);
127 if (error && error != ERROR_HANDLE_EOF) { 133 if (error && error != ERROR_HANDLE_EOF) {
128 result = RecordAndMapError(error, error_source_, record_uma_, 134 result = RecordAndMapError(error, error_source_, record_uma_,
129 bound_net_log_); 135 bound_net_log_);
130 } 136 }
131 137
132 if (bytes_read) 138 if (bytes_read)
133 IncrementOffset(&context->overlapped, bytes_read); 139 IncrementOffset(&context->overlapped, bytes_read);
134 140
135 CompletionCallback temp; 141 CompletionCallback temp_callback = callback_;
136 std::swap(temp, callback_); 142 callback_.Reset();
137 temp.Run(result); 143 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
144 in_flight_buf_ = NULL;
145 temp_callback.Run(result);
138 } 146 }
139 147
140 // FileStream ------------------------------------------------------------ 148 // FileStream ------------------------------------------------------------
141 149
142 FileStream::FileStream(net::NetLog* net_log) 150 FileStream::FileStream(net::NetLog* net_log)
143 : file_(base::kInvalidPlatformFileValue), 151 : file_(base::kInvalidPlatformFileValue),
144 open_flags_(0), 152 open_flags_(0),
145 auto_closed_(true), 153 auto_closed_(true),
146 record_uma_(false), 154 record_uma_(false),
147 bound_net_log_(net::BoundNetLog::Make(net_log, 155 bound_net_log_(net::BoundNetLog::Make(net_log,
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 return RecordAndMapError(error, 278 return RecordAndMapError(error,
271 FILE_ERROR_SOURCE_GET_SIZE, 279 FILE_ERROR_SOURCE_GET_SIZE,
272 record_uma_, 280 record_uma_,
273 bound_net_log_); 281 bound_net_log_);
274 } 282 }
275 283
276 return file_size.QuadPart - cur_pos; 284 return file_size.QuadPart - cur_pos;
277 } 285 }
278 286
279 int FileStream::Read( 287 int FileStream::Read(
280 char* buf, int buf_len, const CompletionCallback& callback) { 288 IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
281 DCHECK(async_context_.get()); 289 DCHECK(async_context_.get());
282 return ReadInternal(buf, buf_len, callback);
283 }
284 290
285 int FileStream::ReadSync(char* buf, int buf_len) {
286 DCHECK(!async_context_.get());
287 return ReadInternal(buf, buf_len, CompletionCallback());
288 }
289
290 int FileStream::ReadInternal(
291 char* buf, int buf_len, const CompletionCallback& callback) {
292 if (!IsOpen()) 291 if (!IsOpen())
293 return ERR_UNEXPECTED; 292 return ERR_UNEXPECTED;
294 293
295 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); 294 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
296 295
297 OVERLAPPED* overlapped = NULL; 296 OVERLAPPED* overlapped = NULL;
298 if (async_context_.get()) { 297 DCHECK(!callback.is_null());
299 DCHECK(!callback.is_null()); 298 DCHECK(async_context_->callback().is_null());
300 DCHECK(async_context_->callback().is_null()); 299 overlapped = async_context_->overlapped();
301 overlapped = async_context_->overlapped(); 300 async_context_->set_error_source(FILE_ERROR_SOURCE_READ);
302 async_context_->set_error_source(FILE_ERROR_SOURCE_READ);
303 } else {
304 DCHECK(callback.is_null());
305 base::ThreadRestrictions::AssertIOAllowed();
306 }
307 301
308 int rv; 302 int rv = 0;
309 303
310 DWORD bytes_read; 304 DWORD bytes_read;
311 if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) { 305 if (!ReadFile(file_, buf->data(), buf_len, &bytes_read, overlapped)) {
312 DWORD error = GetLastError(); 306 DWORD error = GetLastError();
313 if (async_context_.get() && error == ERROR_IO_PENDING) { 307 if (error == ERROR_IO_PENDING) {
314 async_context_->IOCompletionIsPending(callback); 308 async_context_->IOCompletionIsPending(callback, buf);
315 rv = ERR_IO_PENDING; 309 rv = ERR_IO_PENDING;
316 } else if (error == ERROR_HANDLE_EOF) { 310 } else if (error == ERROR_HANDLE_EOF) {
317 rv = 0; // Report EOF by returning 0 bytes read. 311 rv = 0; // Report EOF by returning 0 bytes read.
318 } else { 312 } else {
319 LOG(WARNING) << "ReadFile failed: " << error; 313 LOG(WARNING) << "ReadFile failed: " << error;
320 rv = RecordAndMapError(error, 314 rv = RecordAndMapError(error,
321 FILE_ERROR_SOURCE_READ, 315 FILE_ERROR_SOURCE_READ,
322 record_uma_, 316 record_uma_,
323 bound_net_log_); 317 bound_net_log_);
324 } 318 }
325 } else if (overlapped) { 319 } else if (overlapped) {
326 async_context_->IOCompletionIsPending(callback); 320 async_context_->IOCompletionIsPending(callback, buf);
327 rv = ERR_IO_PENDING; 321 rv = ERR_IO_PENDING;
328 } else { 322 } else {
329 rv = static_cast<int>(bytes_read); 323 rv = static_cast<int>(bytes_read);
330 } 324 }
331 return rv; 325 return rv;
332 } 326 }
333 327
328 int FileStream::ReadSync(char* buf, int buf_len) {
329 DCHECK(!async_context_.get());
330
331 if (!IsOpen())
332 return ERR_UNEXPECTED;
333
334 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
335
336 base::ThreadRestrictions::AssertIOAllowed();
willchan no longer on Chromium 2012/02/15 23:37:49 Can this move up higher?
satorux1 2012/02/16 00:11:57 Done.
337
338 int rv = 0;
339
340 DWORD bytes_read;
341 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) {
342 DWORD error = GetLastError();
343 if (error == ERROR_HANDLE_EOF) {
344 rv = 0; // Report EOF by returning 0 bytes read.
345 } else {
346 LOG(WARNING) << "ReadFile failed: " << error;
347 rv = RecordAndMapError(error,
348 FILE_ERROR_SOURCE_READ,
349 record_uma_,
350 bound_net_log_);
351 }
352 } else {
353 rv = static_cast<int>(bytes_read);
354 }
355 return rv;
356 }
357
334 int FileStream::ReadUntilComplete(char *buf, int buf_len) { 358 int FileStream::ReadUntilComplete(char *buf, int buf_len) {
335 int to_read = buf_len; 359 int to_read = buf_len;
336 int bytes_total = 0; 360 int bytes_total = 0;
337 361
338 do { 362 do {
339 int bytes_read = ReadSync(buf, to_read); 363 int bytes_read = ReadSync(buf, to_read);
340 if (bytes_read <= 0) { 364 if (bytes_read <= 0) {
341 if (bytes_total == 0) 365 if (bytes_total == 0)
342 return bytes_read; 366 return bytes_read;
343 367
344 return bytes_total; 368 return bytes_total;
345 } 369 }
346 370
347 bytes_total += bytes_read; 371 bytes_total += bytes_read;
348 buf += bytes_read; 372 buf += bytes_read;
349 to_read -= bytes_read; 373 to_read -= bytes_read;
350 } while (bytes_total < buf_len); 374 } while (bytes_total < buf_len);
351 375
352 return bytes_total; 376 return bytes_total;
353 } 377 }
354 378
355 int FileStream::Write( 379 int FileStream::Write(
356 const char* buf, int buf_len, const CompletionCallback& callback) { 380 IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
357 DCHECK(async_context_.get()); 381 DCHECK(async_context_.get());
358 return WriteInternal(buf, buf_len, callback);
359 }
360 382
361 int FileStream::WriteSync(
362 const char* buf, int buf_len) {
363 DCHECK(!async_context_.get());
364 return WriteInternal(buf, buf_len, CompletionCallback());
365 }
366
367 int FileStream::WriteInternal(
368 const char* buf, int buf_len, const CompletionCallback& callback) {
369 if (!IsOpen()) 383 if (!IsOpen())
370 return ERR_UNEXPECTED; 384 return ERR_UNEXPECTED;
371 385
372 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 386 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
373 387
374 OVERLAPPED* overlapped = NULL; 388 OVERLAPPED* overlapped = NULL;
375 if (async_context_.get()) { 389 DCHECK(!callback.is_null());
376 DCHECK(!callback.is_null()); 390 DCHECK(async_context_->callback().is_null());
377 DCHECK(async_context_->callback().is_null()); 391 overlapped = async_context_->overlapped();
378 overlapped = async_context_->overlapped(); 392 async_context_->set_error_source(FILE_ERROR_SOURCE_WRITE);
379 async_context_->set_error_source(FILE_ERROR_SOURCE_WRITE);
380 } else {
381 DCHECK(callback.is_null());
382 base::ThreadRestrictions::AssertIOAllowed();
383 }
384 393
385 int rv; 394 int rv = 0;
386 DWORD bytes_written; 395 DWORD bytes_written = 0;
387 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { 396 if (!WriteFile(file_, buf->data(), buf_len, &bytes_written, overlapped)) {
388 DWORD error = GetLastError(); 397 DWORD error = GetLastError();
389 if (async_context_.get() && error == ERROR_IO_PENDING) { 398 if (error == ERROR_IO_PENDING) {
390 async_context_->IOCompletionIsPending(callback); 399 async_context_->IOCompletionIsPending(callback, buf);
391 rv = ERR_IO_PENDING; 400 rv = ERR_IO_PENDING;
392 } else { 401 } else {
393 LOG(WARNING) << "WriteFile failed: " << error; 402 LOG(WARNING) << "WriteFile failed: " << error;
394 rv = RecordAndMapError(error, 403 rv = RecordAndMapError(error,
395 FILE_ERROR_SOURCE_WRITE, 404 FILE_ERROR_SOURCE_WRITE,
396 record_uma_, 405 record_uma_,
397 bound_net_log_); 406 bound_net_log_);
398 } 407 }
399 } else if (overlapped) { 408 } else if (overlapped) {
400 async_context_->IOCompletionIsPending(callback); 409 async_context_->IOCompletionIsPending(callback, buf);
401 rv = ERR_IO_PENDING; 410 rv = ERR_IO_PENDING;
402 } else { 411 } else {
403 rv = static_cast<int>(bytes_written); 412 rv = static_cast<int>(bytes_written);
404 } 413 }
405 return rv; 414 return rv;
406 } 415 }
407 416
417 int FileStream::WriteSync(
418 const char* buf, int buf_len) {
419 DCHECK(!async_context_.get());
420
421 if (!IsOpen())
422 return ERR_UNEXPECTED;
423
424 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
425
426 base::ThreadRestrictions::AssertIOAllowed();
willchan no longer on Chromium 2012/02/15 23:37:49 This too.
satorux1 2012/02/16 00:11:57 Done.
427
428 int rv = 0;
429 DWORD bytes_written = 0;
430 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) {
431 DWORD error = GetLastError();
432 LOG(WARNING) << "WriteFile failed: " << error;
433 rv = RecordAndMapError(error,
434 FILE_ERROR_SOURCE_WRITE,
435 record_uma_,
436 bound_net_log_);
437 } else {
438 rv = static_cast<int>(bytes_written);
439 }
440 return rv;
441 }
442
408 int FileStream::Flush() { 443 int FileStream::Flush() {
409 base::ThreadRestrictions::AssertIOAllowed(); 444 base::ThreadRestrictions::AssertIOAllowed();
410 445
411 if (!IsOpen()) 446 if (!IsOpen())
412 return ERR_UNEXPECTED; 447 return ERR_UNEXPECTED;
413 448
414 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 449 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
415 if (FlushFileBuffers(file_)) { 450 if (FlushFileBuffers(file_)) {
416 return OK; 451 return OK;
417 } 452 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 owner_bound_net_log.source()))); 511 owner_bound_net_log.source())));
477 512
478 owner_bound_net_log.AddEvent( 513 owner_bound_net_log.AddEvent(
479 net::NetLog::TYPE_FILE_STREAM_SOURCE, 514 net::NetLog::TYPE_FILE_STREAM_SOURCE,
480 make_scoped_refptr( 515 make_scoped_refptr(
481 new net::NetLogSourceParameter("source_dependency", 516 new net::NetLogSourceParameter("source_dependency",
482 bound_net_log_.source()))); 517 bound_net_log_.source())));
483 } 518 }
484 519
485 } // namespace net 520 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698