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

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: fix redirect_to_file_resource_handler.cc 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
« no previous file with comments | « net/base/file_stream_unittest.cc ('k') | net/base/mock_file_stream.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 base::ThreadRestrictions::AssertIOAllowed();
331
332 if (!IsOpen())
333 return ERR_UNEXPECTED;
334
335 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
336
337 int rv = 0;
338
339 DWORD bytes_read;
340 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) {
341 DWORD error = GetLastError();
342 if (error == ERROR_HANDLE_EOF) {
343 rv = 0; // Report EOF by returning 0 bytes read.
344 } else {
345 LOG(WARNING) << "ReadFile failed: " << error;
346 rv = RecordAndMapError(error,
347 FILE_ERROR_SOURCE_READ,
348 record_uma_,
349 bound_net_log_);
350 }
351 } else {
352 rv = static_cast<int>(bytes_read);
353 }
354 return rv;
355 }
356
334 int FileStream::ReadUntilComplete(char *buf, int buf_len) { 357 int FileStream::ReadUntilComplete(char *buf, int buf_len) {
335 int to_read = buf_len; 358 int to_read = buf_len;
336 int bytes_total = 0; 359 int bytes_total = 0;
337 360
338 do { 361 do {
339 int bytes_read = ReadSync(buf, to_read); 362 int bytes_read = ReadSync(buf, to_read);
340 if (bytes_read <= 0) { 363 if (bytes_read <= 0) {
341 if (bytes_total == 0) 364 if (bytes_total == 0)
342 return bytes_read; 365 return bytes_read;
343 366
344 return bytes_total; 367 return bytes_total;
345 } 368 }
346 369
347 bytes_total += bytes_read; 370 bytes_total += bytes_read;
348 buf += bytes_read; 371 buf += bytes_read;
349 to_read -= bytes_read; 372 to_read -= bytes_read;
350 } while (bytes_total < buf_len); 373 } while (bytes_total < buf_len);
351 374
352 return bytes_total; 375 return bytes_total;
353 } 376 }
354 377
355 int FileStream::Write( 378 int FileStream::Write(
356 const char* buf, int buf_len, const CompletionCallback& callback) { 379 IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
357 DCHECK(async_context_.get()); 380 DCHECK(async_context_.get());
358 return WriteInternal(buf, buf_len, callback);
359 }
360 381
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()) 382 if (!IsOpen())
370 return ERR_UNEXPECTED; 383 return ERR_UNEXPECTED;
371 384
372 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 385 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
373 386
374 OVERLAPPED* overlapped = NULL; 387 OVERLAPPED* overlapped = NULL;
375 if (async_context_.get()) { 388 DCHECK(!callback.is_null());
376 DCHECK(!callback.is_null()); 389 DCHECK(async_context_->callback().is_null());
377 DCHECK(async_context_->callback().is_null()); 390 overlapped = async_context_->overlapped();
378 overlapped = async_context_->overlapped(); 391 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 392
385 int rv; 393 int rv = 0;
386 DWORD bytes_written; 394 DWORD bytes_written = 0;
387 if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { 395 if (!WriteFile(file_, buf->data(), buf_len, &bytes_written, overlapped)) {
388 DWORD error = GetLastError(); 396 DWORD error = GetLastError();
389 if (async_context_.get() && error == ERROR_IO_PENDING) { 397 if (error == ERROR_IO_PENDING) {
390 async_context_->IOCompletionIsPending(callback); 398 async_context_->IOCompletionIsPending(callback, buf);
391 rv = ERR_IO_PENDING; 399 rv = ERR_IO_PENDING;
392 } else { 400 } else {
393 LOG(WARNING) << "WriteFile failed: " << error; 401 LOG(WARNING) << "WriteFile failed: " << error;
394 rv = RecordAndMapError(error, 402 rv = RecordAndMapError(error,
395 FILE_ERROR_SOURCE_WRITE, 403 FILE_ERROR_SOURCE_WRITE,
396 record_uma_, 404 record_uma_,
397 bound_net_log_); 405 bound_net_log_);
398 } 406 }
399 } else if (overlapped) { 407 } else if (overlapped) {
400 async_context_->IOCompletionIsPending(callback); 408 async_context_->IOCompletionIsPending(callback, buf);
401 rv = ERR_IO_PENDING; 409 rv = ERR_IO_PENDING;
402 } else { 410 } else {
403 rv = static_cast<int>(bytes_written); 411 rv = static_cast<int>(bytes_written);
404 } 412 }
405 return rv; 413 return rv;
406 } 414 }
407 415
416 int FileStream::WriteSync(
417 const char* buf, int buf_len) {
418 DCHECK(!async_context_.get());
419 base::ThreadRestrictions::AssertIOAllowed();
420
421 if (!IsOpen())
422 return ERR_UNEXPECTED;
423
424 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
425
426 int rv = 0;
427 DWORD bytes_written = 0;
428 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) {
429 DWORD error = GetLastError();
430 LOG(WARNING) << "WriteFile failed: " << error;
431 rv = RecordAndMapError(error,
432 FILE_ERROR_SOURCE_WRITE,
433 record_uma_,
434 bound_net_log_);
435 } else {
436 rv = static_cast<int>(bytes_written);
437 }
438 return rv;
439 }
440
408 int FileStream::Flush() { 441 int FileStream::Flush() {
409 base::ThreadRestrictions::AssertIOAllowed(); 442 base::ThreadRestrictions::AssertIOAllowed();
410 443
411 if (!IsOpen()) 444 if (!IsOpen())
412 return ERR_UNEXPECTED; 445 return ERR_UNEXPECTED;
413 446
414 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 447 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
415 if (FlushFileBuffers(file_)) { 448 if (FlushFileBuffers(file_)) {
416 return OK; 449 return OK;
417 } 450 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 owner_bound_net_log.source()))); 509 owner_bound_net_log.source())));
477 510
478 owner_bound_net_log.AddEvent( 511 owner_bound_net_log.AddEvent(
479 net::NetLog::TYPE_FILE_STREAM_SOURCE, 512 net::NetLog::TYPE_FILE_STREAM_SOURCE,
480 make_scoped_refptr( 513 make_scoped_refptr(
481 new net::NetLogSourceParameter("source_dependency", 514 new net::NetLogSourceParameter("source_dependency",
482 bound_net_log_.source()))); 515 bound_net_log_.source())));
483 } 516 }
484 517
485 } // namespace net 518 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_unittest.cc ('k') | net/base/mock_file_stream.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698