diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-14 17:35:37 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-14 17:35:37 +0000 |
commit | c19c715aaa359f0d99fa788051989ce2e1d4f89a (patch) | |
tree | 30d7fca8bac962eb0c4b7405a19deb7fd8293bf2 /net | |
parent | 434171fd3e3d28404c66416a4c98d492ea975b3f (diff) | |
download | chromium_src-c19c715aaa359f0d99fa788051989ce2e1d4f89a.zip chromium_src-c19c715aaa359f0d99fa788051989ce2e1d4f89a.tar.gz chromium_src-c19c715aaa359f0d99fa788051989ce2e1d4f89a.tar.bz2 |
A couple new io buffers that encapsulate more data and are therefore easier to use and easier to reason about. Inspired by RequestHeaders and ResponseHeaders in http_network_transaction.h Separated out of the refactoring of HttpNetworkTransaction to support pipelining. (http://codereview.chromium.org/249031)
BUG=13289
TEST=none
Review URL: http://codereview.chromium.org/264025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28978 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/io_buffer.cc | 25 | ||||
-rw-r--r-- | net/base/io_buffer.h | 79 | ||||
-rw-r--r-- | net/disk_cache/mem_entry_impl.cc | 46 | ||||
-rw-r--r-- | net/disk_cache/sparse_control.cc | 4 | ||||
-rw-r--r-- | net/disk_cache/sparse_control.h | 4 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction.cc | 17 | ||||
-rw-r--r-- | net/ftp/ftp_network_transaction.h | 6 | ||||
-rw-r--r-- | net/socket_stream/socket_stream.cc | 4 | ||||
-rw-r--r-- | net/socket_stream/socket_stream.h | 2 |
9 files changed, 123 insertions, 64 deletions
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc index eb7094b..d348f37 100644 --- a/net/base/io_buffer.cc +++ b/net/base/io_buffer.cc @@ -12,9 +12,28 @@ IOBuffer::IOBuffer(int buffer_size) { DCHECK(buffer_size > 0); data_ = new char[buffer_size]; } -void ReusedIOBuffer::SetOffset(int offset) { - DCHECK(offset >= 0 && offset < size_); - data_ = base_->data() + offset; + +void DrainableIOBuffer::SetOffset(int bytes) { + DCHECK(bytes >= 0 && bytes <= size_); + used_ = bytes; + data_ = base_->data() + used_; +} + +void GrowableIOBuffer::set_capacity(int capacity) { + DCHECK_GE(capacity, 0); + real_data_.reset(static_cast<char*>(realloc(real_data_.release(), capacity))); + capacity_ = capacity; + CHECK(real_data_.get() != NULL || capacity == 0); + if (offset_ > capacity) + set_offset(capacity); + else + set_offset(offset_); // The pointer may have changed. +} + +void GrowableIOBuffer::set_offset(int offset) { + DCHECK(offset >= 0 && offset <= capacity_); + offset_ = offset; + data_ = real_data_.get() + offset; } } // namespace net diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h index ac79644..eaf3a39 100644 --- a/net/base/io_buffer.h +++ b/net/base/io_buffer.h @@ -5,7 +5,10 @@ #ifndef NET_BASE_IO_BUFFER_H_ #define NET_BASE_IO_BUFFER_H_ +#include <string> + #include "base/ref_counted.h" +#include "base/scoped_ptr.h" namespace net { @@ -30,7 +33,7 @@ class IOBuffer : public base::RefCountedThreadSafe<IOBuffer> { // This version stores the size of the buffer so that the creator of the object // doesn't have to keep track of that value. -// NOTE: This doesn't mean that we want to stop sending the size as an explictit +// NOTE: This doesn't mean that we want to stop sending the size as an explicit // argument to IO functions. Please keep using IOBuffer* for API declarations. class IOBufferWithSize : public IOBuffer { public: @@ -43,24 +46,80 @@ class IOBufferWithSize : public IOBuffer { int size_; }; -// This version allows the caller to do multiple IO operations reusing a given -// IOBuffer. We don't own data_, we simply make it point to the buffer of the -// passed in IOBuffer, plus the desired offset. -class ReusedIOBuffer : public IOBuffer { +// This is a read only IOBuffer. The data is stored in a string and +// the IOBuffer interface does not provide a proper way to modify it. +class StringIOBuffer : public IOBuffer { public: - ReusedIOBuffer(IOBuffer* base, int size) - : IOBuffer(base->data()), base_(base), size_(size) {} - ~ReusedIOBuffer() { - // We don't really own a buffer. + explicit StringIOBuffer(const std::string& s) + : IOBuffer(static_cast<char*>(NULL)), + string_data_(s) { + data_ = const_cast<char*>(string_data_.data()); + } + ~StringIOBuffer() { + // We haven't allocated the buffer, so remove it before the base class + // destructor tries to delete[] it. data_ = NULL; } + int size() const { return string_data_.size(); } + + private: + std::string string_data_; +}; + +// This version wraps an existing IOBuffer and provides convenient functions +// to progressively read all the data. +class DrainableIOBuffer : public IOBuffer { + public: + DrainableIOBuffer(IOBuffer* base, int size) + : IOBuffer(base->data()), base_(base), size_(size), used_(0) {} + ~DrainableIOBuffer() { + // The buffer is owned by the |base_| instance. + data_ = NULL; + } + + // DidConsume() changes the |data_| pointer so that |data_| always points + // to the first unconsumed byte. + void DidConsume(int bytes) { SetOffset(used_ + bytes); } + + // Returns the number of unconsumed bytes. + int BytesRemaining() const { return size_ - used_; } + + // Returns the number of consumed bytes. + int BytesConsumed() const { return used_; } + + // Seeks to an arbitrary point in the buffer. The notion of bytes consumed + // and remaining are updated appropriately. + void SetOffset(int bytes); + int size() const { return size_; } - void SetOffset(int offset); private: scoped_refptr<IOBuffer> base_; int size_; + int used_; +}; + +// This version provides a resizable buffer and a changeable offset. +class GrowableIOBuffer : public IOBuffer { + public: + GrowableIOBuffer() : IOBuffer(), capacity_(0), offset_(0) {} + ~GrowableIOBuffer() { data_ = NULL; } + + int capacity() { return capacity_; } + void set_capacity(int capacity); + + // |offset| moves the |data_| pointer, allowing "seeking" in the data. + int offset() { return offset_; } + void set_offset(int offset); + + int RemainingCapacity() { return capacity_ - offset_; } + char* StartOfBuffer() { return real_data_.get(); } + + private: + scoped_ptr_malloc<char> real_data_; + int capacity_; + int offset_; }; // This class allows the creation of a temporary IOBuffer that doesn't really diff --git a/net/disk_cache/mem_entry_impl.cc b/net/disk_cache/mem_entry_impl.cc index 144e33f..a970070 100644 --- a/net/disk_cache/mem_entry_impl.cc +++ b/net/disk_cache/mem_entry_impl.cc @@ -172,29 +172,26 @@ int MemEntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, return net::ERR_INVALID_ARGUMENT; // We will keep using this buffer and adjust the offset in this buffer. - scoped_refptr<net::ReusedIOBuffer> io_buf = new net::ReusedIOBuffer(buf, - buf_len); - - // Counts the number of bytes read. - int bytes_read = 0; + scoped_refptr<net::DrainableIOBuffer> io_buf = + new net::DrainableIOBuffer(buf, buf_len); // Iterate until we have read enough. - while (bytes_read < buf_len) { - MemEntryImpl* child = OpenChild(offset + bytes_read, false); + while (io_buf->BytesRemaining()) { + MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), false); // No child present for that offset. if (!child) break; // We then need to prepare the child offset and len. - int child_offset = ToChildOffset(offset + bytes_read); + int child_offset = ToChildOffset(offset + io_buf->BytesConsumed()); // If we are trying to read from a position that the child entry has no data // we should stop. if (child_offset < child->child_first_pos_) break; int ret = child->ReadData(kSparseData, child_offset, io_buf, - buf_len - bytes_read, NULL); + io_buf->BytesRemaining(), NULL); // If we encounter an error in one entry, return immediately. if (ret < 0) @@ -203,15 +200,12 @@ int MemEntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, break; // Increment the counter by number of bytes read in the child entry. - bytes_read += ret; - // And also adjust the buffer's offset. - if (bytes_read < buf_len) - io_buf->SetOffset(bytes_read); + io_buf->DidConsume(ret); } UpdateRank(false); - return bytes_read; + return io_buf->BytesConsumed(); } int MemEntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, @@ -224,22 +218,20 @@ int MemEntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, if (offset < 0 || buf_len < 0) return net::ERR_INVALID_ARGUMENT; - scoped_refptr<net::ReusedIOBuffer> io_buf = new net::ReusedIOBuffer(buf, - buf_len); - // Counter for amount of bytes written. - int bytes_written = 0; + scoped_refptr<net::DrainableIOBuffer> io_buf = + new net::DrainableIOBuffer(buf, buf_len); // This loop walks through child entries continuously starting from |offset| // and writes blocks of data (of maximum size kMaxSparseEntrySize) into each // child entry until all |buf_len| bytes are written. The write operation can // start in the middle of an entry. - while (bytes_written < buf_len) { - MemEntryImpl* child = OpenChild(offset + bytes_written, true); - int child_offset = ToChildOffset(offset + bytes_written); + while (io_buf->BytesRemaining()) { + MemEntryImpl* child = OpenChild(offset + io_buf->BytesConsumed(), true); + int child_offset = ToChildOffset(offset + io_buf->BytesConsumed()); // Find the right amount to write, this evaluates the remaining bytes to // write and remaining capacity of this child entry. - int write_len = std::min(buf_len - bytes_written, + int write_len = std::min(static_cast<int>(io_buf->BytesRemaining()), kMaxSparseEntrySize - child_offset); // Keep a record of the last byte position (exclusive) in the child. @@ -262,17 +254,13 @@ int MemEntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len, if (data_size != child_offset) child->child_first_pos_ = child_offset; - // Increment the counter. - bytes_written += ret; - - // And adjust the offset in the IO buffer. - if (bytes_written < buf_len) - io_buf->SetOffset(bytes_written); + // Adjust the offset in the IO buffer. + io_buf->DidConsume(ret); } UpdateRank(true); - return bytes_written; + return io_buf->BytesConsumed(); } int MemEntryImpl::GetAvailableRange(int64 offset, int len, int64* start) { diff --git a/net/disk_cache/sparse_control.cc b/net/disk_cache/sparse_control.cc index 3c1dd8c..fb304be 100644 --- a/net/disk_cache/sparse_control.cc +++ b/net/disk_cache/sparse_control.cc @@ -185,7 +185,7 @@ int SparseControl::StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf, // Copy the operation parameters. operation_ = op; offset_ = offset; - user_buf_ = buf ? new net::ReusedIOBuffer(buf, buf_len) : NULL; + user_buf_ = buf ? new net::DrainableIOBuffer(buf, buf_len) : NULL; buf_len_ = buf_len; user_callback_ = callback; @@ -693,7 +693,7 @@ void SparseControl::DoChildIOCompleted(int result) { // We'll be reusing the user provided buffer for the next chunk. if (buf_len_ && user_buf_) - user_buf_->SetOffset(result_); + user_buf_->DidConsume(result); } void SparseControl::OnChildIOCompleted(int result) { diff --git a/net/disk_cache/sparse_control.h b/net/disk_cache/sparse_control.h index 24f5446..0005f58 100644 --- a/net/disk_cache/sparse_control.h +++ b/net/disk_cache/sparse_control.h @@ -16,7 +16,7 @@ namespace net { class IOBuffer; -class ReusedIOBuffer; +class DrainableIOBuffer; } namespace disk_cache { @@ -163,7 +163,7 @@ class SparseControl { net::CompletionCallback* user_callback_; std::vector<net::CompletionCallback*> abort_callbacks_; int64 offset_; // Current sparse offset. - scoped_refptr<net::ReusedIOBuffer> user_buf_; + scoped_refptr<net::DrainableIOBuffer> user_buf_; int buf_len_; // Bytes to read or write. int child_offset_; // Offset to use for the current child. int child_len_; // Bytes to read or write for this child. diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index 79ad77e..d4820b1 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc @@ -59,7 +59,6 @@ FtpNetworkTransaction::FtpNetworkTransaction( ctrl_response_buffer_(new FtpCtrlResponseBuffer()), read_data_buf_len_(0), file_data_len_(0), - write_command_buf_written_(0), last_error_(OK), system_type_(SYSTEM_TYPE_UNKNOWN), retr_failed_(false), @@ -188,8 +187,8 @@ int FtpNetworkTransaction::SendFtpCommand(const std::string& command, command_sent_ = cmd; write_command_buf_ = new IOBufferWithSize(command.length() + 2); - write_buf_ = new ReusedIOBuffer(write_command_buf_, - write_command_buf_->size()); + write_buf_ = new DrainableIOBuffer(write_command_buf_, + write_command_buf_->size()); memcpy(write_command_buf_->data(), command.data(), command.length()); memcpy(write_command_buf_->data() + command.length(), kCRLF, 2); @@ -300,7 +299,8 @@ void FtpNetworkTransaction::ResetStateForRestart() { read_data_buf_ = NULL; read_data_buf_len_ = 0; file_data_len_ = 0; - write_command_buf_written_ = 0; + if (write_buf_) + write_buf_->SetOffset(0); last_error_ = OK; retr_failed_ = false; data_connection_port_ = 0; @@ -539,10 +539,8 @@ int FtpNetworkTransaction::DoCtrlReadComplete(int result) { int FtpNetworkTransaction::DoCtrlWrite() { next_state_ = STATE_CTRL_WRITE_COMPLETE; - write_buf_->SetOffset(write_command_buf_written_); - int bytes_to_write = write_command_buf_->size() - write_command_buf_written_; return ctrl_socket_->Write(write_buf_, - bytes_to_write, + write_buf_->BytesRemaining(), &io_callback_); } @@ -550,12 +548,11 @@ int FtpNetworkTransaction::DoCtrlWriteComplete(int result) { if (result < 0) return result; - write_command_buf_written_ += result; - if (write_command_buf_written_ == write_command_buf_->size()) { + write_buf_->DidConsume(result); + if (write_buf_->BytesRemaining() == 0) { // Clear the write buffer. write_buf_ = NULL; write_command_buf_ = NULL; - write_command_buf_written_ = 0; next_state_ = STATE_CTRL_READ; } else { diff --git a/net/ftp/ftp_network_transaction.h b/net/ftp/ftp_network_transaction.h index e621a9b..7a3c3cc 100644 --- a/net/ftp/ftp_network_transaction.h +++ b/net/ftp/ftp_network_transaction.h @@ -192,11 +192,7 @@ class FtpNetworkTransaction : public FtpTransaction { // Buffer passed to the Write method of control socket. It actually writes // to the write_command_buf_ at correct offset. - scoped_refptr<ReusedIOBuffer> write_buf_; - - // Number of bytes from write_command_buf_ that we've already sent to the - // server. - int write_command_buf_written_; + scoped_refptr<DrainableIOBuffer> write_buf_; int last_error_; diff --git a/net/socket_stream/socket_stream.cc b/net/socket_stream/socket_stream.cc index 7308b53..a05bf80 100644 --- a/net/socket_stream/socket_stream.cc +++ b/net/socket_stream/socket_stream.cc @@ -577,10 +577,10 @@ int SocketStream::DoReadWrite(int result) { } } if (write_buf_ && !current_write_buf_) { - current_write_buf_ = new ReusedIOBuffer(write_buf_, write_buf_size_); + current_write_buf_ = new DrainableIOBuffer(write_buf_, write_buf_size_); current_write_buf_->SetOffset(write_buf_offset_); result = socket_->Write(current_write_buf_, - write_buf_size_ - write_buf_offset_, + current_write_buf_->BytesRemaining(), &write_callback_); if (result > 0) { DidSendData(result); diff --git a/net/socket_stream/socket_stream.h b/net/socket_stream/socket_stream.h index 13f8680..2a3dcb2 100644 --- a/net/socket_stream/socket_stream.h +++ b/net/socket_stream/socket_stream.h @@ -241,7 +241,7 @@ class SocketStream : public base::RefCountedThreadSafe<SocketStream> { // for Write operation, that is, |current_write_buf_| is // |write_buf_| + |write_buf_offset_|. scoped_refptr<IOBuffer> write_buf_; - scoped_refptr<ReusedIOBuffer> current_write_buf_; + scoped_refptr<DrainableIOBuffer> current_write_buf_; int write_buf_offset_; int write_buf_size_; PendingDataQueue pending_write_bufs_; |