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

Side by Side Diff: net/base/file_stream_posix.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.h ('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
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 // For 64-bit file access (off_t = off64_t, lseek64, etc). 5 // For 64-bit file access (off_t = off64_t, lseek64, etc).
6 #define _FILE_OFFSET_BITS 64 6 #define _FILE_OFFSET_BITS 64
7 7
8 #include "net/base/file_stream.h" 8 #include "net/base/file_stream.h"
9 9
10 #include <sys/types.h> 10 #include <sys/types.h>
(...skipping 10 matching lines...) Expand all
21 #include "base/file_path.h" 21 #include "base/file_path.h"
22 #include "base/logging.h" 22 #include "base/logging.h"
23 #include "base/message_loop.h" 23 #include "base/message_loop.h"
24 #include "base/metrics/histogram.h" 24 #include "base/metrics/histogram.h"
25 #include "base/string_util.h" 25 #include "base/string_util.h"
26 #include "base/threading/thread_restrictions.h" 26 #include "base/threading/thread_restrictions.h"
27 #include "base/threading/worker_pool.h" 27 #include "base/threading/worker_pool.h"
28 #include "base/synchronization/waitable_event.h" 28 #include "base/synchronization/waitable_event.h"
29 #include "net/base/file_stream_metrics.h" 29 #include "net/base/file_stream_metrics.h"
30 #include "net/base/file_stream_net_log_parameters.h" 30 #include "net/base/file_stream_net_log_parameters.h"
31 #include "net/base/io_buffer.h"
31 #include "net/base/net_errors.h" 32 #include "net/base/net_errors.h"
32 33
33 #if defined(OS_ANDROID) 34 #if defined(OS_ANDROID)
34 // Android's bionic libc only supports the LFS transitional API. 35 // Android's bionic libc only supports the LFS transitional API.
35 #define off_t off64_t 36 #define off_t off64_t
36 #define lseek lseek64 37 #define lseek lseek64
37 #define stat stat64 38 #define stat stat64
38 #define fstat fstat64 39 #define fstat fstat64
39 #endif 40 #endif
40 41
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 161
161 // FileStream::AsyncContext ---------------------------------------------- 162 // FileStream::AsyncContext ----------------------------------------------
162 163
163 class FileStream::AsyncContext { 164 class FileStream::AsyncContext {
164 public: 165 public:
165 AsyncContext(); 166 AsyncContext();
166 ~AsyncContext(); 167 ~AsyncContext();
167 168
168 // These methods post synchronous read() and write() calls to a WorkerThread. 169 // These methods post synchronous read() and write() calls to a WorkerThread.
169 void InitiateAsyncRead( 170 void InitiateAsyncRead(
170 base::PlatformFile file, char* buf, int buf_len, 171 base::PlatformFile file, IOBuffer* buf, int buf_len,
171 const net::BoundNetLog& bound_net_log, 172 const net::BoundNetLog& bound_net_log,
172 const CompletionCallback& callback); 173 const CompletionCallback& callback);
173 void InitiateAsyncWrite( 174 void InitiateAsyncWrite(
174 base::PlatformFile file, const char* buf, int buf_len, 175 base::PlatformFile file, IOBuffer* buf, int buf_len,
175 const net::BoundNetLog& bound_net_log, 176 const net::BoundNetLog& bound_net_log,
176 const CompletionCallback& callback); 177 const CompletionCallback& callback);
177 178
178 const CompletionCallback& callback() const { return callback_; } 179 const CompletionCallback& callback() const { return callback_; }
179 180
180 // Called by the WorkerPool thread executing the IO after the IO completes. 181 // Called by the WorkerPool thread executing the IO after the IO completes.
181 // This method queues RunAsynchronousCallback() on the MessageLoop and signals 182 // This method queues RunAsynchronousCallback() on the MessageLoop and signals
182 // |background_io_completed_callback_|, in case the destructor is waiting. In 183 // |background_io_completed_callback_|, in case the destructor is waiting. In
183 // that case, the destructor will call RunAsynchronousCallback() instead, and 184 // that case, the destructor will call RunAsynchronousCallback() instead, and
184 // cancel |message_loop_task_|. 185 // cancel |message_loop_task_|.
185 // |result| is the result of the Read/Write task. 186 // |result| is the result of the Read/Write task.
186 void OnBackgroundIOCompleted(int result); 187 void OnBackgroundIOCompleted(int result);
187 188
188 void EnableErrorStatistics() { 189 void EnableErrorStatistics() {
189 record_uma_ = true; 190 record_uma_ = true;
190 } 191 }
191 192
192 private: 193 private:
193 // Always called on the IO thread, either directly by a task on the 194 // Always called on the IO thread, either directly by a task on the
194 // MessageLoop or by ~AsyncContext(). 195 // MessageLoop or by ~AsyncContext().
195 void RunAsynchronousCallback(); 196 void RunAsynchronousCallback();
196 197
197 // The MessageLoopForIO that this AsyncContext is running on. 198 // The MessageLoopForIO that this AsyncContext is running on.
198 MessageLoopForIO* const message_loop_; 199 MessageLoopForIO* const message_loop_;
199 CompletionCallback callback_; // The user provided callback. 200 CompletionCallback callback_; // The user provided callback.
201 scoped_refptr<IOBuffer> in_flight_buf_;
200 202
201 // This is used to synchronize between the AsyncContext destructor (which runs 203 // This is used to synchronize between the AsyncContext destructor (which runs
202 // on the IO thread and OnBackgroundIOCompleted() which runs on the WorkerPool 204 // on the IO thread and OnBackgroundIOCompleted() which runs on the WorkerPool
203 // thread. 205 // thread.
204 base::WaitableEvent background_io_completed_; 206 base::WaitableEvent background_io_completed_;
205 207
206 // These variables are only valid when background_io_completed is signaled. 208 // These variables are only valid when background_io_completed is signaled.
207 int result_; 209 int result_;
208 CancelableCallback* message_loop_task_; 210 CancelableCallback* message_loop_task_;
209 211
(...skipping 21 matching lines...) Expand all
231 RunAsynchronousCallback(); 233 RunAsynchronousCallback();
232 if (need_to_wait) { 234 if (need_to_wait) {
233 // We want to see if we block the message loop for too long. 235 // We want to see if we block the message loop for too long.
234 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose", 236 UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose",
235 base::TimeTicks::Now() - start); 237 base::TimeTicks::Now() - start);
236 } 238 }
237 } 239 }
238 } 240 }
239 241
240 void FileStream::AsyncContext::InitiateAsyncRead( 242 void FileStream::AsyncContext::InitiateAsyncRead(
241 base::PlatformFile file, char* buf, int buf_len, 243 base::PlatformFile file, IOBuffer* buf, int buf_len,
242 const net::BoundNetLog& bound_net_log, 244 const net::BoundNetLog& bound_net_log,
243 const CompletionCallback& callback) { 245 const CompletionCallback& callback) {
244 DCHECK(callback_.is_null()); 246 DCHECK(callback_.is_null());
247 DCHECK(!in_flight_buf_);
245 callback_ = callback; 248 callback_ = callback;
249 in_flight_buf_ = buf; // Hold until the async operation ends.
246 250
247 base::WorkerPool::PostTask( 251 base::WorkerPool::PostTask(
248 FROM_HERE, 252 FROM_HERE,
249 base::Bind(&ReadFileTask, 253 base::Bind(&ReadFileTask,
250 file, 254 file,
251 buf, 255 buf->data(),
252 buf_len, 256 buf_len,
253 record_uma_, 257 record_uma_,
254 bound_net_log, 258 bound_net_log,
255 base::Bind(&AsyncContext::OnBackgroundIOCompleted, 259 base::Bind(&AsyncContext::OnBackgroundIOCompleted,
256 base::Unretained(this))), 260 base::Unretained(this))),
257 true /* task_is_slow */); 261 true /* task_is_slow */);
258 } 262 }
259 263
260 void FileStream::AsyncContext::InitiateAsyncWrite( 264 void FileStream::AsyncContext::InitiateAsyncWrite(
261 base::PlatformFile file, const char* buf, int buf_len, 265 base::PlatformFile file, IOBuffer* buf, int buf_len,
262 const net::BoundNetLog& bound_net_log, 266 const net::BoundNetLog& bound_net_log,
263 const CompletionCallback& callback) { 267 const CompletionCallback& callback) {
264 DCHECK(callback_.is_null()); 268 DCHECK(callback_.is_null());
269 DCHECK(!in_flight_buf_);
265 callback_ = callback; 270 callback_ = callback;
271 in_flight_buf_ = buf; // Hold until the async operation ends.
266 272
267 base::WorkerPool::PostTask( 273 base::WorkerPool::PostTask(
268 FROM_HERE, 274 FROM_HERE,
269 base::Bind(&WriteFileTask, 275 base::Bind(&WriteFileTask,
270 file, 276 file,
271 buf, 277 buf->data(),
272 buf_len, 278 buf_len,
273 record_uma_, 279 record_uma_,
274 bound_net_log, 280 bound_net_log,
275 base::Bind(&AsyncContext::OnBackgroundIOCompleted, 281 base::Bind(&AsyncContext::OnBackgroundIOCompleted,
276 base::Unretained(this))), 282 base::Unretained(this))),
277 true /* task_is_slow */); 283 true /* task_is_slow */);
278 } 284 }
279 285
280 void FileStream::AsyncContext::OnBackgroundIOCompleted(int result) { 286 void FileStream::AsyncContext::OnBackgroundIOCompleted(int result) {
281 result_ = result; 287 result_ = result;
(...skipping 12 matching lines...) Expand all
294 background_io_completed_.Wait(); 300 background_io_completed_.Wait();
295 301
296 // Either we're in the MessageLoop's task, in which case Cancel() doesn't do 302 // Either we're in the MessageLoop's task, in which case Cancel() doesn't do
297 // anything, or we're in ~AsyncContext(), in which case this prevents the call 303 // anything, or we're in ~AsyncContext(), in which case this prevents the call
298 // from happening again. Must do it here after calling Wait(). 304 // from happening again. Must do it here after calling Wait().
299 message_loop_task_->Cancel(); 305 message_loop_task_->Cancel();
300 message_loop_task_ = NULL; // lifetime handled by base::Owned 306 message_loop_task_ = NULL; // lifetime handled by base::Owned
301 307
302 if (is_closing_) { 308 if (is_closing_) {
303 callback_.Reset(); 309 callback_.Reset();
310 in_flight_buf_ = NULL;
304 return; 311 return;
305 } 312 }
306 313
307 DCHECK(!callback_.is_null()); 314 DCHECK(!callback_.is_null());
308 CompletionCallback temp; 315 CompletionCallback temp_callback = callback_;
309 std::swap(temp, callback_); 316 callback_.Reset();
317 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
318 in_flight_buf_ = NULL;
310 background_io_completed_.Reset(); 319 background_io_completed_.Reset();
311 temp.Run(result_); 320 temp_callback.Run(result_);
312 } 321 }
313 322
314 // FileStream ------------------------------------------------------------ 323 // FileStream ------------------------------------------------------------
315 324
316 FileStream::FileStream(net::NetLog* net_log) 325 FileStream::FileStream(net::NetLog* net_log)
317 : file_(base::kInvalidPlatformFileValue), 326 : file_(base::kInvalidPlatformFileValue),
318 open_flags_(0), 327 open_flags_(0),
319 auto_closed_(true), 328 auto_closed_(true),
320 record_uma_(false), 329 record_uma_(false),
321 bound_net_log_(net::BoundNetLog::Make(net_log, 330 bound_net_log_(net::BoundNetLog::Make(net_log,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 bound_net_log_); 442 bound_net_log_);
434 } 443 }
435 444
436 int64 size = static_cast<int64>(info.st_size); 445 int64 size = static_cast<int64>(info.st_size);
437 DCHECK_GT(size, cur_pos); 446 DCHECK_GT(size, cur_pos);
438 447
439 return size - cur_pos; 448 return size - cur_pos;
440 } 449 }
441 450
442 int FileStream::Read( 451 int FileStream::Read(
443 char* buf, int buf_len, const CompletionCallback& callback) { 452 IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
444 DCHECK(async_context_.get()); 453 DCHECK(async_context_.get());
445 return ReadInternal(buf, buf_len, callback); 454
455 if (!IsOpen())
456 return ERR_UNEXPECTED;
457
458 // read(..., 0) will return 0, which indicates end-of-file.
459 DCHECK_GT(buf_len, 0);
460 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
461
462 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
463 // Make sure we don't have a request in flight.
464 DCHECK(async_context_->callback().is_null());
465 if (record_uma_)
466 async_context_->EnableErrorStatistics();
467 async_context_->InitiateAsyncRead(file_, buf, buf_len, bound_net_log_,
468 callback);
469 return ERR_IO_PENDING;
446 } 470 }
447 471
448 int FileStream::ReadSync(char* buf, int buf_len) { 472 int FileStream::ReadSync(char* buf, int buf_len) {
449 DCHECK(!async_context_.get()); 473 DCHECK(!async_context_.get());
450 return ReadInternal(buf, buf_len, CompletionCallback());
451 }
452 474
453 int FileStream::ReadInternal(
454 char* buf, int buf_len, const CompletionCallback& callback) {
455 if (!IsOpen()) 475 if (!IsOpen())
456 return ERR_UNEXPECTED; 476 return ERR_UNEXPECTED;
457 477
458 // read(..., 0) will return 0, which indicates end-of-file. 478 // read(..., 0) will return 0, which indicates end-of-file.
459 DCHECK_GT(buf_len, 0); 479 DCHECK_GT(buf_len, 0);
460 DCHECK(open_flags_ & base::PLATFORM_FILE_READ); 480 DCHECK(open_flags_ & base::PLATFORM_FILE_READ);
461 481
462 if (async_context_.get()) { 482 return ReadFile(file_, buf, buf_len, record_uma_, bound_net_log_);
463 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
464 // If we're in async, make sure we don't have a request in flight.
465 DCHECK(async_context_->callback().is_null());
466 if (record_uma_)
467 async_context_->EnableErrorStatistics();
468 async_context_->InitiateAsyncRead(file_, buf, buf_len, bound_net_log_,
469 callback);
470 return ERR_IO_PENDING;
471 } else {
472 return ReadFile(file_, buf, buf_len, record_uma_, bound_net_log_);
473 }
474 } 483 }
475 484
476 int FileStream::ReadUntilComplete(char *buf, int buf_len) { 485 int FileStream::ReadUntilComplete(char *buf, int buf_len) {
477 int to_read = buf_len; 486 int to_read = buf_len;
478 int bytes_total = 0; 487 int bytes_total = 0;
479 488
480 do { 489 do {
481 int bytes_read = ReadSync(buf, to_read); 490 int bytes_read = ReadSync(buf, to_read);
482 if (bytes_read <= 0) { 491 if (bytes_read <= 0) {
483 if (bytes_total == 0) 492 if (bytes_total == 0)
484 return bytes_read; 493 return bytes_read;
485 494
486 return bytes_total; 495 return bytes_total;
487 } 496 }
488 497
489 bytes_total += bytes_read; 498 bytes_total += bytes_read;
490 buf += bytes_read; 499 buf += bytes_read;
491 to_read -= bytes_read; 500 to_read -= bytes_read;
492 } while (bytes_total < buf_len); 501 } while (bytes_total < buf_len);
493 502
494 return bytes_total; 503 return bytes_total;
495 } 504 }
496 505
497 int FileStream::Write( 506 int FileStream::Write(
498 const char* buf, int buf_len, const CompletionCallback& callback) { 507 IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
499 DCHECK(async_context_.get()); 508 DCHECK(async_context_.get());
500 return WriteInternal(buf, buf_len, callback);
501 }
502 509
503 int FileStream::WriteSync(
504 const char* buf, int buf_len) {
505 DCHECK(!async_context_.get());
506 return WriteInternal(buf, buf_len, CompletionCallback());
507 }
508
509 int FileStream::WriteInternal(
510 const char* buf, int buf_len, const CompletionCallback& callback) {
511 // write(..., 0) will return 0, which indicates end-of-file. 510 // write(..., 0) will return 0, which indicates end-of-file.
512 DCHECK_GT(buf_len, 0); 511 DCHECK_GT(buf_len, 0);
513 512
514 if (!IsOpen()) 513 if (!IsOpen())
515 return ERR_UNEXPECTED; 514 return ERR_UNEXPECTED;
516 515
517 if (async_context_.get()) { 516 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC);
518 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); 517 // Make sure we don't have a request in flight.
519 // If we're in async, make sure we don't have a request in flight. 518 DCHECK(async_context_->callback().is_null());
520 DCHECK(async_context_->callback().is_null()); 519 if (record_uma_)
521 if (record_uma_) 520 async_context_->EnableErrorStatistics();
522 async_context_->EnableErrorStatistics(); 521 async_context_->InitiateAsyncWrite(file_, buf, buf_len, bound_net_log_,
523 async_context_->InitiateAsyncWrite(file_, buf, buf_len, bound_net_log_, 522 callback);
524 callback); 523 return ERR_IO_PENDING;
525 return ERR_IO_PENDING; 524 }
526 } else { 525
527 return WriteFile(file_, buf, buf_len, record_uma_, bound_net_log_); 526 int FileStream::WriteSync(
528 } 527 const char* buf, int buf_len) {
528 DCHECK(!async_context_.get());
529
530 // write(..., 0) will return 0, which indicates end-of-file.
531 DCHECK_GT(buf_len, 0);
532
533 if (!IsOpen())
534 return ERR_UNEXPECTED;
535
536 return WriteFile(file_, buf, buf_len, record_uma_, bound_net_log_);
529 } 537 }
530 538
531 int64 FileStream::Truncate(int64 bytes) { 539 int64 FileStream::Truncate(int64 bytes) {
532 base::ThreadRestrictions::AssertIOAllowed(); 540 base::ThreadRestrictions::AssertIOAllowed();
533 541
534 if (!IsOpen()) 542 if (!IsOpen())
535 return ERR_UNEXPECTED; 543 return ERR_UNEXPECTED;
536 544
537 // We'd better be open for writing. 545 // We'd better be open for writing.
538 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 546 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 owner_bound_net_log.source()))); 590 owner_bound_net_log.source())));
583 591
584 owner_bound_net_log.AddEvent( 592 owner_bound_net_log.AddEvent(
585 net::NetLog::TYPE_FILE_STREAM_SOURCE, 593 net::NetLog::TYPE_FILE_STREAM_SOURCE,
586 make_scoped_refptr( 594 make_scoped_refptr(
587 new net::NetLogSourceParameter("source_dependency", 595 new net::NetLogSourceParameter("source_dependency",
588 bound_net_log_.source()))); 596 bound_net_log_.source())));
589 } 597 }
590 598
591 } // namespace net 599 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream.h ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698