diff options
author | satorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-16 09:59:20 +0000 |
---|---|---|
committer | satorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-16 09:59:20 +0000 |
commit | 9f49afb3ef241c12e1097c11d268247fa37f0e68 (patch) | |
tree | 3d4bc9aa1595fb803d333f47e9e2b7c4c80d7a65 /net | |
parent | b89912e30fafc2205cd20439f22195baf48b3d76 (diff) | |
download | chromium_src-9f49afb3ef241c12e1097c11d268247fa37f0e68.zip chromium_src-9f49afb3ef241c12e1097c11d268247fa37f0e68.tar.gz chromium_src-9f49afb3ef241c12e1097c11d268247fa37f0e68.tar.bz2 |
net: FileStream::Read/Write() to take IOBuffer* instead of char*
This will make it easier to use these functions.
BUG=72001
TEST=try bots
Review URL: http://codereview.chromium.org/9402014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122267 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/file_stream.h | 19 | ||||
-rw-r--r-- | net/base/file_stream_posix.cc | 98 | ||||
-rw-r--r-- | net/base/file_stream_unittest.cc | 108 | ||||
-rw-r--r-- | net/base/file_stream_win.cc | 145 | ||||
-rw-r--r-- | net/base/mock_file_stream.cc | 4 | ||||
-rw-r--r-- | net/base/mock_file_stream.h | 6 | ||||
-rw-r--r-- | net/url_request/url_request_file_job.cc | 2 |
7 files changed, 222 insertions, 160 deletions
diff --git a/net/base/file_stream.h b/net/base/file_stream.h index 7017f30..b9efb25 100644 --- a/net/base/file_stream.h +++ b/net/base/file_stream.h @@ -21,6 +21,8 @@ class FilePath; namespace net { +class IOBuffer; + // TODO(darin): Move this to a more generic location. // This explicit mapping matches both FILE_ on Windows and SEEK_ on Linux. enum Whence { @@ -87,9 +89,6 @@ class NET_EXPORT FileStream { // callback will be notified on the current thread (via the MessageLoop) // when the read has completed. // - // The memory pointed to by |buf| must remain valid until the callback is - // notified. TODO(satorux): Use IOBuffer instead of char*. - // // It is valid to destroy or close the file stream while there is an // asynchronous read in progress. That will cancel the read and allow // the buffer to be freed. @@ -98,7 +97,8 @@ class NET_EXPORT FileStream { // in-flight asynchronous operation. // // This method must not be called if the stream was opened WRITE_ONLY. - virtual int Read(char* buf, int buf_len, const CompletionCallback& callback); + virtual int Read(IOBuffer* buf, int buf_len, + const CompletionCallback& callback); // Call this method to read data from the current stream position // synchronously. Up to buf_len bytes will be copied into buf. (In @@ -129,9 +129,6 @@ class NET_EXPORT FileStream { // callback will be notified on the current thread (via the MessageLoop) // when the write has completed. // - // The memory pointed to by |buf| must remain valid until the callback - // is notified. TODO(satorux): Use IOBuffer instead of char*. - // // It is valid to destroy or close the file stream while there is an // asynchronous write in progress. That will cancel the write and allow // the buffer to be freed. @@ -140,7 +137,7 @@ class NET_EXPORT FileStream { // in-flight asynchronous operation. // // This method must not be called if the stream was opened READ_ONLY. - virtual int Write(const char* buf, int buf_len, + virtual int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback); // Call this method to write data at the current stream position @@ -181,12 +178,6 @@ class NET_EXPORT FileStream { void SetBoundNetLogSource(const net::BoundNetLog& owner_bound_net_log); private: - // Helper functions used to implement reads and writes. - int ReadInternal(char* buf, int buf_len, - const CompletionCallback& callback); - int WriteInternal(const char* buf, int buf_len, - const CompletionCallback& callback); - class AsyncContext; friend class AsyncContext; friend class FileStreamTest; diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc index ded0cfc..86bf728 100644 --- a/net/base/file_stream_posix.cc +++ b/net/base/file_stream_posix.cc @@ -28,6 +28,7 @@ #include "base/synchronization/waitable_event.h" #include "net/base/file_stream_metrics.h" #include "net/base/file_stream_net_log_parameters.h" +#include "net/base/io_buffer.h" #include "net/base/net_errors.h" #if defined(OS_ANDROID) @@ -167,11 +168,11 @@ class FileStream::AsyncContext { // These methods post synchronous read() and write() calls to a WorkerThread. void InitiateAsyncRead( - base::PlatformFile file, char* buf, int buf_len, + base::PlatformFile file, IOBuffer* buf, int buf_len, const net::BoundNetLog& bound_net_log, const CompletionCallback& callback); void InitiateAsyncWrite( - base::PlatformFile file, const char* buf, int buf_len, + base::PlatformFile file, IOBuffer* buf, int buf_len, const net::BoundNetLog& bound_net_log, const CompletionCallback& callback); @@ -197,6 +198,7 @@ class FileStream::AsyncContext { // The MessageLoopForIO that this AsyncContext is running on. MessageLoopForIO* const message_loop_; CompletionCallback callback_; // The user provided callback. + scoped_refptr<IOBuffer> in_flight_buf_; // This is used to synchronize between the AsyncContext destructor (which runs // on the IO thread and OnBackgroundIOCompleted() which runs on the WorkerPool @@ -238,17 +240,19 @@ FileStream::AsyncContext::~AsyncContext() { } void FileStream::AsyncContext::InitiateAsyncRead( - base::PlatformFile file, char* buf, int buf_len, + base::PlatformFile file, IOBuffer* buf, int buf_len, const net::BoundNetLog& bound_net_log, const CompletionCallback& callback) { DCHECK(callback_.is_null()); + DCHECK(!in_flight_buf_); callback_ = callback; + in_flight_buf_ = buf; // Hold until the async operation ends. base::WorkerPool::PostTask( FROM_HERE, base::Bind(&ReadFileTask, file, - buf, + buf->data(), buf_len, record_uma_, bound_net_log, @@ -258,17 +262,19 @@ void FileStream::AsyncContext::InitiateAsyncRead( } void FileStream::AsyncContext::InitiateAsyncWrite( - base::PlatformFile file, const char* buf, int buf_len, + base::PlatformFile file, IOBuffer* buf, int buf_len, const net::BoundNetLog& bound_net_log, const CompletionCallback& callback) { DCHECK(callback_.is_null()); + DCHECK(!in_flight_buf_); callback_ = callback; + in_flight_buf_ = buf; // Hold until the async operation ends. base::WorkerPool::PostTask( FROM_HERE, base::Bind(&WriteFileTask, file, - buf, + buf->data(), buf_len, record_uma_, bound_net_log, @@ -301,14 +307,17 @@ void FileStream::AsyncContext::RunAsynchronousCallback() { if (is_closing_) { callback_.Reset(); + in_flight_buf_ = NULL; return; } DCHECK(!callback_.is_null()); - CompletionCallback temp; - std::swap(temp, callback_); + CompletionCallback temp_callback = callback_; + callback_.Reset(); + scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; + in_flight_buf_ = NULL; background_io_completed_.Reset(); - temp.Run(result_); + temp_callback.Run(result_); } // FileStream ------------------------------------------------------------ @@ -440,18 +449,29 @@ int64 FileStream::Available() { } int FileStream::Read( - char* buf, int buf_len, const CompletionCallback& callback) { + IOBuffer* buf, int buf_len, const CompletionCallback& callback) { DCHECK(async_context_.get()); - return ReadInternal(buf, buf_len, callback); + + if (!IsOpen()) + return ERR_UNEXPECTED; + + // read(..., 0) will return 0, which indicates end-of-file. + DCHECK_GT(buf_len, 0); + DCHECK(open_flags_ & base::PLATFORM_FILE_READ); + + DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); + // Make sure we don't have a request in flight. + DCHECK(async_context_->callback().is_null()); + if (record_uma_) + async_context_->EnableErrorStatistics(); + async_context_->InitiateAsyncRead(file_, buf, buf_len, bound_net_log_, + callback); + return ERR_IO_PENDING; } int FileStream::ReadSync(char* buf, int buf_len) { DCHECK(!async_context_.get()); - return ReadInternal(buf, buf_len, CompletionCallback()); -} -int FileStream::ReadInternal( - char* buf, int buf_len, const CompletionCallback& callback) { if (!IsOpen()) return ERR_UNEXPECTED; @@ -459,18 +479,7 @@ int FileStream::ReadInternal( DCHECK_GT(buf_len, 0); DCHECK(open_flags_ & base::PLATFORM_FILE_READ); - if (async_context_.get()) { - DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); - // If we're in async, make sure we don't have a request in flight. - DCHECK(async_context_->callback().is_null()); - if (record_uma_) - async_context_->EnableErrorStatistics(); - async_context_->InitiateAsyncRead(file_, buf, buf_len, bound_net_log_, - callback); - return ERR_IO_PENDING; - } else { - return ReadFile(file_, buf, buf_len, record_uma_, bound_net_log_); - } + return ReadFile(file_, buf, buf_len, record_uma_, bound_net_log_); } int FileStream::ReadUntilComplete(char *buf, int buf_len) { @@ -495,37 +504,36 @@ int FileStream::ReadUntilComplete(char *buf, int buf_len) { } int FileStream::Write( - const char* buf, int buf_len, const CompletionCallback& callback) { + IOBuffer* buf, int buf_len, const CompletionCallback& callback) { DCHECK(async_context_.get()); - return WriteInternal(buf, buf_len, callback); + + // write(..., 0) will return 0, which indicates end-of-file. + DCHECK_GT(buf_len, 0); + + if (!IsOpen()) + return ERR_UNEXPECTED; + + DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); + // Make sure we don't have a request in flight. + DCHECK(async_context_->callback().is_null()); + if (record_uma_) + async_context_->EnableErrorStatistics(); + async_context_->InitiateAsyncWrite(file_, buf, buf_len, bound_net_log_, + callback); + return ERR_IO_PENDING; } int FileStream::WriteSync( const char* buf, int buf_len) { DCHECK(!async_context_.get()); - return WriteInternal(buf, buf_len, CompletionCallback()); -} -int FileStream::WriteInternal( - const char* buf, int buf_len, const CompletionCallback& callback) { // write(..., 0) will return 0, which indicates end-of-file. DCHECK_GT(buf_len, 0); if (!IsOpen()) return ERR_UNEXPECTED; - if (async_context_.get()) { - DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); - // If we're in async, make sure we don't have a request in flight. - DCHECK(async_context_->callback().is_null()); - if (record_uma_) - async_context_->EnableErrorStatistics(); - async_context_->InitiateAsyncWrite(file_, buf, buf_len, bound_net_log_, - callback); - return ERR_IO_PENDING; - } else { - return WriteFile(file_, buf, buf_len, record_uma_, bound_net_log_); - } + return WriteFile(file_, buf, buf_len, record_uma_, bound_net_log_); } int64 FileStream::Truncate(int64 bytes) { diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc index 44044f6..537e6b1 100644 --- a/net/base/file_stream_unittest.cc +++ b/net/base/file_stream_unittest.cc @@ -10,6 +10,7 @@ #include "base/message_loop.h" #include "base/path_service.h" #include "base/platform_file.h" +#include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,6 +23,13 @@ namespace { const char kTestData[] = "0123456789"; const int kTestDataSize = arraysize(kTestData) - 1; +// Creates an IOBufferWithSize that contains the kTestDataSize. +IOBufferWithSize* CreateTestDataBuffer() { + IOBufferWithSize* buf = new IOBufferWithSize(kTestDataSize); + memcpy(buf->data(), kTestData, kTestDataSize); + return buf; +} + } // namespace class FileStreamTest : public PlatformTest { @@ -197,15 +205,15 @@ TEST_F(FileStreamTest, AsyncRead) { std::string data_read; for (;;) { - char buf[4]; - rv = stream.Read(buf, arraysize(buf), callback.callback()); + scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); + rv = stream.Read(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LE(0, rv); if (rv <= 0) break; total_bytes_read += rv; - data_read.append(buf, rv); + data_read.append(buf->data(), rv); } EXPECT_EQ(file_size, total_bytes_read); EXPECT_EQ(kTestData, data_read); @@ -228,8 +236,8 @@ TEST_F(FileStreamTest, AsyncRead_EarlyClose) { TestCompletionCallback callback; - char buf[4]; - rv = stream.Read(buf, arraysize(buf), callback.callback()); + scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); + rv = stream.Read(buf, buf->size(), callback.callback()); stream.CloseSync(); if (rv < 0) { EXPECT_EQ(ERR_IO_PENDING, rv); @@ -237,7 +245,7 @@ TEST_F(FileStreamTest, AsyncRead_EarlyClose) { MessageLoop::current()->RunAllPending(); EXPECT_FALSE(callback.have_result()); } else { - EXPECT_EQ(std::string(kTestData, rv), std::string(buf, rv)); + EXPECT_EQ(std::string(kTestData, rv), std::string(buf->data(), rv)); } } @@ -301,15 +309,15 @@ TEST_F(FileStreamTest, AsyncRead_FromOffset) { std::string data_read; for (;;) { - char buf[4]; - rv = stream.Read(buf, arraysize(buf), callback.callback()); + scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); + rv = stream.Read(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LE(0, rv); if (rv <= 0) break; total_bytes_read += rv; - data_read.append(buf, rv); + data_read.append(buf->data(), rv); } EXPECT_EQ(file_size - kOffset, total_bytes_read); EXPECT_EQ(kTestData + kOffset, data_read); @@ -375,15 +383,18 @@ TEST_F(FileStreamTest, AsyncWrite) { TestCompletionCallback callback; int total_bytes_written = 0; + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + scoped_refptr<DrainableIOBuffer> drainable = + new DrainableIOBuffer(buf, buf->size()); while (total_bytes_written != kTestDataSize) { - rv = stream.Write(kTestData + total_bytes_written, - kTestDataSize - total_bytes_written, + rv = stream.Write(drainable, drainable->BytesRemaining(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LT(0, rv); if (rv <= 0) break; + drainable->DidConsume(rv); total_bytes_written += rv; } ok = file_util::GetFileSize(temp_file_path(), &file_size); @@ -405,11 +416,9 @@ TEST_F(FileStreamTest, AsyncWrite_EarlyClose) { EXPECT_EQ(0, file_size); TestCompletionCallback callback; - int total_bytes_written = 0; - rv = stream.Write(kTestData + total_bytes_written, - kTestDataSize - total_bytes_written, - callback.callback()); + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + rv = stream.Write(buf, buf->size(), callback.callback()); stream.CloseSync(); if (rv < 0) { EXPECT_EQ(ERR_IO_PENDING, rv); @@ -467,15 +476,18 @@ TEST_F(FileStreamTest, AsyncWrite_FromOffset) { TestCompletionCallback callback; int total_bytes_written = 0; + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + scoped_refptr<DrainableIOBuffer> drainable = + new DrainableIOBuffer(buf, buf->size()); while (total_bytes_written != kTestDataSize) { - rv = stream.Write(kTestData + total_bytes_written, - kTestDataSize - total_bytes_written, + rv = stream.Write(drainable, drainable->BytesRemaining(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LT(0, rv); if (rv <= 0) break; + drainable->DidConsume(rv); total_bytes_written += rv; } ok = file_util::GetFileSize(temp_file_path(), &file_size); @@ -591,30 +603,33 @@ TEST_F(FileStreamTest, BasicAsyncReadWrite) { std::string data_read; for (;;) { - char buf[4]; - rv = stream.Read(buf, arraysize(buf), callback.callback()); + scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); + rv = stream.Read(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LE(0, rv); if (rv <= 0) break; total_bytes_read += rv; - data_read.append(buf, rv); + data_read.append(buf->data(), rv); } EXPECT_EQ(file_size, total_bytes_read); EXPECT_TRUE(data_read == kTestData); int total_bytes_written = 0; + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + scoped_refptr<DrainableIOBuffer> drainable = + new DrainableIOBuffer(buf, buf->size()); while (total_bytes_written != kTestDataSize) { - rv = stream.Write(kTestData + total_bytes_written, - kTestDataSize - total_bytes_written, + rv = stream.Write(drainable, drainable->BytesRemaining(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LT(0, rv); if (rv <= 0) break; + drainable->DidConsume(rv); total_bytes_written += rv; } @@ -647,15 +662,18 @@ TEST_F(FileStreamTest, BasicAsyncWriteRead) { TestCompletionCallback callback; int total_bytes_written = 0; + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + scoped_refptr<DrainableIOBuffer> drainable = + new DrainableIOBuffer(buf, buf->size()); while (total_bytes_written != kTestDataSize) { - rv = stream.Write(kTestData + total_bytes_written, - kTestDataSize - total_bytes_written, + rv = stream.Write(drainable, drainable->BytesRemaining(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LT(0, rv); if (rv <= 0) break; + drainable->DidConsume(rv); total_bytes_written += rv; } @@ -668,15 +686,15 @@ TEST_F(FileStreamTest, BasicAsyncWriteRead) { std::string data_read; for (;;) { - char buf[4]; - rv = stream.Read(buf, arraysize(buf), callback.callback()); + scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); + rv = stream.Read(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LE(0, rv); if (rv <= 0) break; total_bytes_read += rv; - data_read.append(buf, rv); + data_read.append(buf->data(), rv); } stream.CloseSync(); @@ -705,7 +723,10 @@ class TestWriteReadCompletionCallback { total_bytes_read_(total_bytes_read), data_read_(data_read), callback_(base::Bind(&TestWriteReadCompletionCallback::OnComplete, - base::Unretained(this))) {} + base::Unretained(this))), + test_data_(CreateTestDataBuffer()), + drainable_(new DrainableIOBuffer(test_data_, kTestDataSize)) { + } int WaitForResult() { DCHECK(!waiting_for_result_); @@ -733,11 +754,11 @@ class TestWriteReadCompletionCallback { std::string data_read; TestWriteReadCompletionCallback callback( stream_, &total_bytes_written, &total_bytes_read, &data_read); - rv = stream_->Write(kTestData + *total_bytes_written_, - kTestDataSize - *total_bytes_written_, + rv = stream_->Write(drainable_, drainable_->BytesRemaining(), callback.callback()); DCHECK_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); + drainable_->DidConsume(total_bytes_written); *total_bytes_written_ += total_bytes_written; *total_bytes_read_ += total_bytes_read; *data_read_ += data_read; @@ -746,8 +767,8 @@ class TestWriteReadCompletionCallback { TestCompletionCallback callback; for (;;) { - char buf[4]; - rv = stream_->Read(buf, arraysize(buf), callback.callback()); + scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4); + rv = stream_->Read(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) { MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); rv = callback.WaitForResult(); @@ -756,7 +777,7 @@ class TestWriteReadCompletionCallback { if (rv <= 0) break; *total_bytes_read_ += rv; - data_read_->append(buf, rv); + data_read_->append(buf->data(), rv); } } @@ -774,6 +795,8 @@ class TestWriteReadCompletionCallback { int* total_bytes_read_; std::string* data_read_; const CompletionCallback callback_; + scoped_refptr<IOBufferWithSize> test_data_; + scoped_refptr<DrainableIOBuffer> drainable_; DISALLOW_COPY_AND_ASSIGN(TestWriteReadCompletionCallback); }; @@ -803,9 +826,8 @@ TEST_F(FileStreamTest, AsyncWriteRead) { TestWriteReadCompletionCallback callback(&stream, &total_bytes_written, &total_bytes_read, &data_read); - rv = stream.Write(kTestData + total_bytes_written, - kTestDataSize - static_cast<int>(total_bytes_written), - callback.callback()); + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + rv = stream.Write(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); EXPECT_LT(0, rv); @@ -832,7 +854,10 @@ class TestWriteCloseCompletionCallback { stream_(stream), total_bytes_written_(total_bytes_written), callback_(base::Bind(&TestWriteCloseCompletionCallback::OnComplete, - base::Unretained(this))) {} + base::Unretained(this))), + test_data_(CreateTestDataBuffer()), + drainable_(new DrainableIOBuffer(test_data_, kTestDataSize)) { + } int WaitForResult() { DCHECK(!waiting_for_result_); @@ -858,11 +883,11 @@ class TestWriteCloseCompletionCallback { // Recurse to finish writing all data. int total_bytes_written = 0; TestWriteCloseCompletionCallback callback(stream_, &total_bytes_written); - rv = stream_->Write(kTestData + *total_bytes_written_, - kTestDataSize - *total_bytes_written_, + rv = stream_->Write(drainable_, drainable_->BytesRemaining(), callback.callback()); DCHECK_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); + drainable_->DidConsume(total_bytes_written); *total_bytes_written_ += total_bytes_written; } else { // We're done writing all data. Close the file. stream_->CloseSync(); @@ -880,6 +905,8 @@ class TestWriteCloseCompletionCallback { FileStream* stream_; int* total_bytes_written_; const CompletionCallback callback_; + scoped_refptr<IOBufferWithSize> test_data_; + scoped_refptr<DrainableIOBuffer> drainable_; DISALLOW_COPY_AND_ASSIGN(TestWriteCloseCompletionCallback); }; @@ -906,7 +933,8 @@ TEST_F(FileStreamTest, AsyncWriteClose) { int total_bytes_written = 0; TestWriteCloseCompletionCallback callback(&stream, &total_bytes_written); - rv = stream.Write(kTestData, kTestDataSize, callback.callback()); + scoped_refptr<IOBufferWithSize> buf = CreateTestDataBuffer(); + rv = stream.Write(buf, buf->size(), callback.callback()); if (rv == ERR_IO_PENDING) total_bytes_written = callback.WaitForResult(); EXPECT_LT(0, total_bytes_written); diff --git a/net/base/file_stream_win.cc b/net/base/file_stream_win.cc index e111733..aa2b045 100644 --- a/net/base/file_stream_win.cc +++ b/net/base/file_stream_win.cc @@ -13,6 +13,7 @@ #include "base/threading/thread_restrictions.h" #include "net/base/file_stream_metrics.h" #include "net/base/file_stream_net_log_parameters.h" +#include "net/base/io_buffer.h" #include "net/base/net_errors.h" namespace net { @@ -69,7 +70,8 @@ class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { } ~AsyncContext(); - void IOCompletionIsPending(const CompletionCallback& callback); + void IOCompletionIsPending(const CompletionCallback& callback, + IOBuffer* buf); OVERLAPPED* overlapped() { return &context_.overlapped; } const CompletionCallback& callback() const { return callback_; } @@ -86,6 +88,7 @@ class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { MessageLoopForIO::IOContext context_; CompletionCallback callback_; + scoped_refptr<IOBuffer> in_flight_buf_; bool is_closing_; bool record_uma_; const net::BoundNetLog bound_net_log_; @@ -108,9 +111,11 @@ FileStream::AsyncContext::~AsyncContext() { } void FileStream::AsyncContext::IOCompletionIsPending( - const CompletionCallback& callback) { + const CompletionCallback& callback, + IOBuffer* buf) { DCHECK(callback_.is_null()); callback_ = callback; + in_flight_buf_ = buf; // Hold until the async operation ends. } void FileStream::AsyncContext::OnIOCompleted( @@ -120,6 +125,7 @@ void FileStream::AsyncContext::OnIOCompleted( if (is_closing_) { callback_.Reset(); + in_flight_buf_ = NULL; return; } @@ -132,9 +138,11 @@ void FileStream::AsyncContext::OnIOCompleted( if (bytes_read) IncrementOffset(&context->overlapped, bytes_read); - CompletionCallback temp; - std::swap(temp, callback_); - temp.Run(result); + CompletionCallback temp_callback = callback_; + callback_.Reset(); + scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; + in_flight_buf_ = NULL; + temp_callback.Run(result); } // FileStream ------------------------------------------------------------ @@ -277,41 +285,27 @@ int64 FileStream::Available() { } int FileStream::Read( - char* buf, int buf_len, const CompletionCallback& callback) { + IOBuffer* buf, int buf_len, const CompletionCallback& callback) { DCHECK(async_context_.get()); - return ReadInternal(buf, buf_len, callback); -} - -int FileStream::ReadSync(char* buf, int buf_len) { - DCHECK(!async_context_.get()); - return ReadInternal(buf, buf_len, CompletionCallback()); -} -int FileStream::ReadInternal( - char* buf, int buf_len, const CompletionCallback& callback) { if (!IsOpen()) return ERR_UNEXPECTED; DCHECK(open_flags_ & base::PLATFORM_FILE_READ); OVERLAPPED* overlapped = NULL; - if (async_context_.get()) { - DCHECK(!callback.is_null()); - DCHECK(async_context_->callback().is_null()); - overlapped = async_context_->overlapped(); - async_context_->set_error_source(FILE_ERROR_SOURCE_READ); - } else { - DCHECK(callback.is_null()); - base::ThreadRestrictions::AssertIOAllowed(); - } + DCHECK(!callback.is_null()); + DCHECK(async_context_->callback().is_null()); + overlapped = async_context_->overlapped(); + async_context_->set_error_source(FILE_ERROR_SOURCE_READ); - int rv; + int rv = 0; DWORD bytes_read; - if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) { + if (!ReadFile(file_, buf->data(), buf_len, &bytes_read, overlapped)) { DWORD error = GetLastError(); - if (async_context_.get() && error == ERROR_IO_PENDING) { - async_context_->IOCompletionIsPending(callback); + if (error == ERROR_IO_PENDING) { + async_context_->IOCompletionIsPending(callback, buf); rv = ERR_IO_PENDING; } else if (error == ERROR_HANDLE_EOF) { rv = 0; // Report EOF by returning 0 bytes read. @@ -323,7 +317,7 @@ int FileStream::ReadInternal( bound_net_log_); } } else if (overlapped) { - async_context_->IOCompletionIsPending(callback); + async_context_->IOCompletionIsPending(callback, buf); rv = ERR_IO_PENDING; } else { rv = static_cast<int>(bytes_read); @@ -331,6 +325,35 @@ int FileStream::ReadInternal( return rv; } +int FileStream::ReadSync(char* buf, int buf_len) { + DCHECK(!async_context_.get()); + base::ThreadRestrictions::AssertIOAllowed(); + + if (!IsOpen()) + return ERR_UNEXPECTED; + + DCHECK(open_flags_ & base::PLATFORM_FILE_READ); + + int rv = 0; + + DWORD bytes_read; + if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) { + DWORD error = GetLastError(); + if (error == ERROR_HANDLE_EOF) { + rv = 0; // Report EOF by returning 0 bytes read. + } else { + LOG(WARNING) << "ReadFile failed: " << error; + rv = RecordAndMapError(error, + FILE_ERROR_SOURCE_READ, + record_uma_, + bound_net_log_); + } + } else { + rv = static_cast<int>(bytes_read); + } + return rv; +} + int FileStream::ReadUntilComplete(char *buf, int buf_len) { int to_read = buf_len; int bytes_total = 0; @@ -353,41 +376,26 @@ int FileStream::ReadUntilComplete(char *buf, int buf_len) { } int FileStream::Write( - const char* buf, int buf_len, const CompletionCallback& callback) { + IOBuffer* buf, int buf_len, const CompletionCallback& callback) { DCHECK(async_context_.get()); - return WriteInternal(buf, buf_len, callback); -} - -int FileStream::WriteSync( - const char* buf, int buf_len) { - DCHECK(!async_context_.get()); - return WriteInternal(buf, buf_len, CompletionCallback()); -} -int FileStream::WriteInternal( - const char* buf, int buf_len, const CompletionCallback& callback) { if (!IsOpen()) return ERR_UNEXPECTED; DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); OVERLAPPED* overlapped = NULL; - if (async_context_.get()) { - DCHECK(!callback.is_null()); - DCHECK(async_context_->callback().is_null()); - overlapped = async_context_->overlapped(); - async_context_->set_error_source(FILE_ERROR_SOURCE_WRITE); - } else { - DCHECK(callback.is_null()); - base::ThreadRestrictions::AssertIOAllowed(); - } - - int rv; - DWORD bytes_written; - if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { + DCHECK(!callback.is_null()); + DCHECK(async_context_->callback().is_null()); + overlapped = async_context_->overlapped(); + async_context_->set_error_source(FILE_ERROR_SOURCE_WRITE); + + int rv = 0; + DWORD bytes_written = 0; + if (!WriteFile(file_, buf->data(), buf_len, &bytes_written, overlapped)) { DWORD error = GetLastError(); - if (async_context_.get() && error == ERROR_IO_PENDING) { - async_context_->IOCompletionIsPending(callback); + if (error == ERROR_IO_PENDING) { + async_context_->IOCompletionIsPending(callback, buf); rv = ERR_IO_PENDING; } else { LOG(WARNING) << "WriteFile failed: " << error; @@ -397,7 +405,7 @@ int FileStream::WriteInternal( bound_net_log_); } } else if (overlapped) { - async_context_->IOCompletionIsPending(callback); + async_context_->IOCompletionIsPending(callback, buf); rv = ERR_IO_PENDING; } else { rv = static_cast<int>(bytes_written); @@ -405,6 +413,31 @@ int FileStream::WriteInternal( return rv; } +int FileStream::WriteSync( + const char* buf, int buf_len) { + DCHECK(!async_context_.get()); + base::ThreadRestrictions::AssertIOAllowed(); + + if (!IsOpen()) + return ERR_UNEXPECTED; + + DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); + + int rv = 0; + DWORD bytes_written = 0; + if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) { + DWORD error = GetLastError(); + LOG(WARNING) << "WriteFile failed: " << error; + rv = RecordAndMapError(error, + FILE_ERROR_SOURCE_WRITE, + record_uma_, + bound_net_log_); + } else { + rv = static_cast<int>(bytes_written); + } + return rv; +} + int FileStream::Flush() { base::ThreadRestrictions::AssertIOAllowed(); diff --git a/net/base/mock_file_stream.cc b/net/base/mock_file_stream.cc index e87491f..419f65f 100644 --- a/net/base/mock_file_stream.cc +++ b/net/base/mock_file_stream.cc @@ -21,7 +21,7 @@ int64 MockFileStream::Available() { return ReturnError64(FileStream::Available()); } -int MockFileStream::Read(char* buf, +int MockFileStream::Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { return ReturnError(FileStream::Read(buf, buf_len, callback)); @@ -35,7 +35,7 @@ int MockFileStream::ReadUntilComplete(char *buf, int buf_len) { return ReturnError(FileStream::ReadUntilComplete(buf, buf_len)); } -int MockFileStream::Write(const char* buf, +int MockFileStream::Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback) { return ReturnError(FileStream::Write(buf, buf_len, callback)); diff --git a/net/base/mock_file_stream.h b/net/base/mock_file_stream.h index 8424e51..61c9db8 100644 --- a/net/base/mock_file_stream.h +++ b/net/base/mock_file_stream.h @@ -16,6 +16,8 @@ namespace net { +class IOBuffer; + namespace testing { class MockFileStream : public net::FileStream { @@ -30,12 +32,12 @@ class MockFileStream : public net::FileStream { virtual int OpenSync(const FilePath& path, int open_flags) OVERRIDE; virtual int64 Seek(net::Whence whence, int64 offset) OVERRIDE; virtual int64 Available() OVERRIDE; - virtual int Read(char* buf, + virtual int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) OVERRIDE; virtual int ReadSync(char* buf, int buf_len) OVERRIDE; virtual int ReadUntilComplete(char *buf, int buf_len) OVERRIDE; - virtual int Write(const char* buf, + virtual int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback) OVERRIDE; virtual int WriteSync(const char* buf, int buf_len) OVERRIDE; diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index fa6d6a2..70826e5 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc @@ -187,7 +187,7 @@ bool URLRequestFileJob::ReadRawData(IOBuffer* dest, int dest_size, return true; } - int rv = stream_.Read(dest->data(), dest_size, + int rv = stream_.Read(dest, dest_size, base::Bind(&URLRequestFileJob::DidRead, base::Unretained(this))); if (rv >= 0) { |