summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorvandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-14 17:35:37 +0000
committervandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-14 17:35:37 +0000
commitc19c715aaa359f0d99fa788051989ce2e1d4f89a (patch)
tree30d7fca8bac962eb0c4b7405a19deb7fd8293bf2 /net
parent434171fd3e3d28404c66416a4c98d492ea975b3f (diff)
downloadchromium_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.cc25
-rw-r--r--net/base/io_buffer.h79
-rw-r--r--net/disk_cache/mem_entry_impl.cc46
-rw-r--r--net/disk_cache/sparse_control.cc4
-rw-r--r--net/disk_cache/sparse_control.h4
-rw-r--r--net/ftp/ftp_network_transaction.cc17
-rw-r--r--net/ftp/ftp_network_transaction.h6
-rw-r--r--net/socket_stream/socket_stream.cc4
-rw-r--r--net/socket_stream/socket_stream.h2
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_;